From d90e91b58c592155171c7ccc70e8172a5609f913 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 22 Dec 2016 16:12:38 +0800 Subject: IntelFrameworkModulePkg: Move to new location Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../Bus/Isa/IsaBusDxe/ComponentName.c | 182 + .../Bus/Isa/IsaBusDxe/ComponentName.h | 148 + .../Bus/Isa/IsaBusDxe/InternalIsaBus.h | 297 ++ .../Bus/Isa/IsaBusDxe/InternalIsaIo.h | 331 ++ .../Bus/Isa/IsaBusDxe/IsaBus.c | 673 +++ .../Bus/Isa/IsaBusDxe/IsaBusDxe.inf | 73 + .../Bus/Isa/IsaBusDxe/IsaBusDxe.uni | Bin 0 -> 2658 bytes .../Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni | Bin 0 -> 1336 bytes .../Bus/Isa/IsaBusDxe/IsaIo.c | 1463 +++++++ .../Bus/Isa/IsaFloppyDxe/ComponentName.c | 249 ++ .../Bus/Isa/IsaFloppyDxe/ComponentName.h | 146 + .../Bus/Isa/IsaFloppyDxe/IsaFloppy.c | 515 +++ .../Bus/Isa/IsaFloppyDxe/IsaFloppy.h | 1093 +++++ .../Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c | 375 ++ .../Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c | 1398 +++++++ .../Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf | 78 + .../Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni | Bin 0 -> 2444 bytes .../Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni | Bin 0 -> 1348 bytes .../Bus/Isa/IsaFloppyPei/Fdc.h | 235 ++ .../Bus/Isa/IsaFloppyPei/FloppyPeim.c | 1759 ++++++++ .../Bus/Isa/IsaFloppyPei/FloppyPeim.h | 246 ++ .../Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf | 73 + .../Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni | Bin 0 -> 2348 bytes .../Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni | Bin 0 -> 1358 bytes .../Bus/Isa/IsaIoDxe/ComponentName.c | 182 + .../Bus/Isa/IsaIoDxe/ComponentName.h | 148 + .../Bus/Isa/IsaIoDxe/IsaDriver.c | 326 ++ .../Bus/Isa/IsaIoDxe/IsaDriver.h | 263 ++ .../Bus/Isa/IsaIoDxe/IsaIo.c | 1803 ++++++++ .../Bus/Isa/IsaIoDxe/IsaIo.h | 331 ++ .../Bus/Isa/IsaIoDxe/IsaIoDxe.inf | 71 + .../Bus/Isa/IsaIoDxe/IsaIoDxe.uni | Bin 0 -> 2414 bytes .../Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni | Bin 0 -> 1334 bytes .../Bus/Isa/IsaSerialDxe/ComponentName.c | 272 ++ .../Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf | 80 + .../Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni | Bin 0 -> 2094 bytes .../Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni | Bin 0 -> 1366 bytes .../Bus/Isa/IsaSerialDxe/Serial.c | 2038 +++++++++ .../Bus/Isa/IsaSerialDxe/Serial.h | 842 ++++ .../Bus/Isa/Ps2KeyboardDxe/ComponentName.c | 372 ++ .../Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c | 1908 +++++++++ .../Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c | 683 +++ .../Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c | 642 +++ .../Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h | 550 +++ .../Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni | Bin 0 -> 1928 bytes .../Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni | Bin 0 -> 1358 bytes .../Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf | 85 + .../Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c | 923 +++++ .../Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h | 435 ++ .../Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c | 241 ++ .../Ps2MouseAbsolutePointer.c | 778 ++++ .../Ps2MouseAbsolutePointer.h | 400 ++ .../Ps2MouseAbsolutePointerDxe.inf | 77 + .../Ps2MouseAbsolutePointerDxe.uni | Bin 0 -> 2064 bytes .../Ps2MouseAbsolutePointerDxeExtra.uni | Bin 0 -> 1394 bytes .../Bus/Isa/Ps2MouseDxe/CommPs2.c | 921 +++++ .../Bus/Isa/Ps2MouseDxe/CommPs2.h | 435 ++ .../Bus/Isa/Ps2MouseDxe/ComponentName.c | 241 ++ .../Bus/Isa/Ps2MouseDxe/Ps2Mouse.c | 792 ++++ .../Bus/Isa/Ps2MouseDxe/Ps2Mouse.h | 400 ++ .../Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf | 76 + .../Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni | Bin 0 -> 1628 bytes .../Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni | Bin 0 -> 1346 bytes .../Bus/Pci/IdeBusDxe/Ata.c | 2799 +++++++++++++ .../Bus/Pci/IdeBusDxe/Atapi.c | 1952 +++++++++ .../Bus/Pci/IdeBusDxe/ComponentName.c | 278 ++ .../Bus/Pci/IdeBusDxe/ComponentName.h | 166 + .../Bus/Pci/IdeBusDxe/DriverConfiguration.c | 292 ++ .../Bus/Pci/IdeBusDxe/DriverDiagnostics.c | 245 ++ .../Bus/Pci/IdeBusDxe/Ide.c | 1330 ++++++ .../Bus/Pci/IdeBusDxe/Ide.h | 835 ++++ .../Bus/Pci/IdeBusDxe/IdeBus.c | 1571 +++++++ .../Bus/Pci/IdeBusDxe/IdeBus.h | 540 +++ .../Bus/Pci/IdeBusDxe/IdeBusDxe.inf | 88 + .../Bus/Pci/IdeBusDxe/IdeBusDxe.uni | Bin 0 -> 1764 bytes .../Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni | Bin 0 -> 1328 bytes .../Bus/Pci/IdeBusDxe/IdeData.h | 311 ++ .../Bus/Pci/VgaMiniPortDxe/ComponentName.c | 168 + .../Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c | 331 ++ .../Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h | 271 ++ .../Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni | Bin 0 -> 2038 bytes .../Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf | 57 + .../Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni | Bin 0 -> 1352 bytes Core/IntelFrameworkModulePkg/Contributions.txt | 218 + .../Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c | 780 ++++ .../Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h | 432 ++ .../Csm/BiosThunk/BlockIoDxe/BiosInt13.c | 1495 +++++++ .../Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf | 65 + .../Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni | Bin 0 -> 2138 bytes .../Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni | Bin 0 -> 1366 bytes .../Csm/BiosThunk/BlockIoDxe/ComponentName.c | 309 ++ .../Csm/BiosThunk/BlockIoDxe/Edd.h | 209 + .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c | 2428 +++++++++++ .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h | 743 ++++ .../Csm/BiosThunk/KeyboardDxe/ComponentName.c | 183 + .../Csm/BiosThunk/KeyboardDxe/ComponentName.h | 153 + .../Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf | 77 + .../Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni | Bin 0 -> 2044 bytes .../Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni | Bin 0 -> 1366 bytes .../Csm/BiosThunk/Snp16Dxe/BiosSnp16.c | 3522 ++++++++++++++++ .../Csm/BiosThunk/Snp16Dxe/BiosSnp16.h | 1655 ++++++++ .../Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni | Bin 0 -> 1824 bytes .../Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni | Bin 0 -> 1392 bytes .../Csm/BiosThunk/Snp16Dxe/ComponentName.c | 309 ++ .../Csm/BiosThunk/Snp16Dxe/Misc.c | 962 +++++ .../Csm/BiosThunk/Snp16Dxe/Pxe.h | 613 +++ .../Csm/BiosThunk/Snp16Dxe/PxeUndi.c | 1254 ++++++ .../Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf | 73 + .../Csm/BiosThunk/VideoDxe/BiosVideo.c | 3296 +++++++++++++++ .../Csm/BiosThunk/VideoDxe/BiosVideo.h | 539 +++ .../Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni | Bin 0 -> 1984 bytes .../Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni | Bin 0 -> 1362 bytes .../Csm/BiosThunk/VideoDxe/ComponentName.c | 313 ++ .../Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h | 466 +++ .../Csm/BiosThunk/VideoDxe/VideoDxe.inf | 87 + .../Csm/LegacyBiosDxe/IA32/InterruptTable.S | 67 + .../Csm/LegacyBiosDxe/IA32/InterruptTable.asm | 73 + .../Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c | 277 ++ .../Csm/LegacyBiosDxe/Ipf/IpfThunk.h | 102 + .../Csm/LegacyBiosDxe/Ipf/IpfThunk.i | 89 + .../Csm/LegacyBiosDxe/Ipf/IpfThunk.s | 524 +++ .../Csm/LegacyBiosDxe/Ipf/Thunk.c | 550 +++ .../Csm/LegacyBiosDxe/LegacyBbs.c | 384 ++ .../Csm/LegacyBiosDxe/LegacyBda.c | 66 + .../Csm/LegacyBiosDxe/LegacyBios.c | 1154 ++++++ .../Csm/LegacyBiosDxe/LegacyBiosDxe.inf | 150 + .../Csm/LegacyBiosDxe/LegacyBiosDxe.uni | Bin 0 -> 1848 bytes .../Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni | Bin 0 -> 1378 bytes .../Csm/LegacyBiosDxe/LegacyBiosInterface.h | 1541 +++++++ .../Csm/LegacyBiosDxe/LegacyBootSupport.c | 2165 ++++++++++ .../Csm/LegacyBiosDxe/LegacyCmos.c | 124 + .../Csm/LegacyBiosDxe/LegacyIde.c | 317 ++ .../Csm/LegacyBiosDxe/LegacyPci.c | 3007 ++++++++++++++ .../Csm/LegacyBiosDxe/LegacySio.c | 234 ++ .../Csm/LegacyBiosDxe/Thunk.c | 419 ++ .../Csm/LegacyBiosDxe/X64/InterruptTable.S | 72 + .../Csm/LegacyBiosDxe/X64/InterruptTable.asm | 71 + .../Include/Guid/AcpiVariableCompatibility.h | 69 + Core/IntelFrameworkModulePkg/Include/Guid/BdsHii.h | 55 + .../Include/Guid/BdsLibHii.h | 25 + .../Include/Guid/BlockIoVendor.h | 31 + .../Include/Guid/CapsuleDataFile.h | 23 + .../Include/Guid/DataHubStatusCodeRecord.h | 61 + .../Include/Guid/HdBootVariable.h | 31 + .../Guid/IntelFrameworkModulePkgTokenSpace.h | 27 + .../Include/Guid/LastEnumLang.h | 31 + .../Include/Guid/LegacyBios.h | 36 + .../Include/Guid/LegacyDevOrder.h | 45 + .../Include/Guid/TianoDecompress.h | 28 + .../Include/Library/GenericBdsLib.h | 1114 +++++ .../Include/Library/PlatformBdsLib.h | 156 + .../Include/Protocol/ExitPmAuth.h | 25 + .../Include/Protocol/IsaAcpi.h | 304 ++ .../Include/Protocol/IsaIo.h | 362 ++ .../Include/Protocol/OEMBadging.h | 88 + .../Include/Protocol/Ps2Policy.h | 41 + .../Include/Protocol/VgaMiniPort.h | 94 + .../IntelFrameworkModulePkg.dec | 283 ++ .../IntelFrameworkModulePkg.dsc | 198 + .../IntelFrameworkModulePkg.uni | Bin 0 -> 37484 bytes .../IntelFrameworkModulePkgExtra.uni | Bin 0 -> 1398 bytes .../BaseUefiTianoCustomDecompressLib.c | 1050 +++++ .../BaseUefiTianoCustomDecompressLib.inf | 48 + .../BaseUefiTianoCustomDecompressLibInternals.h | 220 + .../BaseUefiTianoDecompressLib.uni | Bin 0 -> 2040 bytes .../Library/DxeCapsuleLib/DxeCapsuleLib.c | 518 +++ .../Library/DxeCapsuleLib/DxeCapsuleLib.inf | 55 + .../Library/DxeCapsuleLib/DxeCapsuleLib.uni | Bin 0 -> 1840 bytes .../DxeReportStatusCodeLib.inf | 58 + .../DxeReportStatusCodeLib.uni | Bin 0 -> 1986 bytes .../ReportStatusCodeLib.c | 634 +++ .../Library/GenericBdsLib/BdsBoot.c | 4356 ++++++++++++++++++++ .../Library/GenericBdsLib/BdsConnect.c | 435 ++ .../Library/GenericBdsLib/BdsConsole.c | 1301 ++++++ .../Library/GenericBdsLib/BdsMisc.c | 1589 +++++++ .../Library/GenericBdsLib/DevicePath.c | 33 + .../Library/GenericBdsLib/GenericBdsLib.inf | 145 + .../Library/GenericBdsLib/GenericBdsLib.uni | Bin 0 -> 2378 bytes .../Library/GenericBdsLib/GenericBdsStrings.uni | Bin 0 -> 3852 bytes .../Library/GenericBdsLib/InternalBdsLib.h | 194 + .../Library/GenericBdsLib/Performance.c | 313 ++ .../Library/GenericBdsLib/String.c | 32 + .../Library/GenericBdsLib/String.h | 48 + .../LegacyBootMaintUiLib/LegacyBootMaintUi.c | 1456 +++++++ .../LegacyBootMaintUiLib/LegacyBootMaintUi.h | 255 ++ .../LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf | 69 + .../LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni | Bin 0 -> 1800 bytes .../LegacyBootMaintUiStrings.uni | Bin 0 -> 6380 bytes .../LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr | 73 + .../LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h | 85 + .../LegacyBootManagerLib/InternalLegacyBm.h | 66 + .../Library/LegacyBootManagerLib/LegacyBm.c | 1536 +++++++ .../LegacyBootManagerLib/LegacyBootManagerLib.inf | 64 + .../LegacyBootManagerLib/LegacyBootManagerLib.uni | Bin 0 -> 1736 bytes .../F86GuidedSectionExtraction.c | 218 + .../GuidedSectionExtraction.c | 201 + .../LzmaCustomDecompressLib/LZMA-SDK-README.txt | 4 + .../LzmaArchCustomDecompressLib.inf | 66 + .../LzmaArchDecompressLib.uni | Bin 0 -> 2480 bytes .../LzmaCustomDecompressLib.inf | 62 + .../LzmaCustomDecompressLib/LzmaDecompress.c | 220 + .../LzmaCustomDecompressLib/LzmaDecompressLib.uni | Bin 0 -> 2274 bytes .../LzmaDecompressLibInternal.h | 96 + .../LzmaCustomDecompressLib/Sdk/C/7zVersion.h | 7 + .../Library/LzmaCustomDecompressLib/Sdk/C/Bra.h | 60 + .../Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c | 85 + .../LzmaCustomDecompressLib/Sdk/C/CpuArch.h | 69 + .../Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c | 770 ++++ .../Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h | 107 + .../Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h | 54 + .../LzmaCustomDecompressLib/Sdk/C/LzmaDec.c | 1026 +++++ .../LzmaCustomDecompressLib/Sdk/C/LzmaDec.h | 223 + .../Library/LzmaCustomDecompressLib/Sdk/C/Types.h | 231 ++ .../LzmaCustomDecompressLib/Sdk/history.txt | 236 ++ .../Library/LzmaCustomDecompressLib/Sdk/lzma.txt | 594 +++ .../Library/LzmaCustomDecompressLib/UefiLzma.h | 47 + .../PeiDxeDebugLibReportStatusCode/DebugLib.c | 468 +++ .../PeiDxeDebugLibReportStatusCode.inf | 54 + .../PeiDxeDebugLibReportStatusCode.uni | Bin 0 -> 1896 bytes .../Library/PeiRecoveryLib/PeiRecoveryLib.c | 50 + .../Library/PeiRecoveryLib/PeiRecoveryLib.inf | 50 + .../Library/PeiRecoveryLib/PeiRecoveryLib.uni | Bin 0 -> 2272 bytes .../Library/PeiS3Lib/PeiS3Lib.c | 51 + .../Library/PeiS3Lib/PeiS3Lib.inf | 49 + .../Library/PeiS3Lib/PeiS3Lib.uni | Bin 0 -> 2392 bytes .../Library/PlatformBdsLibNull/BdsPlatform.c | 187 + .../Library/PlatformBdsLibNull/BdsPlatform.h | 28 + .../Library/PlatformBdsLibNull/PlatformBdsLib.uni | Bin 0 -> 1880 bytes .../PlatformBdsLibNull/PlatformBdsLibNull.inf | 47 + .../Library/PlatformBdsLibNull/PlatformData.c | 21 + .../ReportStatusCodeLib.c | 493 +++ .../ReportStatusCodeLibInternal.h | 73 + .../SmmRuntimeDxeReportStatusCodeLibFramework.inf | 73 + .../SmmRuntimeDxeReportStatusCodeLibFramework.uni | Bin 0 -> 2844 bytes .../SmmRuntimeDxeSupport.c | 335 ++ Core/IntelFrameworkModulePkg/License.txt | 25 + .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c | 643 +++ .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h | 59 + .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf | 89 + .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni | Bin 0 -> 1916 bytes .../Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni | Bin 0 -> 1368 bytes .../Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c | 224 + .../Universal/Acpi/AcpiSupportDxe/AcpiSupport.c | 91 + .../Universal/Acpi/AcpiSupportDxe/AcpiSupport.h | 166 + .../AcpiSupportAcpiSupportProtocol.c | 1918 +++++++++ .../Acpi/AcpiSupportDxe/AcpiSupportDxe.inf | 81 + .../Acpi/AcpiSupportDxe/AcpiSupportDxe.uni | Bin 0 -> 2246 bytes .../Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni | Bin 0 -> 1366 bytes .../IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h | 237 ++ .../Universal/BdsDxe/BdsDxe.inf | 228 + .../Universal/BdsDxe/BdsDxe.uni | Bin 0 -> 5172 bytes .../Universal/BdsDxe/BdsDxeExtra.uni | Bin 0 -> 1370 bytes .../Universal/BdsDxe/BdsEntry.c | 754 ++++ .../Universal/BdsDxe/BootMaint/BBSsupport.c | 254 ++ .../Universal/BdsDxe/BootMaint/BBSsupport.h | 82 + .../Universal/BdsDxe/BootMaint/Bm.vfr | 365 ++ .../Universal/BdsDxe/BootMaint/BmLib.c | 411 ++ .../Universal/BdsDxe/BootMaint/Bmstring.uni | Bin 0 -> 38776 bytes .../Universal/BdsDxe/BootMaint/BootMaint.c | 1690 ++++++++ .../Universal/BdsDxe/BootMaint/BootMaint.h | 1679 ++++++++ .../Universal/BdsDxe/BootMaint/BootOption.c | 1823 ++++++++ .../Universal/BdsDxe/BootMaint/ConsoleOption.c | 1198 ++++++ .../Universal/BdsDxe/BootMaint/Data.c | 332 ++ .../Universal/BdsDxe/BootMaint/FE.vfr | 127 + .../Universal/BdsDxe/BootMaint/FileExplorer.c | 469 +++ .../Universal/BdsDxe/BootMaint/FormGuid.h | 243 ++ .../Universal/BdsDxe/BootMaint/UpdatePage.c | 1391 +++++++ .../Universal/BdsDxe/BootMaint/Variable.c | 1380 +++++++ .../Universal/BdsDxe/BootMngr/BootManager.c | 399 ++ .../Universal/BdsDxe/BootMngr/BootManager.h | 103 + .../BdsDxe/BootMngr/BootManagerStrings.uni | Bin 0 -> 3344 bytes .../Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr | 50 + .../Universal/BdsDxe/Capsules.c | 233 ++ .../Universal/BdsDxe/DeviceMngr/DeviceManager.c | 2591 ++++++++++++ .../Universal/BdsDxe/DeviceMngr/DeviceManager.h | 523 +++ .../BdsDxe/DeviceMngr/DeviceManagerStrings.uni | Bin 0 -> 13366 bytes .../BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr | 93 + .../Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h | 56 + .../BdsDxe/DeviceMngr/DriverHealthVfr.Vfr | 38 + .../Universal/BdsDxe/FrontPage.c | 1480 +++++++ .../Universal/BdsDxe/FrontPage.h | 254 ++ .../Universal/BdsDxe/FrontPageStrings.uni | Bin 0 -> 9974 bytes .../Universal/BdsDxe/FrontPageVfr.Vfr | 137 + .../Universal/BdsDxe/Hotkey.c | 597 +++ .../Universal/BdsDxe/Hotkey.h | 67 + .../Universal/BdsDxe/HwErrRecSupport.c | 48 + .../Universal/BdsDxe/HwErrRecSupport.h | 32 + .../Universal/BdsDxe/Language.c | 499 +++ .../Universal/BdsDxe/Language.h | 51 + .../Universal/BdsDxe/MemoryTest.c | 436 ++ .../Universal/BdsDxe/String.c | 59 + .../Universal/BdsDxe/String.h | 65 + .../Universal/BdsDxe/Strings.uni | Bin 0 -> 7444 bytes .../Universal/Console/VgaClassDxe/ComponentName.c | 167 + .../Universal/Console/VgaClassDxe/VgaClass.c | 1288 ++++++ .../Universal/Console/VgaClassDxe/VgaClass.h | 484 +++ .../Universal/Console/VgaClassDxe/VgaClassDxe.inf | 64 + .../Universal/Console/VgaClassDxe/VgaClassDxe.uni | Bin 0 -> 2006 bytes .../Console/VgaClassDxe/VgaClassDxeExtra.uni | Bin 0 -> 1346 bytes .../Universal/CpuIoDxe/CpuIo.c | 536 +++ .../Universal/CpuIoDxe/CpuIo.h | 226 + .../Universal/CpuIoDxe/CpuIoDxe.inf | 51 + .../Universal/CpuIoDxe/CpuIoDxe.uni | Bin 0 -> 2066 bytes .../Universal/CpuIoDxe/CpuIoDxeExtra.uni | Bin 0 -> 1338 bytes .../Universal/DataHubDxe/DataHub.c | 587 +++ .../Universal/DataHubDxe/DataHub.h | 131 + .../Universal/DataHubDxe/DataHubDxe.inf | 85 + .../Universal/DataHubDxe/DataHubDxe.uni | Bin 0 -> 8204 bytes .../Universal/DataHubDxe/DataHubDxeExtra.uni | Bin 0 -> 1332 bytes .../Universal/DataHubStdErrDxe/DataHubStdErr.c | 151 + .../DataHubStdErrDxe/DataHubStdErrDxe.inf | 57 + .../DataHubStdErrDxe/DataHubStdErrDxe.uni | Bin 0 -> 1992 bytes .../DataHubStdErrDxe/DataHubStdErrDxeExtra.uni | Bin 0 -> 1358 bytes .../Universal/FirmwareVolume/FwVolDxe/Ffs.c | 608 +++ .../Universal/FirmwareVolume/FwVolDxe/FwPadFile.c | 1228 ++++++ .../Universal/FirmwareVolume/FwVolDxe/FwVol.c | 798 ++++ .../FirmwareVolume/FwVolDxe/FwVolAttrib.c | 220 + .../FirmwareVolume/FwVolDxe/FwVolDriver.h | 761 ++++ .../Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf | 74 + .../Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni | Bin 0 -> 1960 bytes .../FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni | Bin 0 -> 1354 bytes .../Universal/FirmwareVolume/FwVolDxe/FwVolRead.c | 629 +++ .../Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c | 1586 +++++++ .../FirmwareVolume/UpdateDriverDxe/FlashUpdate.c | 1218 ++++++ .../UpdateDriverDxe/ParseUpdateProfile.c | 1133 +++++ .../UpdateDriverDxe/UpdateDispatcher.c | 846 ++++ .../FirmwareVolume/UpdateDriverDxe/UpdateDriver.h | 213 + .../UpdateDriverDxe/UpdateDriverDxe.inf | 76 + .../UpdateDriverDxe/UpdateDriverDxe.uni | Bin 0 -> 2360 bytes .../UpdateDriverDxe/UpdateDriverDxeExtra.uni | Bin 0 -> 1366 bytes .../UpdateDriverDxe/UpdateStrings.uni | Bin 0 -> 2410 bytes .../Universal/LegacyRegionDxe/LegacyRegion.c | 170 + .../Universal/LegacyRegionDxe/LegacyRegionDxe.inf | 55 + .../Universal/LegacyRegionDxe/LegacyRegionDxe.uni | Bin 0 -> 3044 bytes .../LegacyRegionDxe/LegacyRegionDxeExtra.uni | Bin 0 -> 1362 bytes .../SectionExtractionDxe/SectionExtraction.c | 1456 +++++++ .../SectionExtractionDxe/SectionExtractionDxe.inf | 57 + .../SectionExtractionDxe/SectionExtractionDxe.uni | Bin 0 -> 2552 bytes .../SectionExtractionDxeExtra.uni | Bin 0 -> 1400 bytes .../DataHubStatusCodeWorker.c | 376 ++ .../DatahubStatusCodeHandlerDxe.c | 88 + .../DatahubStatusCodeHandlerDxe.h | 91 + .../DatahubStatusCodeHandlerDxe.inf | 72 + .../DatahubStatusCodeHandlerDxe.uni | Bin 0 -> 1782 bytes .../DatahubStatusCodeHandlerDxeExtra.uni | Bin 0 -> 1390 bytes .../StatusCode/Pei/MemoryStausCodeWorker.c | 118 + .../StatusCode/Pei/SerialStatusCodeWorker.c | 162 + .../Universal/StatusCode/Pei/StatusCodePei.c | 146 + .../Universal/StatusCode/Pei/StatusCodePei.h | 147 + .../Universal/StatusCode/Pei/StatusCodePei.inf | 78 + .../Universal/StatusCode/Pei/StatusCodePei.uni | Bin 0 -> 1718 bytes .../StatusCode/Pei/StatusCodePeiExtra.uni | Bin 0 -> 1344 bytes .../RuntimeDxe/DataHubStatusCodeWorker.c | 390 ++ .../RuntimeDxe/RtMemoryStatusCodeWorker.c | 104 + .../StatusCode/RuntimeDxe/SerialStatusCodeWorker.c | 160 + .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c | 301 ++ .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h | 240 ++ .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf | 88 + .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni | Bin 0 -> 1886 bytes .../RuntimeDxe/StatusCodeRuntimeDxeExtra.uni | Bin 0 -> 1374 bytes .../Bus/Isa/IsaBusDxe/ComponentName.c | 182 - .../Bus/Isa/IsaBusDxe/ComponentName.h | 148 - .../Bus/Isa/IsaBusDxe/InternalIsaBus.h | 297 -- .../Bus/Isa/IsaBusDxe/InternalIsaIo.h | 331 -- IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c | 673 --- .../Bus/Isa/IsaBusDxe/IsaBusDxe.inf | 73 - .../Bus/Isa/IsaBusDxe/IsaBusDxe.uni | Bin 2658 -> 0 bytes .../Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni | Bin 1336 -> 0 bytes IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c | 1463 ------- .../Bus/Isa/IsaFloppyDxe/ComponentName.c | 249 -- .../Bus/Isa/IsaFloppyDxe/ComponentName.h | 146 - .../Bus/Isa/IsaFloppyDxe/IsaFloppy.c | 515 --- .../Bus/Isa/IsaFloppyDxe/IsaFloppy.h | 1093 ----- .../Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c | 375 -- .../Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c | 1398 ------- .../Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf | 78 - .../Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni | Bin 2444 -> 0 bytes .../Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni | Bin 1348 -> 0 bytes IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h | 235 -- .../Bus/Isa/IsaFloppyPei/FloppyPeim.c | 1759 -------- .../Bus/Isa/IsaFloppyPei/FloppyPeim.h | 246 -- .../Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf | 73 - .../Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni | Bin 2348 -> 0 bytes .../Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni | Bin 1358 -> 0 bytes .../Bus/Isa/IsaIoDxe/ComponentName.c | 182 - .../Bus/Isa/IsaIoDxe/ComponentName.h | 148 - .../Bus/Isa/IsaIoDxe/IsaDriver.c | 326 -- .../Bus/Isa/IsaIoDxe/IsaDriver.h | 263 -- IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c | 1803 -------- IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h | 331 -- .../Bus/Isa/IsaIoDxe/IsaIoDxe.inf | 71 - .../Bus/Isa/IsaIoDxe/IsaIoDxe.uni | Bin 2414 -> 0 bytes .../Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni | Bin 1334 -> 0 bytes .../Bus/Isa/IsaSerialDxe/ComponentName.c | 272 -- .../Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf | 80 - .../Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni | Bin 2094 -> 0 bytes .../Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni | Bin 1366 -> 0 bytes .../Bus/Isa/IsaSerialDxe/Serial.c | 2038 --------- .../Bus/Isa/IsaSerialDxe/Serial.h | 842 ---- .../Bus/Isa/Ps2KeyboardDxe/ComponentName.c | 372 -- .../Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c | 1908 --------- .../Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c | 683 --- .../Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c | 642 --- .../Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h | 550 --- .../Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni | Bin 1928 -> 0 bytes .../Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni | Bin 1358 -> 0 bytes .../Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf | 85 - .../Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c | 923 ----- .../Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h | 435 -- .../Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c | 241 -- .../Ps2MouseAbsolutePointer.c | 778 ---- .../Ps2MouseAbsolutePointer.h | 400 -- .../Ps2MouseAbsolutePointerDxe.inf | 77 - .../Ps2MouseAbsolutePointerDxe.uni | Bin 2064 -> 0 bytes .../Ps2MouseAbsolutePointerDxeExtra.uni | Bin 1394 -> 0 bytes .../Bus/Isa/Ps2MouseDxe/CommPs2.c | 921 ----- .../Bus/Isa/Ps2MouseDxe/CommPs2.h | 435 -- .../Bus/Isa/Ps2MouseDxe/ComponentName.c | 241 -- .../Bus/Isa/Ps2MouseDxe/Ps2Mouse.c | 792 ---- .../Bus/Isa/Ps2MouseDxe/Ps2Mouse.h | 400 -- .../Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf | 76 - .../Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni | Bin 1628 -> 0 bytes .../Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni | Bin 1346 -> 0 bytes IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c | 2799 ------------- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c | 1952 --------- .../Bus/Pci/IdeBusDxe/ComponentName.c | 278 -- .../Bus/Pci/IdeBusDxe/ComponentName.h | 166 - .../Bus/Pci/IdeBusDxe/DriverConfiguration.c | 292 -- .../Bus/Pci/IdeBusDxe/DriverDiagnostics.c | 245 -- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c | 1330 ------ IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h | 835 ---- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c | 1571 ------- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h | 540 --- .../Bus/Pci/IdeBusDxe/IdeBusDxe.inf | 88 - .../Bus/Pci/IdeBusDxe/IdeBusDxe.uni | Bin 1764 -> 0 bytes .../Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni | Bin 1328 -> 0 bytes .../Bus/Pci/IdeBusDxe/IdeData.h | 311 -- .../Bus/Pci/VgaMiniPortDxe/ComponentName.c | 168 - .../Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c | 331 -- .../Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h | 271 -- .../Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni | Bin 2038 -> 0 bytes .../Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf | 57 - .../Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni | Bin 1352 -> 0 bytes IntelFrameworkModulePkg/Contributions.txt | 218 - .../Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c | 780 ---- .../Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h | 432 -- .../Csm/BiosThunk/BlockIoDxe/BiosInt13.c | 1495 ------- .../Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf | 65 - .../Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni | Bin 2138 -> 0 bytes .../Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni | Bin 1366 -> 0 bytes .../Csm/BiosThunk/BlockIoDxe/ComponentName.c | 309 -- .../Csm/BiosThunk/BlockIoDxe/Edd.h | 209 - .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c | 2428 ----------- .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h | 743 ---- .../Csm/BiosThunk/KeyboardDxe/ComponentName.c | 183 - .../Csm/BiosThunk/KeyboardDxe/ComponentName.h | 153 - .../Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf | 77 - .../Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni | Bin 2044 -> 0 bytes .../Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni | Bin 1366 -> 0 bytes .../Csm/BiosThunk/Snp16Dxe/BiosSnp16.c | 3522 ---------------- .../Csm/BiosThunk/Snp16Dxe/BiosSnp16.h | 1655 -------- .../Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni | Bin 1824 -> 0 bytes .../Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni | Bin 1392 -> 0 bytes .../Csm/BiosThunk/Snp16Dxe/ComponentName.c | 309 -- .../Csm/BiosThunk/Snp16Dxe/Misc.c | 962 ----- .../Csm/BiosThunk/Snp16Dxe/Pxe.h | 613 --- .../Csm/BiosThunk/Snp16Dxe/PxeUndi.c | 1254 ------ .../Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf | 73 - .../Csm/BiosThunk/VideoDxe/BiosVideo.c | 3296 --------------- .../Csm/BiosThunk/VideoDxe/BiosVideo.h | 539 --- .../Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni | Bin 1984 -> 0 bytes .../Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni | Bin 1362 -> 0 bytes .../Csm/BiosThunk/VideoDxe/ComponentName.c | 313 -- .../Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h | 466 --- .../Csm/BiosThunk/VideoDxe/VideoDxe.inf | 87 - .../Csm/LegacyBiosDxe/IA32/InterruptTable.S | 67 - .../Csm/LegacyBiosDxe/IA32/InterruptTable.asm | 73 - .../Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c | 277 -- .../Csm/LegacyBiosDxe/Ipf/IpfThunk.h | 102 - .../Csm/LegacyBiosDxe/Ipf/IpfThunk.i | 89 - .../Csm/LegacyBiosDxe/Ipf/IpfThunk.s | 524 --- .../Csm/LegacyBiosDxe/Ipf/Thunk.c | 550 --- .../Csm/LegacyBiosDxe/LegacyBbs.c | 384 -- .../Csm/LegacyBiosDxe/LegacyBda.c | 66 - .../Csm/LegacyBiosDxe/LegacyBios.c | 1154 ------ .../Csm/LegacyBiosDxe/LegacyBiosDxe.inf | 150 - .../Csm/LegacyBiosDxe/LegacyBiosDxe.uni | Bin 1848 -> 0 bytes .../Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni | Bin 1378 -> 0 bytes .../Csm/LegacyBiosDxe/LegacyBiosInterface.h | 1541 ------- .../Csm/LegacyBiosDxe/LegacyBootSupport.c | 2165 ---------- .../Csm/LegacyBiosDxe/LegacyCmos.c | 124 - .../Csm/LegacyBiosDxe/LegacyIde.c | 317 -- .../Csm/LegacyBiosDxe/LegacyPci.c | 3007 -------------- .../Csm/LegacyBiosDxe/LegacySio.c | 234 -- IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c | 419 -- .../Csm/LegacyBiosDxe/X64/InterruptTable.S | 72 - .../Csm/LegacyBiosDxe/X64/InterruptTable.asm | 71 - .../Include/Guid/AcpiVariableCompatibility.h | 69 - IntelFrameworkModulePkg/Include/Guid/BdsHii.h | 55 - IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h | 25 - .../Include/Guid/BlockIoVendor.h | 31 - .../Include/Guid/CapsuleDataFile.h | 23 - .../Include/Guid/DataHubStatusCodeRecord.h | 61 - .../Include/Guid/HdBootVariable.h | 31 - .../Guid/IntelFrameworkModulePkgTokenSpace.h | 27 - .../Include/Guid/LastEnumLang.h | 31 - IntelFrameworkModulePkg/Include/Guid/LegacyBios.h | 36 - .../Include/Guid/LegacyDevOrder.h | 45 - .../Include/Guid/TianoDecompress.h | 28 - .../Include/Library/GenericBdsLib.h | 1114 ----- .../Include/Library/PlatformBdsLib.h | 156 - .../Include/Protocol/ExitPmAuth.h | 25 - IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h | 304 -- IntelFrameworkModulePkg/Include/Protocol/IsaIo.h | 362 -- .../Include/Protocol/OEMBadging.h | 88 - .../Include/Protocol/Ps2Policy.h | 41 - .../Include/Protocol/VgaMiniPort.h | 94 - .../IntelFrameworkModulePkg.dec | 283 -- .../IntelFrameworkModulePkg.dsc | 198 - .../IntelFrameworkModulePkg.uni | Bin 37484 -> 0 bytes .../IntelFrameworkModulePkgExtra.uni | Bin 1398 -> 0 bytes .../BaseUefiTianoCustomDecompressLib.c | 1050 ----- .../BaseUefiTianoCustomDecompressLib.inf | 48 - .../BaseUefiTianoCustomDecompressLibInternals.h | 220 - .../BaseUefiTianoDecompressLib.uni | Bin 2040 -> 0 bytes .../Library/DxeCapsuleLib/DxeCapsuleLib.c | 518 --- .../Library/DxeCapsuleLib/DxeCapsuleLib.inf | 55 - .../Library/DxeCapsuleLib/DxeCapsuleLib.uni | Bin 1840 -> 0 bytes .../DxeReportStatusCodeLib.inf | 58 - .../DxeReportStatusCodeLib.uni | Bin 1986 -> 0 bytes .../ReportStatusCodeLib.c | 634 --- .../Library/GenericBdsLib/BdsBoot.c | 4356 -------------------- .../Library/GenericBdsLib/BdsConnect.c | 435 -- .../Library/GenericBdsLib/BdsConsole.c | 1301 ------ .../Library/GenericBdsLib/BdsMisc.c | 1589 ------- .../Library/GenericBdsLib/DevicePath.c | 33 - .../Library/GenericBdsLib/GenericBdsLib.inf | 145 - .../Library/GenericBdsLib/GenericBdsLib.uni | Bin 2378 -> 0 bytes .../Library/GenericBdsLib/GenericBdsStrings.uni | Bin 3852 -> 0 bytes .../Library/GenericBdsLib/InternalBdsLib.h | 194 - .../Library/GenericBdsLib/Performance.c | 313 -- .../Library/GenericBdsLib/String.c | 32 - .../Library/GenericBdsLib/String.h | 48 - .../LegacyBootMaintUiLib/LegacyBootMaintUi.c | 1456 ------- .../LegacyBootMaintUiLib/LegacyBootMaintUi.h | 255 -- .../LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf | 69 - .../LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni | Bin 1800 -> 0 bytes .../LegacyBootMaintUiStrings.uni | Bin 6380 -> 0 bytes .../LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr | 73 - .../LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h | 85 - .../LegacyBootManagerLib/InternalLegacyBm.h | 66 - .../Library/LegacyBootManagerLib/LegacyBm.c | 1536 ------- .../LegacyBootManagerLib/LegacyBootManagerLib.inf | 64 - .../LegacyBootManagerLib/LegacyBootManagerLib.uni | Bin 1736 -> 0 bytes .../F86GuidedSectionExtraction.c | 218 - .../GuidedSectionExtraction.c | 201 - .../LzmaCustomDecompressLib/LZMA-SDK-README.txt | 4 - .../LzmaArchCustomDecompressLib.inf | 66 - .../LzmaArchDecompressLib.uni | Bin 2480 -> 0 bytes .../LzmaCustomDecompressLib.inf | 62 - .../LzmaCustomDecompressLib/LzmaDecompress.c | 220 - .../LzmaCustomDecompressLib/LzmaDecompressLib.uni | Bin 2274 -> 0 bytes .../LzmaDecompressLibInternal.h | 96 - .../LzmaCustomDecompressLib/Sdk/C/7zVersion.h | 7 - .../Library/LzmaCustomDecompressLib/Sdk/C/Bra.h | 60 - .../Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c | 85 - .../LzmaCustomDecompressLib/Sdk/C/CpuArch.h | 69 - .../Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c | 770 ---- .../Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h | 107 - .../Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h | 54 - .../LzmaCustomDecompressLib/Sdk/C/LzmaDec.c | 1026 ----- .../LzmaCustomDecompressLib/Sdk/C/LzmaDec.h | 223 - .../Library/LzmaCustomDecompressLib/Sdk/C/Types.h | 231 -- .../LzmaCustomDecompressLib/Sdk/history.txt | 236 -- .../Library/LzmaCustomDecompressLib/Sdk/lzma.txt | 594 --- .../Library/LzmaCustomDecompressLib/UefiLzma.h | 47 - .../PeiDxeDebugLibReportStatusCode/DebugLib.c | 468 --- .../PeiDxeDebugLibReportStatusCode.inf | 54 - .../PeiDxeDebugLibReportStatusCode.uni | Bin 1896 -> 0 bytes .../Library/PeiRecoveryLib/PeiRecoveryLib.c | 50 - .../Library/PeiRecoveryLib/PeiRecoveryLib.inf | 50 - .../Library/PeiRecoveryLib/PeiRecoveryLib.uni | Bin 2272 -> 0 bytes .../Library/PeiS3Lib/PeiS3Lib.c | 51 - .../Library/PeiS3Lib/PeiS3Lib.inf | 49 - .../Library/PeiS3Lib/PeiS3Lib.uni | Bin 2392 -> 0 bytes .../Library/PlatformBdsLibNull/BdsPlatform.c | 187 - .../Library/PlatformBdsLibNull/BdsPlatform.h | 28 - .../Library/PlatformBdsLibNull/PlatformBdsLib.uni | Bin 1880 -> 0 bytes .../PlatformBdsLibNull/PlatformBdsLibNull.inf | 47 - .../Library/PlatformBdsLibNull/PlatformData.c | 21 - .../ReportStatusCodeLib.c | 493 --- .../ReportStatusCodeLibInternal.h | 73 - .../SmmRuntimeDxeReportStatusCodeLibFramework.inf | 73 - .../SmmRuntimeDxeReportStatusCodeLibFramework.uni | Bin 2844 -> 0 bytes .../SmmRuntimeDxeSupport.c | 335 -- IntelFrameworkModulePkg/License.txt | 25 - .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c | 643 --- .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h | 59 - .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf | 89 - .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni | Bin 1916 -> 0 bytes .../Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni | Bin 1368 -> 0 bytes .../Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c | 224 - .../Universal/Acpi/AcpiSupportDxe/AcpiSupport.c | 91 - .../Universal/Acpi/AcpiSupportDxe/AcpiSupport.h | 166 - .../AcpiSupportAcpiSupportProtocol.c | 1918 --------- .../Acpi/AcpiSupportDxe/AcpiSupportDxe.inf | 81 - .../Acpi/AcpiSupportDxe/AcpiSupportDxe.uni | Bin 2246 -> 0 bytes .../Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni | Bin 1366 -> 0 bytes IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h | 237 -- .../Universal/BdsDxe/BdsDxe.inf | 228 - .../Universal/BdsDxe/BdsDxe.uni | Bin 5172 -> 0 bytes .../Universal/BdsDxe/BdsDxeExtra.uni | Bin 1370 -> 0 bytes .../Universal/BdsDxe/BdsEntry.c | 754 ---- .../Universal/BdsDxe/BootMaint/BBSsupport.c | 254 -- .../Universal/BdsDxe/BootMaint/BBSsupport.h | 82 - .../Universal/BdsDxe/BootMaint/Bm.vfr | 365 -- .../Universal/BdsDxe/BootMaint/BmLib.c | 411 -- .../Universal/BdsDxe/BootMaint/Bmstring.uni | Bin 38776 -> 0 bytes .../Universal/BdsDxe/BootMaint/BootMaint.c | 1690 -------- .../Universal/BdsDxe/BootMaint/BootMaint.h | 1679 -------- .../Universal/BdsDxe/BootMaint/BootOption.c | 1823 -------- .../Universal/BdsDxe/BootMaint/ConsoleOption.c | 1198 ------ .../Universal/BdsDxe/BootMaint/Data.c | 332 -- .../Universal/BdsDxe/BootMaint/FE.vfr | 127 - .../Universal/BdsDxe/BootMaint/FileExplorer.c | 469 --- .../Universal/BdsDxe/BootMaint/FormGuid.h | 243 -- .../Universal/BdsDxe/BootMaint/UpdatePage.c | 1391 ------- .../Universal/BdsDxe/BootMaint/Variable.c | 1380 ------- .../Universal/BdsDxe/BootMngr/BootManager.c | 399 -- .../Universal/BdsDxe/BootMngr/BootManager.h | 103 - .../BdsDxe/BootMngr/BootManagerStrings.uni | Bin 3344 -> 0 bytes .../Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr | 50 - .../Universal/BdsDxe/Capsules.c | 233 -- .../Universal/BdsDxe/DeviceMngr/DeviceManager.c | 2591 ------------ .../Universal/BdsDxe/DeviceMngr/DeviceManager.h | 523 --- .../BdsDxe/DeviceMngr/DeviceManagerStrings.uni | Bin 13366 -> 0 bytes .../BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr | 93 - .../Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h | 56 - .../BdsDxe/DeviceMngr/DriverHealthVfr.Vfr | 38 - .../Universal/BdsDxe/FrontPage.c | 1480 ------- .../Universal/BdsDxe/FrontPage.h | 254 -- .../Universal/BdsDxe/FrontPageStrings.uni | Bin 9974 -> 0 bytes .../Universal/BdsDxe/FrontPageVfr.Vfr | 137 - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c | 597 --- IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h | 67 - .../Universal/BdsDxe/HwErrRecSupport.c | 48 - .../Universal/BdsDxe/HwErrRecSupport.h | 32 - .../Universal/BdsDxe/Language.c | 499 --- .../Universal/BdsDxe/Language.h | 51 - .../Universal/BdsDxe/MemoryTest.c | 436 -- IntelFrameworkModulePkg/Universal/BdsDxe/String.c | 59 - IntelFrameworkModulePkg/Universal/BdsDxe/String.h | 65 - .../Universal/BdsDxe/Strings.uni | Bin 7444 -> 0 bytes .../Universal/Console/VgaClassDxe/ComponentName.c | 167 - .../Universal/Console/VgaClassDxe/VgaClass.c | 1288 ------ .../Universal/Console/VgaClassDxe/VgaClass.h | 484 --- .../Universal/Console/VgaClassDxe/VgaClassDxe.inf | 64 - .../Universal/Console/VgaClassDxe/VgaClassDxe.uni | Bin 2006 -> 0 bytes .../Console/VgaClassDxe/VgaClassDxeExtra.uni | Bin 1346 -> 0 bytes IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c | 536 --- IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h | 226 - .../Universal/CpuIoDxe/CpuIoDxe.inf | 51 - .../Universal/CpuIoDxe/CpuIoDxe.uni | Bin 2066 -> 0 bytes .../Universal/CpuIoDxe/CpuIoDxeExtra.uni | Bin 1338 -> 0 bytes .../Universal/DataHubDxe/DataHub.c | 587 --- .../Universal/DataHubDxe/DataHub.h | 131 - .../Universal/DataHubDxe/DataHubDxe.inf | 85 - .../Universal/DataHubDxe/DataHubDxe.uni | Bin 8204 -> 0 bytes .../Universal/DataHubDxe/DataHubDxeExtra.uni | Bin 1332 -> 0 bytes .../Universal/DataHubStdErrDxe/DataHubStdErr.c | 151 - .../DataHubStdErrDxe/DataHubStdErrDxe.inf | 57 - .../DataHubStdErrDxe/DataHubStdErrDxe.uni | Bin 1992 -> 0 bytes .../DataHubStdErrDxe/DataHubStdErrDxeExtra.uni | Bin 1358 -> 0 bytes .../Universal/FirmwareVolume/FwVolDxe/Ffs.c | 608 --- .../Universal/FirmwareVolume/FwVolDxe/FwPadFile.c | 1228 ------ .../Universal/FirmwareVolume/FwVolDxe/FwVol.c | 798 ---- .../FirmwareVolume/FwVolDxe/FwVolAttrib.c | 220 - .../FirmwareVolume/FwVolDxe/FwVolDriver.h | 761 ---- .../Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf | 74 - .../Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni | Bin 1960 -> 0 bytes .../FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni | Bin 1354 -> 0 bytes .../Universal/FirmwareVolume/FwVolDxe/FwVolRead.c | 629 --- .../Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c | 1586 ------- .../FirmwareVolume/UpdateDriverDxe/FlashUpdate.c | 1218 ------ .../UpdateDriverDxe/ParseUpdateProfile.c | 1133 ----- .../UpdateDriverDxe/UpdateDispatcher.c | 846 ---- .../FirmwareVolume/UpdateDriverDxe/UpdateDriver.h | 213 - .../UpdateDriverDxe/UpdateDriverDxe.inf | 76 - .../UpdateDriverDxe/UpdateDriverDxe.uni | Bin 2360 -> 0 bytes .../UpdateDriverDxe/UpdateDriverDxeExtra.uni | Bin 1366 -> 0 bytes .../UpdateDriverDxe/UpdateStrings.uni | Bin 2410 -> 0 bytes .../Universal/LegacyRegionDxe/LegacyRegion.c | 170 - .../Universal/LegacyRegionDxe/LegacyRegionDxe.inf | 55 - .../Universal/LegacyRegionDxe/LegacyRegionDxe.uni | Bin 3044 -> 0 bytes .../LegacyRegionDxe/LegacyRegionDxeExtra.uni | Bin 1362 -> 0 bytes .../SectionExtractionDxe/SectionExtraction.c | 1456 ------- .../SectionExtractionDxe/SectionExtractionDxe.inf | 57 - .../SectionExtractionDxe/SectionExtractionDxe.uni | Bin 2552 -> 0 bytes .../SectionExtractionDxeExtra.uni | Bin 1400 -> 0 bytes .../DataHubStatusCodeWorker.c | 376 -- .../DatahubStatusCodeHandlerDxe.c | 88 - .../DatahubStatusCodeHandlerDxe.h | 91 - .../DatahubStatusCodeHandlerDxe.inf | 72 - .../DatahubStatusCodeHandlerDxe.uni | Bin 1782 -> 0 bytes .../DatahubStatusCodeHandlerDxeExtra.uni | Bin 1390 -> 0 bytes .../StatusCode/Pei/MemoryStausCodeWorker.c | 118 - .../StatusCode/Pei/SerialStatusCodeWorker.c | 162 - .../Universal/StatusCode/Pei/StatusCodePei.c | 146 - .../Universal/StatusCode/Pei/StatusCodePei.h | 147 - .../Universal/StatusCode/Pei/StatusCodePei.inf | 78 - .../Universal/StatusCode/Pei/StatusCodePei.uni | Bin 1718 -> 0 bytes .../StatusCode/Pei/StatusCodePeiExtra.uni | Bin 1344 -> 0 bytes .../RuntimeDxe/DataHubStatusCodeWorker.c | 390 -- .../RuntimeDxe/RtMemoryStatusCodeWorker.c | 104 - .../StatusCode/RuntimeDxe/SerialStatusCodeWorker.c | 160 - .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c | 301 -- .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h | 240 -- .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf | 88 - .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni | Bin 1886 -> 0 bytes .../RuntimeDxe/StatusCodeRuntimeDxeExtra.uni | Bin 1374 -> 0 bytes 720 files changed, 133851 insertions(+), 133851 deletions(-) create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeData.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Contributions.txt create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.S create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.asm create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.S create mode 100644 Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.asm create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/AcpiVariableCompatibility.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/BdsHii.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/BlockIoVendor.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/CapsuleDataFile.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/HdBootVariable.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/IntelFrameworkModulePkgTokenSpace.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/LastEnumLang.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/LegacyBios.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/LegacyDevOrder.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Guid/TianoDecompress.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Library/GenericBdsLib.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Library/PlatformBdsLib.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Protocol/ExitPmAuth.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Protocol/IsaIo.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Protocol/OEMBadging.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Protocol/Ps2Policy.h create mode 100644 Core/IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h create mode 100644 Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec create mode 100644 Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc create mode 100644 Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.uni create mode 100644 Core/IntelFrameworkModulePkg/IntelFrameworkModulePkgExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c create mode 100644 Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLibInternals.h create mode 100644 Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoDecompressLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c create mode 100644 Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/ReportStatusCodeLib.c create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c create mode 100644 Core/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/GuidedSectionExtraction.c create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchDecompressLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Types.h create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/history.txt create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/lzma.txt create mode 100644 Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/UefiLzma.h create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.c create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.c create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c create mode 100644 Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h create mode 100644 Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLib.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformData.c create mode 100644 Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLib.c create mode 100644 Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLibInternal.h create mode 100644 Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf create mode 100644 Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.uni create mode 100644 Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c create mode 100644 Core/IntelFrameworkModulePkg/License.txt create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportAcpiSupportProtocol.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DriverHealthVfr.Vfr create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/String.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/String.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/ComponentName.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErr.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwPadFile.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolAttrib.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDriver.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolRead.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/FlashUpdate.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriver.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateStrings.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegion.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxeExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/MemoryStausCodeWorker.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/SerialStatusCodeWorker.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePeiExtra.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni create mode 100644 Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.h delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeData.h delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf delete mode 100644 IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni delete mode 100644 IntelFrameworkModulePkg/Contributions.txt delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h delete mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.S delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.asm delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.S delete mode 100644 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.asm delete mode 100644 IntelFrameworkModulePkg/Include/Guid/AcpiVariableCompatibility.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/BdsHii.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/BlockIoVendor.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/CapsuleDataFile.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/HdBootVariable.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/IntelFrameworkModulePkgTokenSpace.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/LastEnumLang.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/LegacyBios.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/LegacyDevOrder.h delete mode 100644 IntelFrameworkModulePkg/Include/Guid/TianoDecompress.h delete mode 100644 IntelFrameworkModulePkg/Include/Library/GenericBdsLib.h delete mode 100644 IntelFrameworkModulePkg/Include/Library/PlatformBdsLib.h delete mode 100644 IntelFrameworkModulePkg/Include/Protocol/ExitPmAuth.h delete mode 100644 IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h delete mode 100644 IntelFrameworkModulePkg/Include/Protocol/IsaIo.h delete mode 100644 IntelFrameworkModulePkg/Include/Protocol/OEMBadging.h delete mode 100644 IntelFrameworkModulePkg/Include/Protocol/Ps2Policy.h delete mode 100644 IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h delete mode 100644 IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec delete mode 100644 IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc delete mode 100644 IntelFrameworkModulePkg/IntelFrameworkModulePkg.uni delete mode 100644 IntelFrameworkModulePkg/IntelFrameworkModulePkgExtra.uni delete mode 100644 IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c delete mode 100644 IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLibInternals.h delete mode 100644 IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoDecompressLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c delete mode 100644 IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/ReportStatusCodeLib.c delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/String.c delete mode 100644 IntelFrameworkModulePkg/Library/GenericBdsLib/String.h delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.h delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/GuidedSectionExtraction.c delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchDecompressLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.h delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Types.h delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/history.txt delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/lzma.txt delete mode 100644 IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/UefiLzma.h delete mode 100644 IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c delete mode 100644 IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf delete mode 100644 IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.uni delete mode 100644 IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.c delete mode 100644 IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf delete mode 100644 IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.c delete mode 100644 IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf delete mode 100644 IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.uni delete mode 100644 IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c delete mode 100644 IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h delete mode 100644 IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLib.uni delete mode 100644 IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf delete mode 100644 IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformData.c delete mode 100644 IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLib.c delete mode 100644 IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLibInternal.h delete mode 100644 IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf delete mode 100644 IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.uni delete mode 100644 IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c delete mode 100644 IntelFrameworkModulePkg/License.txt delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.c delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.h delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportAcpiSupportProtocol.c delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DriverHealthVfr.Vfr delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/Language.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/Language.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/String.c delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/String.h delete mode 100644 IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni delete mode 100644 IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/ComponentName.c delete mode 100644 IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.c delete mode 100644 IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.h delete mode 100644 IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c delete mode 100644 IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h delete mode 100644 IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.h delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErr.c delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwPadFile.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolAttrib.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDriver.h delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolRead.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/FlashUpdate.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriver.h delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateStrings.uni delete mode 100644 IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegion.c delete mode 100644 IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c delete mode 100644 IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxeExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/Pei/MemoryStausCodeWorker.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/Pei/SerialStatusCodeWorker.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.h delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.uni delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePeiExtra.uni delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni delete mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c new file mode 100644 index 0000000000..1663d7fcd5 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c @@ -0,0 +1,182 @@ +/** @file + UEFI Component Name(2) protocol implementation for IsaBus 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 "InternalIsaBus.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaBusComponentName = { + IsaBusComponentNameGetDriverName, + IsaBusComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaBusComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaBusComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaBusComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaBusDriverNameTable[] = { + { + "eng;en", + L"ISA Bus Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +IsaBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mIsaBusDriverNameTable, + DriverName, + (BOOLEAN)(This == &gIsaBusComponentName) + ); +} + +/** + 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 +IsaBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h new file mode 100644 index 0000000000..ffacf44063 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h @@ -0,0 +1,148 @@ +/** @file + Header file for implementation of UEFI Component Name(2) protocol. + +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 _COMPONENT_NAME_H_ +#define _COMPONENT_NAME_H_ + +extern EFI_COMPONENT_NAME_PROTOCOL gIsaBusComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gIsaBusComponentName2; + +/** + 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 +IsaBusComponentNameGetDriverName ( + 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 +IsaBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h new file mode 100644 index 0000000000..9e559da72b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h @@ -0,0 +1,297 @@ +/** @file + The header file for ISA bus driver + +Copyright (c) 2006 - 2009, Intel 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_ISA_BUS_H_ +#define _INTERNAL_ISA_BUS_H_ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ComponentName.h" + +// +// 8237 DMA registers +// +#define R_8237_DMA_BASE_CA_CH0 0x00 +#define R_8237_DMA_BASE_CA_CH1 0x02 +#define R_8237_DMA_BASE_CA_CH2 0x04 +#define R_8237_DMA_BASE_CA_CH3 0xd6 +#define R_8237_DMA_BASE_CA_CH5 0xc4 +#define R_8237_DMA_BASE_CA_CH6 0xc8 +#define R_8237_DMA_BASE_CA_CH7 0xcc + +#define R_8237_DMA_BASE_CC_CH0 0x01 +#define R_8237_DMA_BASE_CC_CH1 0x03 +#define R_8237_DMA_BASE_CC_CH2 0x05 +#define R_8237_DMA_BASE_CC_CH3 0xd7 +#define R_8237_DMA_BASE_CC_CH5 0xc6 +#define R_8237_DMA_BASE_CC_CH6 0xca +#define R_8237_DMA_BASE_CC_CH7 0xce + +#define R_8237_DMA_MEM_LP_CH0 0x87 +#define R_8237_DMA_MEM_LP_CH1 0x83 +#define R_8237_DMA_MEM_LP_CH2 0x81 +#define R_8237_DMA_MEM_LP_CH3 0x82 +#define R_8237_DMA_MEM_LP_CH5 0x8B +#define R_8237_DMA_MEM_LP_CH6 0x89 +#define R_8237_DMA_MEM_LP_CH7 0x8A + + +#define R_8237_DMA_COMMAND_CH0_3 0x08 +#define R_8237_DMA_COMMAND_CH4_7 0xd0 +#define B_8237_DMA_COMMAND_GAP 0x10 +#define B_8237_DMA_COMMAND_CGE 0x04 + + +#define R_8237_DMA_STA_CH0_3 0xd8 +#define R_8237_DMA_STA_CH4_7 0xd0 + +#define R_8237_DMA_WRSMSK_CH0_3 0x0a +#define R_8237_DMA_WRSMSK_CH4_7 0xd4 +#define B_8237_DMA_WRSMSK_CMS 0x04 + + +#define R_8237_DMA_CHMODE_CH0_3 0x0b +#define R_8237_DMA_CHMODE_CH4_7 0xd6 +#define V_8237_DMA_CHMODE_DEMAND 0x00 +#define V_8237_DMA_CHMODE_SINGLE 0x40 +#define V_8237_DMA_CHMODE_CASCADE 0xc0 +#define B_8237_DMA_CHMODE_DECREMENT 0x20 +#define B_8237_DMA_CHMODE_INCREMENT 0x00 +#define B_8237_DMA_CHMODE_AE 0x10 +#define V_8237_DMA_CHMODE_VERIFY 0 +#define V_8237_DMA_CHMODE_IO2MEM 0x04 +#define V_8237_DMA_CHMODE_MEM2IO 0x08 + +#define R_8237_DMA_CBPR_CH0_3 0x0c +#define R_8237_DMA_CBPR_CH4_7 0xd8 + +#define R_8237_DMA_MCR_CH0_3 0x0d +#define R_8237_DMA_MCR_CH4_7 0xda + +#define R_8237_DMA_CLMSK_CH0_3 0x0e +#define R_8237_DMA_CLMSK_CH4_7 0xdc + +#define R_8237_DMA_WRMSK_CH0_3 0x0f +#define R_8237_DMA_WRMSK_CH4_7 0xde + +typedef enum { + IsaAccessTypeUnknown, + IsaAccessTypeIo, + IsaAccessTypeMem, + IsaAccessTypeMaxType +} ISA_ACCESS_TYPE; + +// +// 16 MB Memory Range +// +#define ISA_MAX_MEMORY_ADDRESS 0x1000000 +// +// 64K I/O Range +// +#define ISA_MAX_IO_ADDRESS 0x10000 + +typedef struct { + UINT8 Address; + UINT8 Page; + UINT8 Count; +} EFI_ISA_DMA_REGISTERS; + +// +// ISA I/O Device Structure +// +#define ISA_IO_DEVICE_SIGNATURE SIGNATURE_32 ('i', 's', 'a', 'i') + +typedef struct { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_ISA_IO_PROTOCOL IsaIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; +} ISA_IO_DEVICE; + +#define ISA_IO_DEVICE_FROM_ISA_IO_THIS(a) CR (a, ISA_IO_DEVICE, IsaIo, ISA_IO_DEVICE_SIGNATURE) + +// +// Mapping structure for performing ISA DMA to a buffer above 16 MB +// +typedef struct { + EFI_ISA_IO_PROTOCOL_OPERATION Operation; + UINTN NumberOfBytes; + UINTN NumberOfPages; + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS MappedHostAddress; +} ISA_MAP_INFO; + +// +// EFI Driver Binding Protocol Interface Functions +// + +/** + Tests to see if a controller can be managed by the ISA Bus Driver. If a child device is provided, + it further tests to see if this driver supports creating a handle for the specified child device. + + Note that the ISA Bus driver always creates all of its child handles on the first call to Start(). + How the Start() function of a driver is implemented can affect how the Supported() function is implemented. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of the controller to test. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The device is supported by this driver. + @retval EFI_ALREADY_STARTED The device is already being managed by this driver. + @retval EFI_ACCESS_DENIED The device is already being managed by a different driver + or an application that requires exclusive access. + @retval EFI_UNSUPPORTED The device is is not supported by this driver. + +**/ +EFI_STATUS +EFIAPI +IsaBusControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Start this driver on ControllerHandle. + + Note that the ISA Bus driver always creates all of its child handles on the first call to Start(). + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, but the following calling + restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + This parameter is ignored by device drivers, and is optional for bus drivers. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. +**/ +EFI_STATUS +EFIAPI +IsaBusControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Stop this driver on ControllerHandle. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +IsaBusControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer OPTIONAL + ); + +// +// Function Prototypes +// + +/** + Create EFI Handle for a ISA device found via ISA ACPI Protocol + + @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of ISA bus controller(PCI to ISA bridge) + @param[in] PciIo The Pointer to the PCI protocol + @param[in] ParentDevicePath Device path of the ISA bus controller + @param[in] IsaDeviceResourceList The resource list of the ISA device + @param[out] ChildDevicePath The pointer to the child device. + + @retval EFI_SUCCESS The handle for the child device was created. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The handle for the child device can not be created. +**/ +EFI_STATUS +IsaCreateDevice ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList, + OUT EFI_DEVICE_PATH_PROTOCOL **ChildDevicePath + ); + +/** + Initializes an ISA I/O Instance + + @param[in] IsaIoDevice The iso device to be initialized. + @param[in] IsaDeviceResourceList The resource list. + +**/ +VOID +InitializeIsaIoInstance ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDevice + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h new file mode 100644 index 0000000000..054a6b9bab --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h @@ -0,0 +1,331 @@ +/** @file + The header file for EFI_ISA_IO protocol implementation. + +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 _INTERNAL_ISA_IO_H_ +#define _INTERNAL_ISA_IO_H_ + +#include "InternalIsaBus.h" + +// +// Bits definition of PcdIsaBusSupportedFeatures +// +#define PCD_ISA_BUS_SUPPORT_DMA BIT0 +#define PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA BIT1 +#define PCD_ISA_BUS_SUPPORT_ISA_MEMORY BIT2 + +// +// ISA I/O Support Function Prototypes +// + +/** + Verifies access to an ISA device + + @param[in] IsaIoDevice The ISA device to be verified. + @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. + @param[in] Width The width of the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Offset The offset in ISA memory space to start the memory operation. + + @retval EFI_SUCCESS Verify success. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The device ont support the access type. +**/ +EFI_STATUS +IsaIoVerifyAccess ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN ISA_ACCESS_TYPE Type, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT32 Offset + ); + +/** + Performs an ISA I/O Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Performs an ISA I/O Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was writen to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Maps a memory region for DMA + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoMap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Unmaps a memory region for DMA + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +EFI_STATUS +EFIAPI +IsaIoUnmap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Flushes any posted write data to the system memory. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. +**/ +EFI_STATUS +EFIAPI +IsaIoFlush ( + IN EFI_ISA_IO_PROTOCOL *This + ); + +/** + Writes I/O operation base address and count number to a 8 bit I/O Port. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] AddrOffset The address' offset. + @param[in] PageOffset The page's offest. + @param[in] CountOffset The count's offset. + @param[in] BaseAddress The base address. + @param[in] Count The number of I/O operations to perform. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WriteDmaPort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 AddrOffset, + IN UINT32 PageOffset, + IN UINT32 CountOffset, + IN UINT32 BaseAddress, + IN UINT16 Count + ); + +/** + Writes an 8-bit I/O Port + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Offset The offset in ISA IO space to start the IO operation. + @param[in] Value The data to write port. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WritePort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 Value + ); + +/** + Performs an ISA Memory Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device successfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ); + + +/** + Performs an ISA Memory Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was written to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory copy operation. + @param[in] DestOffset The offset of the destination + @param[in] SrcOffset The offset of the source + @param[in] Count The number of memory copy operations to perform + + @retval EFI_SUCCESS The data was copied sucessfully. + @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoCopyMem ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ); + +/** + Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Type The type allocation to perform. + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base address of the allocated range. + @param[in] Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL + @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified + by HostAddress, Pages, and Type is not available for common buffer use. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoAllocateBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Pages The number of pages to free. + @param[in] HostAddress The base address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). +**/ +EFI_STATUS +EFIAPI +IsaIoFreeBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c new file mode 100644 index 0000000000..1312f260f9 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c @@ -0,0 +1,673 @@ +/** @file + ISA Bus UEFI driver. + + Discovers all the ISA Controllers and their resources by using the ISA ACPI + Protocol, produces an instance of the ISA I/O Protocol for every ISA + Controller found. This driver is designed to manage a PCI-to-ISA bridge Device + such as LPC bridge. + +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 +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 "InternalIsaBus.h" + +// +// ISA Bus Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver = { + IsaBusControllerDriverSupported, + IsaBusControllerDriverStart, + IsaBusControllerDriverStop, + 0xa, + NULL, + NULL +}; + +/** + The main entry point for the ISA Bus 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 EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. +**/ +EFI_STATUS +EFIAPI +InitializeIsaBus( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gIsaBusControllerDriver, + ImageHandle, + &gIsaBusComponentName, + &gIsaBusComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Tests to see if a controller can be managed by the ISA Bus Driver. If a child device is provided, + it further tests to see if this driver supports creating a handle for the specified child device. + + Note that the ISA Bus driver always creates all of its child handles on the first call to Start(). + How the Start() function of a driver is implemented can affect how the Supported() function is implemented. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of the controller to test. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The device is supported by this driver. + @retval EFI_ALREADY_STARTED The device is already being managed by this driver. + @retval EFI_ACCESS_DENIED The device is already being managed by a different driver + or an application that requires exclusive access. + @retval EFI_UNSUPPORTED The device is is not supported by this driver. + +**/ +EFI_STATUS +EFIAPI +IsaBusControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_ISA_ACPI_PROTOCOL *IsaAcpi; + + // + // If RemainingDevicePath is not NULL, it should verify that the first device + // path node in RemainingDevicePath is an ACPI Device path node which is a + // legal Device Path Node for this bus driver's children. + // + if (RemainingDevicePath != NULL) { + if (RemainingDevicePath->Type != ACPI_DEVICE_PATH) { + return EFI_UNSUPPORTED; + } else if (RemainingDevicePath->SubType == ACPI_DP) { + if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_HID_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } else if (RemainingDevicePath->SubType == ACPI_EXTENDED_DP) { + if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } else { + return EFI_UNSUPPORTED; + } + } + // + // Try to open EFI DEVICE PATH protocol on the controller + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + // + // Although this driver creates all child handles at one time, + // but because all child handles may be not stopped at one time in EFI Driver Binding.Stop(), + // So it is allowed to create child handles again in successive calls to EFI Driver Binding.Start(). + // + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Try to get Pci IO Protocol because it is assumed + // to have been opened by ISA ACPI driver + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Try to open the Isa Acpi protocol on the controller + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaAcpiProtocolGuid, + (VOID **) &IsaAcpi, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Add more check to see if the child device is valid by calling IsaAcpi->DeviceEnumerate? + // + + gBS->CloseProtocol ( + Controller, + &gEfiIsaAcpiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Start this driver on ControllerHandle. + + Note that the ISA Bus driver always creates all of its child handles on the first call to Start(). + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, but the following calling + restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + This parameter is ignored by device drivers, and is optional for bus drivers. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. +**/ +EFI_STATUS +EFIAPI +IsaBusControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_ISA_ACPI_PROTOCOL *IsaAcpi; + EFI_ISA_ACPI_DEVICE_ID *IsaDevice; + EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; + EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; + + // + // Local variables declaration for StatusCode reporting + // + EFI_DEVICE_PATH_PROTOCOL *DevicePathData; + + DevicePathData = NULL; + + // + // Get Pci IO Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open Device Path Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + // + // Open ISA Acpi Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaAcpiProtocolGuid, + (VOID **) &IsaAcpi, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + // + // Close opened protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + // + // The IsaBus driver will use memory below 16M, which is not tested yet, + // so call CompatibleRangeTest to test them. Since memory below 1M should + // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M + // ~15M here + // + Status = gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + (VOID **) &GenMemoryTest + ); + + if (!EFI_ERROR (Status)) { + Status = GenMemoryTest->CompatibleRangeTest ( + GenMemoryTest, + 0x100000, + 0xE00000 + ); + } + // + // Report Status Code here since we will initialize the host controller + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT), + ParentDevicePath + ); + + // + // first init ISA interface + // + IsaAcpi->InterfaceInit (IsaAcpi); + + // + // Report Status Code here since we will enable the host controller + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE), + ParentDevicePath + ); + + // + // Create each ISA device handle in this ISA bus + // + IsaDevice = NULL; + do { + Status = IsaAcpi->DeviceEnumerate (IsaAcpi, &IsaDevice); + if (EFI_ERROR (Status)) { + break; + } + // + // Get current resource of this ISA device + // + ResourceList = NULL; + Status = IsaAcpi->GetCurResource (IsaAcpi, IsaDevice, &ResourceList); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Create handle for this ISA device + // + // If any child device handle was created in previous call to Start() and not stopped + // in previous call to Stop(), it will not be created again because the + // InstallMultipleProtocolInterfaces() boot service will reject same device path. + // + Status = IsaCreateDevice ( + This, + Controller, + PciIo, + ParentDevicePath, + ResourceList, + &DevicePathData + ); + + if (EFI_ERROR (Status)) { + continue; + } + // + // Initialize ISA device + // + IsaAcpi->InitDevice (IsaAcpi, IsaDevice); + + // + // Set resources for this ISA device + // + Status = IsaAcpi->SetResource (IsaAcpi, IsaDevice, ResourceList); + + // + // Report Status Code here when failed to resource conflicts + // + if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) { + // + // It's hard to tell which resource conflicts + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE, + (EFI_IO_BUS_LPC | EFI_IOB_EC_RESOURCE_CONFLICT), + DevicePathData + ); + + } + // + // Set power for this ISA device + // + IsaAcpi->SetPower (IsaAcpi, IsaDevice, TRUE); + + // + // Enable this ISA device + // + IsaAcpi->EnableDevice (IsaAcpi, IsaDevice, TRUE); + + } while (TRUE); + + return EFI_SUCCESS; +} + +/** + Stop this driver on ControllerHandle. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +IsaBusControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + ISA_IO_DEVICE *IsaIoDevice; + EFI_ISA_IO_PROTOCOL *IsaIo; + EFI_PCI_IO_PROTOCOL *PciIo; + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol ( + Controller, + &gEfiIsaAcpiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; + } + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + // + // Stop all the children + // Find all the ISA devices that were discovered on this PCI to ISA Bridge + // with the Start() function. + // + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo); + + // + // Close the child handle + // + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + IsaIoDevice->DevicePath, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + + if (!EFI_ERROR (Status)) { + FreePool (IsaIoDevice->DevicePath); + FreePool (IsaIoDevice); + } else { + // + // Re-open PCI IO Protocol on behalf of the child device + // because of failure of destroying the child device handle + // + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +// +// Internal Function +// + +/** + Create EFI Handle for a ISA device found via ISA ACPI Protocol + + @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of ISA bus controller(PCI to ISA bridge) + @param[in] PciIo The Pointer to the PCI protocol + @param[in] ParentDevicePath Device path of the ISA bus controller + @param[in] IsaDeviceResourceList The resource list of the ISA device + @param[out] ChildDevicePath The pointer to the child device. + + @retval EFI_SUCCESS The handle for the child device was created. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The handle for the child device can not be created. +**/ +EFI_STATUS +IsaCreateDevice ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList, + OUT EFI_DEVICE_PATH_PROTOCOL **ChildDevicePath + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + EFI_DEV_PATH Node; + + // + // Initialize the PCI_IO_DEVICE structure + // + IsaIoDevice = AllocateZeroPool (sizeof (ISA_IO_DEVICE)); + if (IsaIoDevice == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + IsaIoDevice->Signature = ISA_IO_DEVICE_SIGNATURE; + IsaIoDevice->Handle = NULL; + IsaIoDevice->PciIo = PciIo; + + // + // Initialize the ISA I/O instance structure + // + InitializeIsaIoInstance (IsaIoDevice, IsaDeviceResourceList); + + // + // Build the child device path + // + Node.DevPath.Type = ACPI_DEVICE_PATH; + Node.DevPath.SubType = ACPI_DP; + SetDevicePathNodeLength (&Node.DevPath, sizeof (ACPI_HID_DEVICE_PATH)); + Node.Acpi.HID = IsaDeviceResourceList->Device.HID; + Node.Acpi.UID = IsaDeviceResourceList->Device.UID; + + IsaIoDevice->DevicePath = AppendDevicePathNode ( + ParentDevicePath, + &Node.DevPath + ); + + if (IsaIoDevice->DevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + *ChildDevicePath = IsaIoDevice->DevicePath; + + // + // Create a child handle and install Device Path and ISA I/O protocols + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &IsaIoDevice->Handle, + &gEfiDevicePathProtocolGuid, + IsaIoDevice->DevicePath, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + IsaIoDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + IsaIoDevice->Handle, + &gEfiDevicePathProtocolGuid, + IsaIoDevice->DevicePath, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + } + +Done: + + if (EFI_ERROR (Status)) { + if (IsaIoDevice->DevicePath != NULL) { + FreePool (IsaIoDevice->DevicePath); + } + + FreePool (IsaIoDevice); + } + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf new file mode 100644 index 0000000000..be6dd43ea6 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf @@ -0,0 +1,73 @@ +## @file +# Generates ISA I/O Protocols based on the ISA ACPI Protocol instances. +# +# Discovers all the ISA Controllers and their resources by using the ISA ACPI +# Protocol, produces an instance of the ISA I/O Protocol for every ISA +# Controller found. This driver is designed to manage a PCI-to-ISA bridge Device +# such as an LPC bridge. +# +# 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 +# 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 = IsaBusDxe + MODULE_UNI_FILE = IsaBusDxe.uni + FILE_GUID = 240612B5-A063-11d4-9A3A-0090273FC14D + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeIsaBus + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# DRIVER_BINDING = gIsaBusControllerDriver +# COMPONENT_NAME = gIsaBusComponentName; +# COMPONENT_NAME2 = gIsaBusComponentName2; +# + +[Sources] + ComponentName.c + IsaIo.c + IsaBus.c + InternalIsaIo.h + InternalIsaBus.h + ComponentName.h + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PcdLib + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + DevicePathLib + UefiLib + UefiDriverEntryPoint + DebugLib + +[Protocols] + gEfiIsaIoProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## BY_START + gEfiIsaAcpiProtocolGuid ## TO_START + gEfiPciIoProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## TO_START + gEfiGenericMemTestProtocolGuid ## TO_START + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures ## CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + IsaBusDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.uni new file mode 100644 index 0000000000..204dc2d336 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni new file mode 100644 index 0000000000..47d9737806 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c new file mode 100644 index 0000000000..6f1cd1b8b1 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c @@ -0,0 +1,1463 @@ +/** @file + The implementation for EFI_ISA_IO_PROTOCOL. + +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 "InternalIsaIo.h" + +// +// Module Variables +// +EFI_ISA_IO_PROTOCOL mIsaIoInterface = { + { + IsaIoMemRead, + IsaIoMemWrite + }, + { + IsaIoIoRead, + IsaIoIoWrite + }, + IsaIoCopyMem, + IsaIoMap, + IsaIoUnmap, + IsaIoAllocateBuffer, + IsaIoFreeBuffer, + IsaIoFlush, + NULL, + 0, + NULL +}; + +EFI_ISA_DMA_REGISTERS mDmaRegisters[8] = { + { + 0x00, + 0x87, + 0x01 + }, + { + 0x02, + 0x83, + 0x03 + }, + { + 0x04, + 0x81, + 0x05 + }, + { + 0x06, + 0x82, + 0x07 + }, + { + 0x00, + 0x00, + 0x00 + }, // Channel 4 is invalid + { + 0xC4, + 0x8B, + 0xC6 + }, + { + 0xC8, + 0x89, + 0xCA + }, + { + 0xCC, + 0x8A, + 0xCE + }, +}; + +/** + Initializes an ISA I/O Instance + + @param[in] IsaIoDevice The iso device to be initialized. + @param[in] IsaDeviceResourceList The resource list. + +**/ +VOID +InitializeIsaIoInstance ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList + ) +{ + // + // Use the ISA IO Protocol structure template to initialize the ISA IO instance + // + CopyMem ( + &IsaIoDevice->IsaIo, + &mIsaIoInterface, + sizeof (EFI_ISA_IO_PROTOCOL) + ); + + IsaIoDevice->IsaIo.ResourceList = IsaDeviceResourceList; +} + +/** + Performs an ISA I/O Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeIo, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Io.Read ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Performs an ISA I/O Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was writen to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeIo, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Io.Write ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Writes an 8-bit I/O Port + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Offset The offset in ISA IO space to start the IO operation. + @param[in] Value The data to write port. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WritePort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + Status = IsaIoDevice->PciIo->Io.Write ( + IsaIoDevice->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + 1, + &Value + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + return Status; + } + + gBS->Stall (50); + + return EFI_SUCCESS; +} + +/** + Writes I/O operation base address and count number to a 8 bit I/O Port. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] AddrOffset The address' offset. + @param[in] PageOffset The page's offest. + @param[in] CountOffset The count's offset. + @param[in] BaseAddress The base address. + @param[in] Count The number of I/O operations to perform. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WriteDmaPort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 AddrOffset, + IN UINT32 PageOffset, + IN UINT32 CountOffset, + IN UINT32 BaseAddress, + IN UINT16 Count + ) +{ + EFI_STATUS Status; + + Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff)); + return Status; +} + +/** + Unmaps a memory region for DMA + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +EFI_STATUS +EFIAPI +IsaIoUnmap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + ISA_MAP_INFO *IsaMapInfo; + + // + // Check if DMA is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { + return EFI_UNSUPPORTED; + } + + // + // See if the Map() operation associated with this Unmap() required a mapping + // buffer.If a mapping buffer was not required, then this function simply + // returns EFI_SUCCESS. + // + if (Mapping != NULL) { + // + // Get the MAP_INFO structure from Mapping + // + IsaMapInfo = (ISA_MAP_INFO *) Mapping; + + // + // If this is a write operation from the Agent's point of view, + // then copy the contents of the mapped buffer into the real buffer + // so the processor can read the contents of the real buffer. + // + if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->HostAddress, + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // Free the mapped buffer and the MAP_INFO structure. + // + gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages); + FreePool (IsaMapInfo); + } + + return EFI_SUCCESS; +} + +/** + Flushes any posted write data to the system memory. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. +**/ +EFI_STATUS +EFIAPI +IsaIoFlush ( + IN EFI_ISA_IO_PROTOCOL *This + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Verifies access to an ISA device + + @param[in] IsaIoDevice The ISA device to be verified. + @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. + @param[in] Width The width of the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Offset The offset in ISA memory space to start the memory operation. + + @retval EFI_SUCCESS Verify success. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The device ont support the access type. +**/ +EFI_STATUS +IsaIoVerifyAccess ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN ISA_ACCESS_TYPE Type, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT32 Offset + ) +{ + EFI_ISA_ACPI_RESOURCE *Item; + EFI_STATUS Status; + + if ((UINT32)Width >= EfiIsaIoWidthMaximum || + Width == EfiIsaIoWidthReserved || + Width == EfiIsaIoWidthFifoReserved || + Width == EfiIsaIoWidthFillReserved + ) { + return EFI_INVALID_PARAMETER; + } + + // + // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX + // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX + // + if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) { + Count = 1; + } + + Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03); + + Status = EFI_UNSUPPORTED; + Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem; + while (Item->Type != EfiIsaAcpiResourceEndOfList) { + if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) || + (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) { + if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) { + return EFI_SUCCESS; + } + + if (Offset >= Item->StartRange && Offset <= Item->EndRange) { + Status = EFI_INVALID_PARAMETER; + } + } + + Item++; + } + + return Status; +} + +/** + Performs an ISA Memory Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device successfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify the Isa Io Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Mem.Read ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Performs an ISA Memory Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was written to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Mem.Write ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory copy operation. + @param[in] DestOffset The offset of the destination + @param[in] SrcOffset The offset of the source + @param[in] Count The number of memory copy operations to perform + + @retval EFI_SUCCESS The data was copied sucessfully. + @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoCopyMem ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access for destination and source + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + DestOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + SrcOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->CopyMem ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + DestOffset, + EFI_PCI_IO_PASS_THROUGH_BAR, + SrcOffset, + Count + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Maps a memory region for DMA, note this implementation + only supports slave read/write operation to save code size. + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +IsaIoMapOnlySupportSlaveReadWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + ISA_MAP_INFO *IsaMapInfo; + UINT8 DmaMode; + UINTN MaxNumberOfBytes; + UINT32 BaseAddress; + UINT16 Count; + UINT8 DmaMask; + UINT8 DmaClear; + UINT8 DmaChannelMode; + + if ((NULL == This) || + (NULL == HostAddress) || + (NULL == NumberOfBytes) || + (NULL == DeviceAddress) || + (NULL == Mapping) + ) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure the Operation parameter is valid. + // Light IsaIo only supports two operations. + // + if (!(Operation == EfiIsaIoOperationSlaveRead || + Operation == EfiIsaIoOperationSlaveWrite)) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber >= 4) { + // + // The Light IsaIo doesn't support channelNumber larger than 4. + // + return EFI_INVALID_PARAMETER; + } + + // + // Map the HostAddress to a DeviceAddress. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + if ((PhysicalAddress + *NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) { + // + // Common Buffer operations can not be remapped. If the common buffer + // is above 16MB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + // + // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() + // is called later. + // + IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); + if (IsaMapInfo == NULL) { + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = IsaMapInfo; + + // + // Initialize the MAP_INFO structure + // + IsaMapInfo->Operation = Operation; + IsaMapInfo->NumberOfBytes = *NumberOfBytes; + IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + IsaMapInfo->HostAddress = PhysicalAddress; + IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1; + + // + // Allocate a buffer below 16MB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + IsaMapInfo->NumberOfPages, + &IsaMapInfo->MappedHostAddress + ); + if (EFI_ERROR (Status)) { + FreePool (IsaMapInfo); + *NumberOfBytes = 0; + *Mapping = NULL; + return Status; + } + // + // If this is a read operation from the DMA agents's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the DMA agent can read the contents of the real buffer. + // + if (Operation == EfiIsaIoOperationSlaveRead) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + (VOID *) (UINTN) IsaMapInfo->HostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // The DeviceAddress is the address of the maped buffer below 16 MB + // + *DeviceAddress = IsaMapInfo->MappedHostAddress; + } else { + // + // The transfer is below 16 MB, so the DeviceAddress is simply the + // HostAddress + // + *DeviceAddress = PhysicalAddress; + } + + // + // Figure out what to program into the DMA Channel Mode Register + // + DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); + if (Operation == EfiIsaIoOperationSlaveRead) { + DmaMode |= V_8237_DMA_CHMODE_MEM2IO; + } else { + DmaMode |= V_8237_DMA_CHMODE_IO2MEM; + } + // + // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo + // + DmaMode |= V_8237_DMA_CHMODE_SINGLE; + + // + // A Slave DMA transfer can not cross a 64K boundary. + // Compute *NumberOfBytes based on this restriction. + // + MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); + if (*NumberOfBytes > MaxNumberOfBytes) { + *NumberOfBytes = MaxNumberOfBytes; + } + // + // Compute the values to program into the BaseAddress and Count registers + // of the Slave DMA controller + // + BaseAddress = (UINT32) (*DeviceAddress); + Count = (UINT16) (*NumberOfBytes - 1); + // + // Program the DMA Write Single Mask Register for ChannelNumber + // Clear the DMA Byte Pointer Register + // + DmaMask = R_8237_DMA_WRSMSK_CH0_3; + DmaClear = R_8237_DMA_CBPR_CH0_3; + DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; + + Status = WritePort ( + This, + DmaMask, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaClear, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, DmaChannelMode, DmaMode); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteDmaPort ( + This, + mDmaRegisters[ChannelNumber].Address, + mDmaRegisters[ChannelNumber].Page, + mDmaRegisters[ChannelNumber].Count, + BaseAddress, + Count + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (ChannelNumber & 0x03) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Maps a memory region for DMA. This implementation implement the + the full mapping support. + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. +**/ +EFI_STATUS +IsaIoMapFullSupport ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + BOOLEAN Master; + BOOLEAN Read; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + ISA_MAP_INFO *IsaMapInfo; + UINT8 DmaMode; + UINTN MaxNumberOfBytes; + UINT32 BaseAddress; + UINT16 Count; + UINT8 DmaMask; + UINT8 DmaClear; + UINT8 DmaChannelMode; + + if ((NULL == This) || + (NULL == HostAddress) || + (NULL == NumberOfBytes) || + (NULL == DeviceAddress) || + (NULL == Mapping) + ) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure the Operation parameter is valid + // + if ((UINT32)Operation >= EfiIsaIoOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber >= 8) { + return EFI_INVALID_PARAMETER; + } + + // + // See if this is a Slave DMA Operation + // + Master = TRUE; + Read = FALSE; + if (Operation == EfiIsaIoOperationSlaveRead) { + Operation = EfiIsaIoOperationBusMasterRead; + Master = FALSE; + Read = TRUE; + } + + if (Operation == EfiIsaIoOperationSlaveWrite) { + Operation = EfiIsaIoOperationBusMasterWrite; + Master = FALSE; + Read = FALSE; + } + + if (!Master) { + // + // Make sure that ChannelNumber is a valid channel number + // Channel 4 is used to cascade, so it is illegal. + // + if (ChannelNumber == 4 || ChannelNumber > 7) { + return EFI_INVALID_PARAMETER; + } + // + // This implementation only support COMPATIBLE DMA Transfers + // + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((ChannelAttributes & + (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A | + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B | + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber < 4) { + // + // If this is Channel 0..3, then the width must be 8 bit + // + if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) || + ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0) + ) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // If this is Channel 4..7, then the width must be 16 bit + // + if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) || + ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) { + return EFI_INVALID_PARAMETER; + } + } + // + // Either Demand Mode or Single Mode must be selected, but not both + // + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { + return EFI_INVALID_PARAMETER; + } + } else { + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) { + return EFI_INVALID_PARAMETER; + } + } + } + // + // Map the HostAddress to a DeviceAddress. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) { + // + // Common Buffer operations can not be remapped. If the common buffer + // is above 16MB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + // + // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() + // is called later. + // + IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); + if (IsaMapInfo == NULL) { + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = IsaMapInfo; + + // + // Initialize the MAP_INFO structure + // + IsaMapInfo->Operation = Operation; + IsaMapInfo->NumberOfBytes = *NumberOfBytes; + IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + IsaMapInfo->HostAddress = PhysicalAddress; + IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1; + + // + // Allocate a buffer below 16MB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + IsaMapInfo->NumberOfPages, + &IsaMapInfo->MappedHostAddress + ); + if (EFI_ERROR (Status)) { + FreePool (IsaMapInfo); + *NumberOfBytes = 0; + *Mapping = NULL; + return Status; + } + // + // If this is a read operation from the DMA agents's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the DMA agent can read the contents of the real buffer. + // + if (Operation == EfiIsaIoOperationBusMasterRead) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + (VOID *) (UINTN) IsaMapInfo->HostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // The DeviceAddress is the address of the maped buffer below 16 MB + // + *DeviceAddress = IsaMapInfo->MappedHostAddress; + } else { + // + // The transfer is below 16 MB, so the DeviceAddress is simply the + // HostAddress + // + *DeviceAddress = PhysicalAddress; + } + // + // If this is a Bus Master operation then return + // + if (Master) { + return EFI_SUCCESS; + } + // + // Figure out what to program into the DMA Channel Mode Register + // + DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); + if (Read) { + DmaMode |= V_8237_DMA_CHMODE_MEM2IO; + } else { + DmaMode |= V_8237_DMA_CHMODE_IO2MEM; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) { + DmaMode |= B_8237_DMA_CHMODE_AE; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { + DmaMode |= V_8237_DMA_CHMODE_DEMAND; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { + DmaMode |= V_8237_DMA_CHMODE_SINGLE; + } + // + // A Slave DMA transfer can not cross a 64K boundary. + // Compute *NumberOfBytes based on this restriction. + // + MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); + if (*NumberOfBytes > MaxNumberOfBytes) { + *NumberOfBytes = MaxNumberOfBytes; + } + // + // Compute the values to program into the BaseAddress and Count registers + // of the Slave DMA controller + // + if (ChannelNumber < 4) { + BaseAddress = (UINT32) (*DeviceAddress); + Count = (UINT16) (*NumberOfBytes - 1); + } else { + BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1)); + Count = (UINT16) ((*NumberOfBytes - 1) >> 1); + } + // + // Program the DMA Write Single Mask Register for ChannelNumber + // Clear the DMA Byte Pointer Register + // + if (ChannelNumber < 4) { + DmaMask = R_8237_DMA_WRSMSK_CH0_3; + DmaClear = R_8237_DMA_CBPR_CH0_3; + DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; + } else { + DmaMask = R_8237_DMA_WRSMSK_CH4_7; + DmaClear = R_8237_DMA_CBPR_CH4_7; + DmaChannelMode = R_8237_DMA_CHMODE_CH4_7; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaClear, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, DmaChannelMode, DmaMode); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteDmaPort ( + This, + mDmaRegisters[ChannelNumber].Address, + mDmaRegisters[ChannelNumber].Page, + mDmaRegisters[ChannelNumber].Count, + BaseAddress, + Count + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (ChannelNumber & 0x03) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Maps a memory region for DMA + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoMap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + // + // Check if DMA is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { + return EFI_UNSUPPORTED; + } + // + // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for + // ISA Bus Master. + // + // So we just return EFI_UNSUPPORTED for these functions. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) { + return IsaIoMapOnlySupportSlaveReadWrite ( + This, + Operation, + ChannelNumber, + ChannelAttributes, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + + } else { + return IsaIoMapFullSupport ( + This, + Operation, + ChannelNumber, + ChannelAttributes, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + } +} + +/** + Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Type The type allocation to perform. + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base address of the allocated range. + @param[in] Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL + @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified + by HostAddress, Pages, and Type is not available for common buffer use. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoAllocateBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + // + // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for + // ISA Bus Master. + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || + ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { + return EFI_UNSUPPORTED; + } + + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32)Type >= MaxAllocateType) { + return EFI_INVALID_PARAMETER; + } + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + // + if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { + return EFI_INVALID_PARAMETER; + } + + if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) { + return EFI_UNSUPPORTED; + } + + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (ISA_MAX_MEMORY_ADDRESS - 1); + if (Type == AllocateAddress) { + if ((UINTN) (*HostAddress) >= ISA_MAX_MEMORY_ADDRESS) { + return EFI_UNSUPPORTED; + } else { + PhysicalAddress = (UINTN) (*HostAddress); + } + } + + if (Type == AllocateAnyPages) { + Type = AllocateMaxAddress; + } + + Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + return Status; + } + + *HostAddress = (VOID *) (UINTN) PhysicalAddress; + return Status; +} + +/** + Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Pages The number of pages to free. + @param[in] HostAddress The base address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). +**/ +EFI_STATUS +EFIAPI +IsaIoFreeBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + EFI_STATUS Status; + + // + // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for + // ISA Bus Master. + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || + ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { + return EFI_UNSUPPORTED; + } + + Status = gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, + Pages + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.c new file mode 100644 index 0000000000..f3341ed884 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.c @@ -0,0 +1,249 @@ +/** @file + UEFI Component Name(2) protocol implementation for Isa Floppy driver. + +Copyright (c) 2006 - 2015, Intel 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 "IsaFloppy.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaFloppyComponentName = { + IsaFloppyComponentNameGetDriverName, + IsaFloppyComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaFloppyComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaFloppyComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaFloppyComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaFloppyDriverNameTable[] = { + { + "eng;en", + L"ISA Floppy Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language 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[out] DriverName 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 +IsaFloppyComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mIsaFloppyDriverNameTable, + DriverName, + (BOOLEAN)(This == &gIsaFloppyComponentName) + ); +} + +/** + 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] 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[in] 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[in] Language 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[out] 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 +IsaFloppyComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + FDC_BLK_IO_DEV *FdcDev; + + if (Language == NULL || ControllerName == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Check if this driver is currently managing ControllerHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gFdcControllerDriver.DriverBindingHandle, + &gEfiIsaIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + gFdcControllerDriver.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + FdcDev->ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gIsaFloppyComponentName) + ); +} + +/** + Add the component name for the floppy device + + @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV instance. + +**/ +VOID +AddName ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + CHAR16 FloppyDriveName[FLOPPY_DRIVE_NAME_LEN + 1]; + + if (!(FeaturePcdGet(PcdComponentNameDisable) && FeaturePcdGet(PcdComponentName2Disable))) { + StrCpyS (FloppyDriveName, FLOPPY_DRIVE_NAME_LEN + 1, FLOPPY_DRIVE_NAME); + FloppyDriveName[FLOPPY_DRIVE_NAME_LEN - 1] = (CHAR16) (L'0' + FdcDev->Disk); + + AddUnicodeString2 ( + "eng", + gIsaFloppyComponentName.SupportedLanguages, + &FdcDev->ControllerNameTable, + FloppyDriveName, + TRUE + ); + AddUnicodeString2 ( + "en", + gIsaFloppyComponentName2.SupportedLanguages, + &FdcDev->ControllerNameTable, + FloppyDriveName, + FALSE + ); + } +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.h new file mode 100644 index 0000000000..a136022ceb --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.h @@ -0,0 +1,146 @@ +/** @file + Header file for implementation of UEFI Component Name(2) protocol. + +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 _COMPONENT_NAME_H_ +#define _COMPONENT_NAME_H_ + +#define FLOPPY_DRIVE_NAME L"ISA Floppy Drive # " +#define FLOPPY_DRIVE_NAME_LEN ((sizeof (FLOPPY_DRIVE_NAME) / sizeof (CHAR16)) - 1) + +extern EFI_COMPONENT_NAME_PROTOCOL gIsaFloppyComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gIsaFloppyComponentName2; + +/** + 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language 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[out] DriverName 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 +IsaFloppyComponentNameGetDriverName ( + 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] 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[in] 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[in] Language 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[out] 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 +IsaFloppyComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +/** + Add the component name for the floppy device + + @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV instance. + +**/ +VOID +AddName ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c new file mode 100644 index 0000000000..65555d3eb1 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c @@ -0,0 +1,515 @@ +/** @file + ISA Floppy Disk UEFI Driver conforming to the UEFI driver model + + 1. Support two types diskette drive + 1.44M drive and 2.88M drive (and now only support 1.44M) + 2. Support two diskette drives per floppy disk controller + 3. Use DMA channel 2 to transfer data + 4. Do not use interrupt + 5. Support diskette change line signal and write protect + +Copyright (c) 2006 - 2009, Intel 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 "IsaFloppy.h" + +LIST_ENTRY mControllerHead = INITIALIZE_LIST_HEAD_VARIABLE (mControllerHead); + +// +// ISA Floppy Driver Binding Protocol +// +EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver = { + FdcControllerDriverSupported, + FdcControllerDriverStart, + FdcControllerDriverStop, + 0xa, + NULL, + NULL +}; + + +/** + The main Entry Point for 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 +InitializeIsaFloppy( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gFdcControllerDriver, + ImageHandle, + &gIsaFloppyComponentName, + &gIsaFloppyComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Test if the controller is a floppy disk drive device + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of the controller to test. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The device is supported by this driver. + @retval EFI_ALREADY_STARTED The device is already being managed by this driver. + @retval EFI_ACCESS_DENIED The device is already being managed by a different driver + or an application that requires exclusive access. + @retval EFI_UNSUPPORTED The device is is not supported by this driver. +**/ +EFI_STATUS +EFIAPI +FdcControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_ISA_IO_PROTOCOL *IsaIo; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + + // + // Ignore the parameter RemainingDevicePath because this is a device driver. + // + + // + // Open the device path protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Open the ISA I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Use the ISA I/O Protocol to see if Controller is a floppy disk drive device + // + Status = EFI_SUCCESS; + if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) { + Status = EFI_UNSUPPORTED; + } + // + // Close the ISA I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Start this driver on Controller. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + This parameter is ignored by device drivers, and is optional for bus drivers. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. +**/ +EFI_STATUS +EFIAPI +FdcControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + FDC_BLK_IO_DEV *FdcDev; + EFI_ISA_IO_PROTOCOL *IsaIo; + UINTN Index; + LIST_ENTRY *List; + BOOLEAN Found; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + + FdcDev = NULL; + IsaIo = NULL; + + // + // Open the device path protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Report enable progress code + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE, + ParentDevicePath + ); + + // + // Open the ISA I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Allocate the floppy device's Device structure + // + FdcDev = AllocateZeroPool (sizeof (FDC_BLK_IO_DEV)); + if (FdcDev == NULL) { + goto Done; + } + // + // Initialize the floppy device's device structure + // + FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE; + FdcDev->Handle = Controller; + FdcDev->IsaIo = IsaIo; + FdcDev->Disk = (EFI_FDC_DISK) IsaIo->ResourceList->Device.UID; + FdcDev->Cache = NULL; + FdcDev->Event = NULL; + FdcDev->ControllerState = NULL; + FdcDev->DevicePath = ParentDevicePath; + + FdcDev->ControllerNameTable = NULL; + AddName (FdcDev); + + // + // Look up the base address of the Floppy Disk Controller which controls this floppy device + // + for (Index = 0; FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) { + if (FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) { + FdcDev->BaseAddress = (UINT16) FdcDev->IsaIo->ResourceList->ResourceItem[Index].StartRange; + } + } + // + // Maintain the list of floppy disk controllers + // + Found = FALSE; + List = mControllerHead.ForwardLink; + while (List != &mControllerHead) { + FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List); + if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) { + Found = TRUE; + break; + } + + List = List->ForwardLink; + } + + if (!Found) { + // + // A new floppy disk controller controlling this floppy disk drive is found + // + FdcDev->ControllerState = AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT)); + if (FdcDev->ControllerState == NULL) { + goto Done; + } + + FdcDev->ControllerState->Signature = FLOPPY_CONTROLLER_CONTEXT_SIGNATURE; + FdcDev->ControllerState->FddResetPerformed = FALSE; + FdcDev->ControllerState->NeedRecalibrate = FALSE; + FdcDev->ControllerState->BaseAddress = FdcDev->BaseAddress; + FdcDev->ControllerState->NumberOfDrive = 0; + + InsertTailList (&mControllerHead, &FdcDev->ControllerState->Link); + } + // + // Create a timer event for each floppy disk drive device. + // This timer event is used to control the motor on and off + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FddTimerProc, + FdcDev, + &FdcDev->Event + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Reset the Floppy Disk Controller + // + if (!FdcDev->ControllerState->FddResetPerformed) { + FdcDev->ControllerState->FddResetPerformed = TRUE; + FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev); + } + + if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT, + ParentDevicePath + ); + + // + // Discover the Floppy Drive + // + Status = DiscoverFddDevice (FdcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + // + // Install protocol interfaces for the serial device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiBlockIoProtocolGuid, + &FdcDev->BlkIo, + NULL + ); + if (!EFI_ERROR (Status)) { + FdcDev->ControllerState->NumberOfDrive++; + } + +Done: + if (EFI_ERROR (Status)) { + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR, + ParentDevicePath + ); + + // + // If a floppy drive device structure was allocated, then free it + // + if (FdcDev != NULL) { + if (FdcDev->Event != NULL) { + // + // Close the event for turning the motor off + // + gBS->CloseEvent (FdcDev->Event); + } + + FreeUnicodeStringTable (FdcDev->ControllerNameTable); + FreePool (FdcDev); + } + + // + // Close the ISA I/O Protocol + // + if (IsaIo != NULL) { + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + // + // Close the device path protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + return Status; +} + +/** + Stop this driver on ControllerHandle. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +FdcControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + FDC_BLK_IO_DEV *FdcDev; + + // + // Ignore NumberOfChildren since this is a device driver + // + + // + // Get the Block I/O Protocol on Controller + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the floppy drive device's Device structure + // + FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo); + + // + // Report disable progress code + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE, + FdcDev->DevicePath + ); + + // + // Uninstall the Block I/O Protocol + // + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiBlockIoProtocolGuid, + &FdcDev->BlkIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Close the event for turning the motor off + // + gBS->CloseEvent (FdcDev->Event); + + // + // Turn the motor off on the floppy drive device + // + FddTimerProc (FdcDev->Event, FdcDev); + + // + // Close the device path protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Close the ISA I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Free the controller list if needed + // + FdcDev->ControllerState->NumberOfDrive--; + + // + // Free the cache if one was allocated + // + FdcFreeCache (FdcDev); + + // + // Free the floppy drive device's device structure + // + FreeUnicodeStringTable (FdcDev->ControllerNameTable); + FreePool (FdcDev); + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.h new file mode 100644 index 0000000000..30a2d7bf0c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.h @@ -0,0 +1,1093 @@ +/** @file + Include file for ISA Floppy 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 +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 _ISA_FLOPPY_H_ +#define _ISA_FLOPPY_H_ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver; + +#define STALL_1_SECOND 1000000 +#define STALL_1_MSECOND 1000 + +#define DATA_IN 1 +#define DATA_OUT 0 +#define READ 0 +#define WRITE 1 + +// +// Internal Data Structures +// +#define FDC_BLK_IO_DEV_SIGNATURE SIGNATURE_32 ('F', 'B', 'I', 'O') +#define FLOPPY_CONTROLLER_CONTEXT_SIGNATURE SIGNATURE_32 ('F', 'D', 'C', 'C') + +typedef enum { + FdcDisk0 = 0, + FdcDisk1 = 1, + FdcMaxDisk = 2 +} EFI_FDC_DISK; + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + BOOLEAN FddResetPerformed; + EFI_STATUS FddResetStatus; + BOOLEAN NeedRecalibrate; + UINT8 NumberOfDrive; + UINT16 BaseAddress; +} FLOPPY_CONTROLLER_CONTEXT; + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_BLOCK_IO_PROTOCOL BlkIo; + EFI_BLOCK_IO_MEDIA BlkMedia; + + EFI_ISA_IO_PROTOCOL *IsaIo; + + UINT16 BaseAddress; + + EFI_FDC_DISK Disk; + UINT8 PresentCylinderNumber; + UINT8 *Cache; + + EFI_EVENT Event; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + FLOPPY_CONTROLLER_CONTEXT *ControllerState; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} FDC_BLK_IO_DEV; + +#include "ComponentName.h" + +#define FDD_BLK_IO_FROM_THIS(a) CR (a, FDC_BLK_IO_DEV, BlkIo, FDC_BLK_IO_DEV_SIGNATURE) +#define FLOPPY_CONTROLLER_FROM_LIST_ENTRY(a) \ + CR (a, \ + FLOPPY_CONTROLLER_CONTEXT, \ + Link, \ + FLOPPY_CONTROLLER_CONTEXT_SIGNATURE \ + ) + +#define DISK_1440K_EOT 0x12 +#define DISK_1440K_GPL 0x1b +#define DISK_1440K_DTL 0xff +#define DISK_1440K_NUMBER 0x02 +#define DISK_1440K_MAXTRACKNUM 0x4f +#define DISK_1440K_BYTEPERSECTOR 512 + +typedef struct { + UINT8 CommandCode; + UINT8 DiskHeadSel; + UINT8 Cylinder; + UINT8 Head; + UINT8 Sector; + UINT8 Number; + UINT8 EndOfTrack; + UINT8 GapLength; + UINT8 DataLength; +} FDD_COMMAND_PACKET1; + +typedef struct { + UINT8 CommandCode; + UINT8 DiskHeadSel; +} FDD_COMMAND_PACKET2; + +typedef struct { + UINT8 CommandCode; + UINT8 SrtHut; + UINT8 HltNd; +} FDD_SPECIFY_CMD; + +typedef struct { + UINT8 CommandCode; + UINT8 DiskHeadSel; + UINT8 NewCylinder; +} FDD_SEEK_CMD; + +typedef struct { + UINT8 CommandCode; + UINT8 DiskHeadSel; + UINT8 Cylinder; + UINT8 Head; + UINT8 Sector; + UINT8 EndOfTrack; + UINT8 GapLength; + UINT8 ScanTestPause; +} FDD_SCAN_CMD; + +typedef struct { + UINT8 Status0; + UINT8 Status1; + UINT8 Status2; + UINT8 Cylinder; + UINT8 Head; + UINT8 Sector; + UINT8 Number; +} FDD_RESULT_PACKET; + +// +// FDC Registers +// +// +// Digital Output Register address offset +// +#define FDC_REGISTER_DOR 2 + +// +// Main Status Register address offset +// +#define FDC_REGISTER_MSR 4 + +// +// Data Register address offset +// +#define FDC_REGISTER_DTR 5 + +// +// Configuration Control Register(data rate select) address offset +// +#define FDC_REGISTER_CCR 7 + +// +// Digital Input Register(diskchange) address offset +// +#define FDC_REGISTER_DIR 7 + + +// +// FDC Register Bit Definitions +// +// +// Digital Out Register(WO) +// +// +// Select Drive: 0=A 1=B +// +#define SELECT_DRV BIT0 + +// +// Reset FDC +// +#define RESET_FDC BIT2 + +// +// Enable Int & DMA +// +#define INT_DMA_ENABLE BIT3 + +// +// Turn On Drive A Motor +// +#define DRVA_MOTOR_ON BIT4 + +// +// Turn On Drive B Motor +// +#define DRVB_MOTOR_ON BIT5 + +// +// Main Status Register(RO) +// +// +// Drive A Busy +// +#define MSR_DAB BIT0 + +// +// Drive B Busy +// +#define MSR_DBB BIT1 + +// +// FDC Busy +// +#define MSR_CB BIT4 + +// +// Non-DMA Mode +// +#define MSR_NDM BIT5 + +// +// Data Input/Output +// +#define MSR_DIO BIT6 + +// +// Request For Master +// +#define MSR_RQM BIT7 + +// +// Configuration Control Register(WO) +// +// +// Data Rate select +// +#define CCR_DRC (BIT0 | BIT1) + +// +// Digital Input Register(RO) +// +// +// Disk change line +// +#define DIR_DCL BIT7 +// +// #define CCR_DCL BIT7 // Diskette change +// +// 500K +// +#define DRC_500KBS 0x0 + +// +// 300K +// +#define DRC_300KBS 0x01 + +// +// 250K +// +#define DRC_250KBS 0x02 + +// +// FDC Command Code +// +#define READ_DATA_CMD 0x06 +#define WRITE_DATA_CMD 0x05 +#define WRITE_DEL_DATA_CMD 0x09 +#define READ_DEL_DATA_CMD 0x0C +#define READ_TRACK_CMD 0x02 +#define READ_ID_CMD 0x0A +#define FORMAT_TRACK_CMD 0x0D +#define SCAN_EQU_CMD 0x11 +#define SCAN_LOW_EQU_CMD 0x19 +#define SCAN_HIGH_EQU_CMD 0x1D +#define SEEK_CMD 0x0F +#define RECALIBRATE_CMD 0x07 +#define SENSE_INT_STATUS_CMD 0x08 +#define SPECIFY_CMD 0x03 +#define SENSE_DRV_STATUS_CMD 0x04 + +// +// CMD_MT: Multi_Track Selector +// when set , this flag selects the multi-track operating mode. +// In this mode, the FDC treats a complete cylinder under head0 and 1 +// as a single track +// +#define CMD_MT BIT7 + +// +// CMD_MFM: MFM/FM Mode Selector +// A one selects the double density(MFM) mode +// A zero selects single density (FM) mode +// +#define CMD_MFM BIT6 + +// +// CMD_SK: Skip Flag +// When set to 1, sectors containing a deleted data address mark will +// automatically be skipped during the execution of Read Data. +// When set to 0, the sector is read or written the same as the read and +// write commands. +// +#define CMD_SK BIT5 + +// +// FDC Status Register Bit Definitions +// +// +// Status Register 0 +// +// +// Interrupt Code +// +#define STS0_IC (BIT7 | BIT6) + +// +// Seek End: the FDC completed a seek or recalibrate command +// +#define STS0_SE BIT5 + +// +// Equipment Check +// +#define STS0_EC BIT4 + +// +// Not Ready(unused), this bit is always 0 +// +#define STS0_NR BIT3 + +// +// Head Address: the current head address +// +#define STS0_HA BIT2 + +// +// STS0_US1 & STS0_US0: Drive Select(the current selected drive) +// +// +// Unit Select1 +// +#define STS0_US1 BIT1 + +// +// Unit Select0 +// +#define STS0_US0 BIT0 + +// +// Status Register 1 +// +// +// End of Cylinder +// +#define STS1_EN BIT7 + +// +// BIT6 is unused +// +// +// Data Error: The FDC detected a CRC error in either the ID field or +// data field of a sector +// +#define STS1_DE BIT5 + +// +// Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service +// within the required time interval +// +#define STS1_OR BIT4 + +// +// BIT3 is unused +// +// +// No data +// +#define STS1_ND BIT2 + +// +// Not Writable +// +#define STS1_NW BIT1 + +// +// Missing Address Mark +// +#define STS1_MA BIT0 + +// +// Control Mark +// +#define STS2_CM BIT6 + +// +// Data Error in Data Field: The FDC detected a CRC error in the data field +// +#define STS2_DD BIT5 + +// +// Wrong Cylinder: The track address from sector ID field is different from +// the track address maintained inside FDC +// +#define STS2_WC BIT4 + +// +// Bad Cylinder +// +#define STS2_BC BIT1 + +// +// Missing Address Mark in Data Field +// +#define STS2_MD BIT0 + +// +// Write Protected +// +#define STS3_WP BIT6 + +// +// Track 0 +// +#define STS3_T0 BIT4 + +// +// Head Address +// +#define STS3_HD BIT2 + +// +// STS3_US1 & STS3_US0 : Drive Select +// +#define STS3_US1 BIT1 +#define STS3_US0 BIT0 + +// +// Status Register 0 Interrupt Code Description +// +// +// Normal Termination of Command +// +#define IC_NT 0x0 + +// +// Abnormal Termination of Command +// +#define IC_AT 0x40 + +// +// Invalid Command +// +#define IC_IC 0x80 + +// +// Abnormal Termination caused by Polling +// +#define IC_ATRC 0xC0 + +// +// EFI Driver Binding Protocol Functions +// + +/** + Test controller is a floppy disk drive device + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of the controller to test. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The device is supported by this driver. + @retval EFI_ALREADY_STARTED The device is already being managed by this driver. + @retval EFI_ACCESS_DENIED The device is already being managed by a different driver + or an application that requires exclusive access. +**/ +EFI_STATUS +EFIAPI +FdcControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start this driver on Controller. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + This parameter is ignored by device drivers, and is optional for bus drivers. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. +**/ +EFI_STATUS +EFIAPI +FdcControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop this driver on ControllerHandle. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +FdcControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// EFI Block I/O Protocol Functions +// + +/** + Reset the Floppy Logic Drive, call the FddReset function. + + @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface + @param ExtendedVerification BOOLEAN: Indicate that the driver may perform a more + exhaustive verification operation of the device during + reset, now this par is ignored in this driver + @retval EFI_SUCCESS: The Floppy Logic Drive is reset + @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly + and can not be reset + +**/ +EFI_STATUS +EFIAPI +FdcReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Flush block via fdd controller. + + @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface + @return EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +FddFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +/** + Read the requested number of blocks from the device. + + @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface + @param MediaId UINT32: The media id that the read request is for + @param Lba EFI_LBA: The starting logic block address to read from on the device + @param BufferSize UINTN: The size of the Buffer in bytes + @param Buffer VOID *: A pointer to the destination buffer for the data + + @retval EFI_SUCCESS: The data was read correctly from the device + @retval EFI_DEVICE_ERROR:The device reported an error while attempting to perform + the read operation + @retval EFI_NO_MEDIA: There is no media in the device + @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media + @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the + intrinsic 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 + +**/ +EFI_STATUS +EFIAPI +FddReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Write a specified number of blocks to the device. + + @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface + @param MediaId UINT32: The media id that the write request is for + @param Lba EFI_LBA: The starting logic block address to be written + @param BufferSize UINTN: The size in bytes in Buffer + @param Buffer VOID *: A pointer to the source buffer for the data + + @retval EFI_SUCCESS: The data were written correctly to the device + @retval EFI_WRITE_PROTECTED: The device can not be written to + @retval EFI_NO_MEDIA: There is no media in the device + @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media + @retval EFI_DEVICE_ERROR: The device reported an error while attempting to perform + the write operation + @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the + intrinsic 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 +**/ +EFI_STATUS +EFIAPI +FddWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +// +// Prototypes of internal functions +// +/** + + Detect the floppy drive is presented or not. + + @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV + @retval EFI_SUCCESS Drive is presented + @retval EFI_NOT_FOUND Drive is not presented + +**/ +EFI_STATUS +DiscoverFddDevice ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + + Do recalibrate and see the drive is presented or not. + Set the media parameters. + + @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV + @return the drive is presented or not + +**/ +EFI_STATUS +FddIdentify ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + + Reset the Floppy Logic Drive. + + @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV + + @retval EFI_SUCCESS: The Floppy Logic Drive is reset + @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and + can not be reset + +**/ +EFI_STATUS +FddReset ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + + Turn the drive's motor on. + The drive's motor must be on before any command can be executed. + + @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV + + @retval EFI_SUCCESS: Turn the drive's motor on successfully + @retval EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on + @retval EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer) + +**/ +EFI_STATUS +MotorOn ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + + Set a Timer and when Timer goes off, turn the motor off. + + + @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV + + @retval EFI_SUCCESS: Set the Timer successfully + @retval EFI_INVALID_PARAMETER: Fail to Set the timer + +**/ +EFI_STATUS +MotorOff ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + Detect the disk in the drive is changed or not. + + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + + @retval EFI_SUCCESS: No disk media change + @retval EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation + @retval EFI_NO_MEDIA: No disk in the drive + @retval EFI_MEDIA_CHANGED: There is a new disk in the drive +**/ +EFI_STATUS +DisketChanged ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + Do the Specify command, this command sets DMA operation + and the initial values for each of the three internal + times: HUT, SRT and HLT. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + + @retval EFI_SUCCESS: Execute the Specify command successfully + @retval EFI_DEVICE_ERROR: Fail to execute the command + +**/ +EFI_STATUS +Specify ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + Set the head of floppy drive to track 0. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + @retval EFI_SUCCESS: Execute the Recalibrate operation successfully + @retval EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation + +**/ +EFI_STATUS +Recalibrate ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + Set the head of floppy drive to the new cylinder. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + @param Lba EFI_LBA : The logic block address want to seek + + @retval EFI_SUCCESS: Execute the Seek operation successfully + @retval EFI_DEVICE_ERROR: Fail to execute the Seek operation + +**/ +EFI_STATUS +Seek ( + IN FDC_BLK_IO_DEV *FdcDev, + IN EFI_LBA Lba + ); + +/** + Do the Sense Interrupt Status command, this command resets the interrupt signal. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + @param StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC + @param PresentCylinderNumber UINT8 *: Be used to save present cylinder number + read from FDC + + @retval EFI_SUCCESS: Execute the Sense Interrupt Status command successfully + @retval EFI_DEVICE_ERROR: Fail to execute the command + +**/ +EFI_STATUS +SenseIntStatus ( + IN FDC_BLK_IO_DEV *FdcDev, + IN OUT UINT8 *StatusRegister0, + IN OUT UINT8 *PresentCylinderNumber + ); + +/** + Do the Sense Drive Status command. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + @param Lba EFI_LBA : Logic block address + + @retval EFI_SUCCESS: Execute the Sense Drive Status command successfully + @retval EFI_DEVICE_ERROR: Fail to execute the command + @retval EFI_WRITE_PROTECTED:The disk is write protected + +**/ +EFI_STATUS +SenseDrvStatus ( + IN FDC_BLK_IO_DEV *FdcDev, + IN EFI_LBA Lba + ); + +/** + Update the disk media properties and if necessary reinstall Block I/O interface. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + + @retval EFI_SUCCESS: Do the operation successfully + @retval EFI_DEVICE_ERROR: Fail to the operation + +**/ +EFI_STATUS +DetectMedia ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + Set the data rate and so on. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + + @retval EFI_SUCCESS success to set the data rate +**/ +EFI_STATUS +Setup ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +/** + Read or Write a number of blocks in the same cylinder. + + @param FdcDev A pointer to Data Structure FDC_BLK_IO_DEV + @param HostAddress device address + @param Lba The starting logic block address to read from on the device + @param NumberOfBlocks The number of block wanted to be read or write + @param Read Operation type: read or write + + @retval EFI_SUCCESS Success operate + +**/ +EFI_STATUS +ReadWriteDataSector ( + IN FDC_BLK_IO_DEV *FdcDev, + IN VOID *HostAddress, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks, + IN BOOLEAN Read + ); + +/** + Fill in FDD command's parameter. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + @param Lba The starting logic block address to read from on the device + @param Command FDD command + +**/ +VOID +FillPara ( + IN FDC_BLK_IO_DEV *FdcDev, + IN EFI_LBA Lba, + IN FDD_COMMAND_PACKET1 *Command + ); + +/** + Read result byte from Data Register of FDC. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + @param Pointer Buffer to store the byte read from FDC + + @retval EFI_SUCCESS Read result byte from FDC successfully + @retval EFI_DEVICE_ERROR The FDC is not ready to be read + +**/ +EFI_STATUS +DataInByte ( + IN FDC_BLK_IO_DEV *FdcDev, + OUT UINT8 *Pointer + ); + +/** + Write command byte to Data Register of FDC. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + @param Pointer Be used to save command byte written to FDC + + @retval EFI_SUCCESS: Write command byte to FDC successfully + @retval EFI_DEVICE_ERROR: The FDC is not ready to be written + +**/ +EFI_STATUS +DataOutByte ( + IN FDC_BLK_IO_DEV *FdcDev, + IN UINT8 *Pointer + ); + +/** + Detect the specified floppy logic drive is busy or not within a period of time. + + @param FdcDev Indicate it is drive A or drive B + @param Timeout The time period for waiting + + @retval EFI_SUCCESS: The drive and command are not busy + @retval EFI_TIMEOUT: The drive or command is still busy after a period time that + set by Timeout + +**/ +EFI_STATUS +FddWaitForBSYClear ( + IN FDC_BLK_IO_DEV *FdcDev, + IN UINTN Timeout + ); + +/** + Determine whether FDC is ready to write or read. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + @param Dio BOOLEAN: Indicate the FDC is waiting to write or read + @param Timeout The time period for waiting + + @retval EFI_SUCCESS: FDC is ready to write or read + @retval EFI_NOT_READY: FDC is not ready within the specified time period + +**/ +EFI_STATUS +FddDRQReady ( + IN FDC_BLK_IO_DEV *FdcDev, + IN BOOLEAN Dio, + IN UINTN Timeout + ); + +/** + Set FDC control structure's attribute according to result. + + @param Result Point to result structure + @param FdcDev FDC control structure + + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_SUCCESS - GC_TODO: Add description for return value + +**/ +EFI_STATUS +CheckResult ( + IN FDD_RESULT_PACKET *Result, + IN OUT FDC_BLK_IO_DEV *FdcDev + ); + +/** + Check the drive status information. + + @param StatusRegister3 the value of Status Register 3 + + @retval EFI_SUCCESS The disk is not write protected + @retval EFI_WRITE_PROTECTED: The disk is write protected + +**/ +EFI_STATUS +CheckStatus3 ( + IN UINT8 StatusRegister3 + ); + +/** + Calculate the number of block in the same cylinder according to Lba. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + @param Lba EFI_LBA: The starting logic block address + @param NumberOfBlocks UINTN: The number of blocks + + @return The number of blocks in the same cylinder which the starting + logic block address is Lba + +**/ +UINTN +GetTransferBlockCount ( + IN FDC_BLK_IO_DEV *FdcDev, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ); + +/** + When the Timer(2s) off, turn the drive's motor off. + + @param Event EFI_EVENT: Event(the timer) whose notification function is being + invoked + @param Context VOID *: Pointer to the notification function's context + +**/ +VOID +EFIAPI +FddTimerProc ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Read I/O port for FDC. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + @param Offset The offset address of port + +**/ +UINT8 +FdcReadPort ( + IN FDC_BLK_IO_DEV *FdcDev, + IN UINT32 Offset + ); + +/** + Write I/O port for FDC. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV + @param Offset The offset address of port + @param Data Value written to port + +**/ +VOID +FdcWritePort ( + IN FDC_BLK_IO_DEV *FdcDev, + IN UINT32 Offset, + IN UINT8 Data + ); + +/** + Read or Write a number of blocks to floppy device. + + @param This Pointer to instance of EFI_BLOCK_IO_PROTOCOL + @param MediaId The media id of read/write request + @param Lba The starting logic block address to read from on the device + @param BufferSize The size of the Buffer in bytes + @param Operation - GC_TODO: add argument description + @param Buffer - GC_TODO: add argument description + + @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value + @retval EFI_SUCCESS - GC_TODO: Add description for return value + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_NO_MEDIA - GC_TODO: Add description for return value + @retval EFI_MEDIA_CHANGED - GC_TODO: Add description for return value + @retval EFI_WRITE_PROTECTED - GC_TODO: Add description for return value + @retval EFI_BAD_BUFFER_SIZE - GC_TODO: Add description for return value + @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value + @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value + @retval EFI_SUCCESS - GC_TODO: Add description for return value + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_SUCCESS - GC_TODO: Add description for return value + +**/ +EFI_STATUS +FddReadWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN BOOLEAN Operation, + OUT VOID *Buffer + ); + +/** + Common interface for free cache. + + @param FdcDev Pointer of FDC_BLK_IO_DEV instance + +**/ +VOID +FdcFreeCache ( + IN FDC_BLK_IO_DEV *FdcDev + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c new file mode 100644 index 0000000000..39f0ba0191 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c @@ -0,0 +1,375 @@ +/** @file + Implementation of the EFI Block IO Protocol for ISA Floppy driver + +Copyright (c) 2006 - 2009, Intel 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 "IsaFloppy.h" + +/** + 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. +**/ +EFI_STATUS +EFIAPI +FdcReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + FDC_BLK_IO_DEV *FdcDev; + + // + // Reset the Floppy Disk Controller + // + FdcDev = FDD_BLK_IO_FROM_THIS (This); + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA, + FdcDev->DevicePath + ); + + return FddReset (FdcDev); +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +FddFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + // + // Not supported yet + // + return EFI_SUCCESS; +} + +/** + Common report status code interface. + + @param This Pointer of FDC_BLK_IO_DEV instance + @param Read Read or write operation when error occurrs +**/ +VOID +FddReportStatus ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN Read + ) +{ + FDC_BLK_IO_DEV *FdcDev; + + FdcDev = FDD_BLK_IO_FROM_THIS (This); + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE, + ((Read) ? EFI_P_EC_INPUT_ERROR : EFI_P_EC_OUTPUT_ERROR) | EFI_PERIPHERAL_REMOVABLE_MEDIA, + FdcDev->DevicePath + ); +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +FddReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = FddReadWriteBlocks (This, MediaId, Lba, BufferSize, READ, Buffer); + + if (EFI_ERROR (Status)) { + FddReportStatus (This, TRUE); + } + + return Status; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +FddWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = FddReadWriteBlocks (This, MediaId, Lba, BufferSize, WRITE, Buffer); + + if (EFI_ERROR (Status)) { + FddReportStatus (This, FALSE); + } + + return Status; +} + +/** + Read or Write a number of blocks to floppy disk + + @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 Operation Specifies the read or write operation. + @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. + @retval EFI_WRITE_PROTECTED The device can not be written to. + +**/ +EFI_STATUS +FddReadWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN BOOLEAN Operation, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + FDC_BLK_IO_DEV *FdcDev; + UINTN BlockSize; + UINTN NumberOfBlocks; + UINTN BlockCount; + EFI_STATUS Status; + EFI_LBA Lba0; + UINT8 *Pointer; + + // + // Get the intrinsic block size + // + Media = This->Media; + BlockSize = Media->BlockSize; + FdcDev = FDD_BLK_IO_FROM_THIS (This); + + if (Operation == WRITE) { + if (Lba == 0) { + FdcFreeCache (FdcDev); + } + } + + // + // Set the drive motor on + // + Status = MotorOn (FdcDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Check to see if media can be detected + // + Status = DetectMedia (FdcDev); + if (EFI_ERROR (Status)) { + MotorOff (FdcDev); + FdcFreeCache (FdcDev); + return EFI_DEVICE_ERROR; + } + // + // Check to see if media is present + // + if (!(Media->MediaPresent)) { + MotorOff (FdcDev); + FdcFreeCache (FdcDev); + return EFI_NO_MEDIA; + } + // + // Check to see if media has been changed + // + if (MediaId != Media->MediaId) { + MotorOff (FdcDev); + FdcFreeCache (FdcDev); + return EFI_MEDIA_CHANGED; + } + + if (BufferSize == 0) { + MotorOff (FdcDev); + return EFI_SUCCESS; + } + + if (Operation == WRITE) { + if (Media->ReadOnly) { + MotorOff (FdcDev); + return EFI_WRITE_PROTECTED; + } + } + // + // Check the parameters for this read/write operation + // + if (Buffer == NULL) { + MotorOff (FdcDev); + return EFI_INVALID_PARAMETER; + } + + if (BufferSize % BlockSize != 0) { + MotorOff (FdcDev); + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > Media->LastBlock) { + MotorOff (FdcDev); + return EFI_INVALID_PARAMETER; + } + + if (((BufferSize / BlockSize) + Lba - 1) > Media->LastBlock) { + MotorOff (FdcDev); + return EFI_INVALID_PARAMETER; + } + + if (Operation == READ) { + // + // See if the data that is being read is already in the cache + // + if (FdcDev->Cache != NULL) { + if (Lba == 0 && BufferSize == BlockSize) { + MotorOff (FdcDev); + CopyMem ((UINT8 *) Buffer, (UINT8 *) FdcDev->Cache, BlockSize); + return EFI_SUCCESS; + } + } + } + // + // Set up Floppy Disk Controller + // + Status = Setup (FdcDev); + if (EFI_ERROR (Status)) { + MotorOff (FdcDev); + return EFI_DEVICE_ERROR; + } + + NumberOfBlocks = BufferSize / BlockSize; + Lba0 = Lba; + Pointer = Buffer; + + // + // read blocks in the same cylinder. + // in a cylinder , there are 18 * 2 = 36 blocks + // + BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks); + while ((BlockCount != 0) && !EFI_ERROR (Status)) { + Status = ReadWriteDataSector (FdcDev, Buffer, Lba, BlockCount, Operation); + if (EFI_ERROR (Status)) { + MotorOff (FdcDev); + FddReset (FdcDev); + return EFI_DEVICE_ERROR; + } + + Lba += BlockCount; + NumberOfBlocks -= BlockCount; + Buffer = (VOID *) ((UINTN) Buffer + BlockCount * BlockSize); + BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks); + } + + Buffer = Pointer; + + // + // Turn the motor off + // + MotorOff (FdcDev); + + if (Operation == READ) { + // + // Cache the data read + // + if (Lba0 == 0 && FdcDev->Cache == NULL) { + FdcDev->Cache = AllocateCopyPool (BlockSize, Buffer); + } + } + + return EFI_SUCCESS; + +} + +/** + Free cache for a floppy disk. + + @param FdcDev A Pointer to FDC_BLK_IO_DEV instance + +**/ +VOID +FdcFreeCache ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + if (FdcDev->Cache != NULL) { + FreePool (FdcDev->Cache); + FdcDev->Cache = NULL; + } +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c new file mode 100644 index 0000000000..16ad6b02e3 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c @@ -0,0 +1,1398 @@ +/** @file + Internal floppy disk controller programming functions for the floppy 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 +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 "IsaFloppy.h" + +/** + Detect whether a floppy drive is present or not. + + @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV + + @retval EFI_SUCCESS The floppy disk drive is present + @retval EFI_NOT_FOUND The floppy disk drive is not present +**/ +EFI_STATUS +DiscoverFddDevice ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + EFI_STATUS Status; + + FdcDev->BlkIo.Media = &FdcDev->BlkMedia; + + Status = FddIdentify (FdcDev); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + FdcDev->BlkIo.Reset = FdcReset; + FdcDev->BlkIo.FlushBlocks = FddFlushBlocks; + FdcDev->BlkIo.ReadBlocks = FddReadBlocks; + FdcDev->BlkIo.WriteBlocks = FddWriteBlocks; + FdcDev->BlkMedia.LogicalPartition = FALSE; + FdcDev->BlkMedia.WriteCaching = FALSE; + + return EFI_SUCCESS; +} + +/** + Do recalibrate and check if the drive is present or not + and set the media parameters if the driver is present. + + @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV + + @retval EFI_SUCCESS The floppy disk drive is present + @retval EFI_DEVICE_ERROR The floppy disk drive is not present +**/ +EFI_STATUS +FddIdentify ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + EFI_STATUS Status; + + // + // Set Floppy Disk Controller's motor on + // + Status = MotorOn (FdcDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = Recalibrate (FdcDev); + + if (EFI_ERROR (Status)) { + MotorOff (FdcDev); + FdcDev->ControllerState->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } + // + // Set Media Parameter + // + FdcDev->BlkIo.Media->RemovableMedia = TRUE; + FdcDev->BlkIo.Media->MediaPresent = TRUE; + FdcDev->BlkIo.Media->MediaId = 0; + + // + // Check Media + // + Status = DisketChanged (FdcDev); + + if (Status == EFI_NO_MEDIA) { + FdcDev->BlkIo.Media->MediaPresent = FALSE; + } else if ((Status != EFI_MEDIA_CHANGED) && + (Status != EFI_SUCCESS)) { + MotorOff (FdcDev); + return Status; + } + + // + // Check Disk Write Protected + // + Status = SenseDrvStatus (FdcDev, 0); + + if (Status == EFI_WRITE_PROTECTED) { + FdcDev->BlkIo.Media->ReadOnly = TRUE; + } else if (Status == EFI_SUCCESS) { + FdcDev->BlkIo.Media->ReadOnly = FALSE; + } else { + return EFI_DEVICE_ERROR; + } + + MotorOff (FdcDev); + + // + // Set Media Default Type + // + FdcDev->BlkIo.Media->BlockSize = DISK_1440K_BYTEPERSECTOR; + FdcDev->BlkIo.Media->LastBlock = DISK_1440K_EOT * 2 * (DISK_1440K_MAXTRACKNUM + 1) - 1; + + return EFI_SUCCESS; +} + +/** + Reset the Floppy Logic Drive. + + @param FdcDev FDC_BLK_IO_DEV * : A pointer to the FDC_BLK_IO_DEV + + @retval EFI_SUCCESS: The Floppy Logic Drive is reset + @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and + can not be reset + +**/ +EFI_STATUS +FddReset ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + UINT8 Data; + UINT8 StatusRegister0; + UINT8 PresentCylinderNumber; + UINTN Index; + + // + // Report reset progress code + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET, + FdcDev->DevicePath + ); + + // + // Reset specified Floppy Logic Drive according to FdcDev -> Disk + // Set Digital Output Register(DOR) to do reset work + // bit0 & bit1 of DOR : Drive Select + // bit2 : Reset bit + // bit3 : DMA and Int bit + // Reset : a "0" written to bit2 resets the FDC, this reset will remain + // active until + // a "1" is written to this bit. + // Reset step 1: + // use bit0 & bit1 to select the logic drive + // write "0" to bit2 + // + Data = 0x0; + Data = (UINT8) (Data | (SELECT_DRV & FdcDev->Disk)); + FdcWritePort (FdcDev, FDC_REGISTER_DOR, Data); + + // + // wait some time,at least 120us + // + MicroSecondDelay (500); + + // + // Reset step 2: + // write "1" to bit2 + // write "1" to bit3 : enable DMA + // + Data |= 0x0C; + FdcWritePort (FdcDev, FDC_REGISTER_DOR, Data); + + // + // Experience value + // + MicroSecondDelay (2000); + + // + // wait specified floppy logic drive is not busy + // + if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) { + return EFI_DEVICE_ERROR; + } + // + // Set the Transfer Data Rate + // + FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0); + + // + // Experience value + // + MicroSecondDelay (100); + + // + // Issue Sense interrupt command for each drive (total 4 drives) + // + for (Index = 0; Index < 4; Index++) { + if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) { + return EFI_DEVICE_ERROR; + } + } + // + // issue Specify command + // + if (EFI_ERROR (Specify (FdcDev))) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Turn the floppy disk drive's motor on. + The drive's motor must be on before any command can be executed. + + @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV + + @retval EFI_SUCCESS The drive's motor was turned on successfully + @retval EFI_DEVICE_ERROR The drive is busy, so can not turn motor on +**/ +EFI_STATUS +MotorOn ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + EFI_STATUS Status; + UINT8 DorData; + + // + // Control of the floppy drive motors is a big pain. If motor is off, you have + // to turn it on first. But you can not leave the motor on all the time, since + // that would wear out the disk. On the other hand, if you turn the motor off + // after each operation, the system performance will be awful. The compromise + // used in this driver is to leave the motor on for 2 seconds after + // each operation. If a new operation is started in that interval(2s), + // the motor need not be turned on again. If no new operation is started, + // a timer goes off and the motor is turned off + // + // + // Cancel the timer + // + Status = gBS->SetTimer (FdcDev->Event, TimerCancel, 0); + ASSERT_EFI_ERROR (Status); + + // + // Get the motor status + // + DorData = FdcReadPort (FdcDev, FDC_REGISTER_DOR); + + if (((FdcDev->Disk == FdcDisk0) && ((DorData & 0x10) == 0x10)) || + ((FdcDev->Disk == FdcDisk1) && ((DorData & 0x21) == 0x21)) + ) { + return EFI_SUCCESS; + } + // + // The drive's motor is off, so need turn it on + // first look at command and drive are busy or not + // + if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) { + return EFI_DEVICE_ERROR; + } + // + // for drive A: 1CH, drive B: 2DH + // + DorData = 0x0C; + DorData = (UINT8) (DorData | (SELECT_DRV & FdcDev->Disk)); + if (FdcDev->Disk == FdcDisk0) { + // + // drive A + // + DorData |= DRVA_MOTOR_ON; + } else { + // + // drive B + // + DorData |= DRVB_MOTOR_ON; + } + + FdcWritePort (FdcDev, FDC_REGISTER_DOR, DorData); + + // + // Experience value + // + MicroSecondDelay (4000); + + return EFI_SUCCESS; +} + +/** + Set a Timer and when Timer goes off, turn the motor off. + + @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV + + @retval EFI_SUCCESS Set the Timer successfully + @retval EFI_INVALID_PARAMETER Fail to Set the timer +**/ +EFI_STATUS +MotorOff ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + // + // Set the timer : 2s + // + return gBS->SetTimer (FdcDev->Event, TimerRelative, 20000000); +} + +/** + Detect whether the disk in the drive is changed or not. + + @param[in] FdcDev A pointer to FDC_BLK_IO_DEV + + @retval EFI_SUCCESS No disk media change + @retval EFI_DEVICE_ERROR Fail to do the recalibrate or seek operation + @retval EFI_NO_MEDIA No disk in the drive + @retval EFI_MEDIA_CHANGED There is a new disk in the drive +**/ +EFI_STATUS +DisketChanged ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Check change line + // + Data = FdcReadPort (FdcDev, FDC_REGISTER_DIR); + + // + // Io delay + // + MicroSecondDelay (50); + + if ((Data & DIR_DCL) == 0x80) { + // + // disk change line is active + // + if (FdcDev->PresentCylinderNumber != 0) { + Status = Recalibrate (FdcDev); + } else { + Status = Seek (FdcDev, 0x30); + } + + if (EFI_ERROR (Status)) { + FdcDev->ControllerState->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + // + // Fail to do the seek or recalibrate operation + // + } + + Data = FdcReadPort (FdcDev, FDC_REGISTER_DIR); + + // + // Io delay + // + MicroSecondDelay (50); + + if ((Data & DIR_DCL) == 0x80) { + return EFI_NO_MEDIA; + } + + return EFI_MEDIA_CHANGED; + } + + return EFI_SUCCESS; +} + +/** + Do the Specify command, this command sets DMA operation + and the initial values for each of the three internal + times: HUT, SRT and HLT. + + @param[in] FdcDev Pointer to instance of FDC_BLK_IO_DEV + + @retval EFI_SUCCESS Execute the Specify command successfully + @retval EFI_DEVICE_ERROR Fail to execute the command +**/ +EFI_STATUS +Specify ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + FDD_SPECIFY_CMD Command; + UINTN Index; + UINT8 *CommandPointer; + + ZeroMem (&Command, sizeof (FDD_SPECIFY_CMD)); + Command.CommandCode = SPECIFY_CMD; + // + // set SRT, HUT + // + Command.SrtHut = 0xdf; + // + // 0xdf; + // + // set HLT and DMA + // + Command.HltNd = 0x02; + + CommandPointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDD_SPECIFY_CMD); Index++) { + if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + +/** + Set the head of floppy drive to track 0. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV + @retval EFI_SUCCESS: Execute the Recalibrate operation successfully + @retval EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation + +**/ +EFI_STATUS +Recalibrate ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + FDD_COMMAND_PACKET2 Command; + UINTN Index; + UINT8 StatusRegister0; + UINT8 PresentCylinderNumber; + UINT8 *CommandPointer; + UINT8 Count; + + Count = 2; + + while (Count > 0) { + ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2)); + Command.CommandCode = RECALIBRATE_CMD; + // + // drive select + // + if (FdcDev->Disk == FdcDisk0) { + Command.DiskHeadSel = 0; + // + // 0 + // + } else { + Command.DiskHeadSel = 1; + // + // 1 + // + } + + CommandPointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) { + if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { + return EFI_DEVICE_ERROR; + } + } + // + // Experience value + // + MicroSecondDelay (250000); + // + // need modify according to 1.44M or 2.88M + // + if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) { + return EFI_DEVICE_ERROR; + } + + if ((StatusRegister0 & 0xf0) == 0x20 && PresentCylinderNumber == 0) { + FdcDev->PresentCylinderNumber = 0; + FdcDev->ControllerState->NeedRecalibrate = FALSE; + return EFI_SUCCESS; + } else { + Count--; + if (Count == 0) { + return EFI_DEVICE_ERROR; + } + } + } + // + // end while + // + return EFI_SUCCESS; +} + +/** + Set the head of floppy drive to the new cylinder. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV + @param Lba EFI_LBA : The logic block address want to seek + + @retval EFI_SUCCESS: Execute the Seek operation successfully + @retval EFI_DEVICE_ERROR: Fail to execute the Seek operation + +**/ +EFI_STATUS +Seek ( + IN FDC_BLK_IO_DEV *FdcDev, + IN EFI_LBA Lba + ) +{ + FDD_SEEK_CMD Command; + UINT8 EndOfTrack; + UINT8 Head; + UINT8 Cylinder; + UINT8 StatusRegister0; + UINT8 *CommandPointer; + UINT8 PresentCylinderNumber; + UINTN Index; + UINT8 DelayTime; + + if (FdcDev->ControllerState->NeedRecalibrate) { + if (EFI_ERROR (Recalibrate (FdcDev))) { + FdcDev->ControllerState->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } + } + + EndOfTrack = DISK_1440K_EOT; + // + // Calculate cylinder based on Lba and EOT + // + Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2); + + // + // if the destination cylinder is the present cylinder, unnecessary to do the + // seek operation + // + if (FdcDev->PresentCylinderNumber == Cylinder) { + return EFI_SUCCESS; + } + // + // Calculate the head : 0 or 1 + // + Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); + + ZeroMem (&Command, sizeof (FDD_SEEK_CMD)); + Command.CommandCode = SEEK_CMD; + if (FdcDev->Disk == FdcDisk0) { + Command.DiskHeadSel = 0; + // + // 0 + // + } else { + Command.DiskHeadSel = 1; + // + // 1 + // + } + + Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2)); + Command.NewCylinder = Cylinder; + + CommandPointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDD_SEEK_CMD); Index++) { + if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { + return EFI_DEVICE_ERROR; + } + } + // + // Io delay + // + MicroSecondDelay (100); + + // + // Calculate waiting time + // + if (FdcDev->PresentCylinderNumber > Cylinder) { + DelayTime = (UINT8) (FdcDev->PresentCylinderNumber - Cylinder); + } else { + DelayTime = (UINT8) (Cylinder - FdcDev->PresentCylinderNumber); + } + + MicroSecondDelay ((DelayTime + 1) * 4000); + + if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) { + return EFI_DEVICE_ERROR; + } + + if ((StatusRegister0 & 0xf0) == 0x20) { + FdcDev->PresentCylinderNumber = Command.NewCylinder; + return EFI_SUCCESS; + } else { + FdcDev->ControllerState->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } +} + +/** + Do the Sense Interrupt Status command, this command + resets the interrupt signal. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV + @param StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC + @param PresentCylinderNumber UINT8 *: Be used to save present cylinder number + read from FDC + + @retval EFI_SUCCESS: Execute the Sense Interrupt Status command successfully + @retval EFI_DEVICE_ERROR: Fail to execute the command + +**/ +EFI_STATUS +SenseIntStatus ( + IN FDC_BLK_IO_DEV *FdcDev, + IN OUT UINT8 *StatusRegister0, + IN OUT UINT8 *PresentCylinderNumber + ) +{ + UINT8 Command; + + Command = SENSE_INT_STATUS_CMD; + if (EFI_ERROR (DataOutByte (FdcDev, &Command))) { + return EFI_DEVICE_ERROR; + } + + if (EFI_ERROR (DataInByte (FdcDev, StatusRegister0))) { + return EFI_DEVICE_ERROR; + } + + if (EFI_ERROR (DataInByte (FdcDev, PresentCylinderNumber))) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Do the Sense Drive Status command. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV + @param Lba EFI_LBA : Logic block address + + @retval EFI_SUCCESS: Execute the Sense Drive Status command successfully + @retval EFI_DEVICE_ERROR: Fail to execute the command + @retval EFI_WRITE_PROTECTED:The disk is write protected + +**/ +EFI_STATUS +SenseDrvStatus ( + IN FDC_BLK_IO_DEV *FdcDev, + IN EFI_LBA Lba + ) +{ + FDD_COMMAND_PACKET2 Command; + UINT8 Head; + UINT8 EndOfTrack; + UINTN Index; + UINT8 StatusRegister3; + UINT8 *CommandPointer; + + // + // Sense Drive Status command obtains drive status information, + // it has not execution phase and goes directly to the result phase from the + // command phase, Status Register 3 contains the drive status information + // + ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2)); + Command.CommandCode = SENSE_DRV_STATUS_CMD; + + if (FdcDev->Disk == FdcDisk0) { + Command.DiskHeadSel = 0; + } else { + Command.DiskHeadSel = 1; + } + + EndOfTrack = DISK_1440K_EOT; + Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); + Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2)); + + CommandPointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) { + if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { + return EFI_DEVICE_ERROR; + } + } + + if (EFI_ERROR (DataInByte (FdcDev, &StatusRegister3))) { + return EFI_DEVICE_ERROR; + } + // + // Io delay + // + MicroSecondDelay (50); + + // + // Check Status Register 3 to get drive status information + // + return CheckStatus3 (StatusRegister3); +} + +/** + Update the disk media properties and if necessary reinstall Block I/O interface. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV + + @retval EFI_SUCCESS: Do the operation successfully + @retval EFI_DEVICE_ERROR: Fail to the operation + +**/ +EFI_STATUS +DetectMedia ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + EFI_STATUS Status; + BOOLEAN Reset; + BOOLEAN ReadOnlyLastTime; + BOOLEAN MediaPresentLastTime; + + Reset = FALSE; + ReadOnlyLastTime = FdcDev->BlkIo.Media->ReadOnly; + MediaPresentLastTime = FdcDev->BlkIo.Media->MediaPresent; + + // + // Check disk change + // + Status = DisketChanged (FdcDev); + + if (Status == EFI_MEDIA_CHANGED) { + FdcDev->BlkIo.Media->MediaId++; + FdcDev->BlkIo.Media->MediaPresent = TRUE; + Reset = TRUE; + } else if (Status == EFI_NO_MEDIA) { + FdcDev->BlkIo.Media->MediaPresent = FALSE; + } else if (Status != EFI_SUCCESS) { + MotorOff (FdcDev); + return Status; + // + // EFI_DEVICE_ERROR + // + } + + if (FdcDev->BlkIo.Media->MediaPresent) { + // + // Check disk write protected + // + Status = SenseDrvStatus (FdcDev, 0); + if (Status == EFI_WRITE_PROTECTED) { + FdcDev->BlkIo.Media->ReadOnly = TRUE; + } else { + FdcDev->BlkIo.Media->ReadOnly = FALSE; + } + } + + if (FdcDev->BlkIo.Media->MediaPresent && (ReadOnlyLastTime != FdcDev->BlkIo.Media->ReadOnly)) { + Reset = TRUE; + } + + if (MediaPresentLastTime != FdcDev->BlkIo.Media->MediaPresent) { + Reset = TRUE; + } + + if (Reset) { + Status = gBS->ReinstallProtocolInterface ( + FdcDev->Handle, + &gEfiBlockIoProtocolGuid, + &FdcDev->BlkIo, + &FdcDev->BlkIo + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + +/** + Set the data rate and so on. + + @param FdcDev A pointer to FDC_BLK_IO_DEV + + @retval EFI_SUCCESS success to set the data rate +**/ +EFI_STATUS +Setup ( + IN FDC_BLK_IO_DEV *FdcDev + ) +{ + EFI_STATUS Status; + + // + // Set data rate 500kbs + // + FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0); + + // + // Io delay + // + MicroSecondDelay (50); + + Status = Specify (FdcDev); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Read or Write a number of blocks in the same cylinder. + + @param FdcDev A pointer to FDC_BLK_IO_DEV + @param HostAddress device address + @param Lba The starting logic block address to read from on the device + @param NumberOfBlocks The number of block wanted to be read or write + @param Read Operation type: read or write + + @retval EFI_SUCCESS Success operate + +**/ +EFI_STATUS +ReadWriteDataSector ( + IN FDC_BLK_IO_DEV *FdcDev, + IN VOID *HostAddress, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks, + IN BOOLEAN Read + ) +{ + EFI_STATUS Status; + FDD_COMMAND_PACKET1 Command; + FDD_RESULT_PACKET Result; + UINTN Index; + UINTN Times; + UINT8 *CommandPointer; + + EFI_PHYSICAL_ADDRESS DeviceAddress; + EFI_ISA_IO_PROTOCOL *IsaIo; + UINTN NumberofBytes; + VOID *Mapping; + EFI_ISA_IO_PROTOCOL_OPERATION Operation; + EFI_STATUS Status1; + UINT8 Channel; + EFI_ISA_ACPI_RESOURCE *ResourceItem; + UINT32 Attribute; + + Status = Seek (FdcDev, Lba); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Map Dma + // + IsaIo = FdcDev->IsaIo; + NumberofBytes = NumberOfBlocks * 512; + if (Read == READ) { + Operation = EfiIsaIoOperationSlaveWrite; + } else { + Operation = EfiIsaIoOperationSlaveRead; + } + + ResourceItem = IsaIo->ResourceList->ResourceItem; + Index = 0; + while (ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList) { + if (ResourceItem[Index].Type == EfiIsaAcpiResourceDma) { + break; + } + + Index++; + } + + if (ResourceItem[Index].Type == EfiIsaAcpiResourceEndOfList) { + return EFI_DEVICE_ERROR; + } + + Channel = (UINT8) IsaIo->ResourceList->ResourceItem[Index].StartRange; + Attribute = IsaIo->ResourceList->ResourceItem[Index].Attribute; + + Status1 = IsaIo->Map ( + IsaIo, + Operation, + Channel, + Attribute, + HostAddress, + &NumberofBytes, + &DeviceAddress, + &Mapping + ); + if (EFI_ERROR (Status1)) { + return Status1; + } + + // + // Allocate Read or Write command packet + // + ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET1)); + if (Read == READ) { + Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK; + } else { + Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM; + } + + FillPara (FdcDev, Lba, &Command); + + // + // Write command bytes to FDC + // + CommandPointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET1); Index++) { + if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { + return EFI_DEVICE_ERROR; + } + } + // + // wait for some time + // + Times = (STALL_1_SECOND / 50) + 1; + do { + if ((FdcReadPort (FdcDev, FDC_REGISTER_MSR) & 0xc0) == 0xc0) { + break; + } + + MicroSecondDelay (50); + Times = Times - 1; + } while (Times > 0); + + if (Times == 0) { + return EFI_TIMEOUT; + } + // + // Read result bytes from FDC + // + CommandPointer = (UINT8 *) (&Result); + for (Index = 0; Index < sizeof (FDD_RESULT_PACKET); Index++) { + if (EFI_ERROR (DataInByte (FdcDev, CommandPointer++))) { + return EFI_DEVICE_ERROR; + } + } + // + // Flush before Unmap + // + if (Read == READ) { + Status1 = IsaIo->Flush (IsaIo); + if (EFI_ERROR (Status1)) { + return Status1; + } + } + // + // Unmap Dma + // + Status1 = IsaIo->Unmap (IsaIo, Mapping); + if (EFI_ERROR (Status1)) { + return Status1; + } + + return CheckResult (&Result, FdcDev); +} + +/** + Fill in FDD command's parameter. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + @param Lba The starting logic block address to read from on the device + @param Command FDD command + +**/ +VOID +FillPara ( + IN FDC_BLK_IO_DEV *FdcDev, + IN EFI_LBA Lba, + IN FDD_COMMAND_PACKET1 *Command + ) +{ + UINT8 EndOfTrack; + + // + // Get EndOfTrack from the Para table + // + EndOfTrack = DISK_1440K_EOT; + + // + // Fill the command parameter + // + if (FdcDev->Disk == FdcDisk0) { + Command->DiskHeadSel = 0; + } else { + Command->DiskHeadSel = 1; + } + + Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2); + Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); + Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1); + Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2)); + Command->Number = DISK_1440K_NUMBER; + Command->EndOfTrack = DISK_1440K_EOT; + Command->GapLength = DISK_1440K_GPL; + Command->DataLength = DISK_1440K_DTL; +} + +/** + Read result byte from Data Register of FDC. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + @param Pointer Buffer to store the byte read from FDC + + @retval EFI_SUCCESS Read result byte from FDC successfully + @retval EFI_DEVICE_ERROR The FDC is not ready to be read + +**/ +EFI_STATUS +DataInByte ( + IN FDC_BLK_IO_DEV *FdcDev, + OUT UINT8 *Pointer + ) +{ + UINT8 Data; + + // + // wait for 1ms and detect the FDC is ready to be read + // + if (EFI_ERROR (FddDRQReady (FdcDev, DATA_IN, 1))) { + return EFI_DEVICE_ERROR; + // + // is not ready + // + } + + Data = FdcReadPort (FdcDev, FDC_REGISTER_DTR); + + // + // Io delay + // + MicroSecondDelay (50); + + *Pointer = Data; + return EFI_SUCCESS; +} + +/** + Write command byte to Data Register of FDC. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + @param Pointer Be used to save command byte written to FDC + + @retval EFI_SUCCESS: Write command byte to FDC successfully + @retval EFI_DEVICE_ERROR: The FDC is not ready to be written + +**/ +EFI_STATUS +DataOutByte ( + IN FDC_BLK_IO_DEV *FdcDev, + IN UINT8 *Pointer + ) +{ + UINT8 Data; + + // + // wait for 1ms and detect the FDC is ready to be written + // + if (EFI_ERROR (FddDRQReady (FdcDev, DATA_OUT, 1))) { + // + // Not ready + // + return EFI_DEVICE_ERROR; + } + + Data = *Pointer; + + FdcWritePort (FdcDev, FDC_REGISTER_DTR, Data); + + // + // Io delay + // + MicroSecondDelay (50); + + return EFI_SUCCESS; +} + +/** + Detect the specified floppy logic drive is busy or not within a period of time. + + @param FdcDev Indicate it is drive A or drive B + @param Timeout The time period for waiting + + @retval EFI_SUCCESS: The drive and command are not busy + @retval EFI_TIMEOUT: The drive or command is still busy after a period time that + set by Timeout + +**/ +EFI_STATUS +FddWaitForBSYClear ( + IN FDC_BLK_IO_DEV *FdcDev, + IN UINTN Timeout + ) +{ + UINTN Delay; + UINT8 StatusRegister; + UINT8 Mask; + + // + // How to determine drive and command are busy or not: by the bits of + // Main Status Register + // bit0: Drive 0 busy (drive A) + // bit1: Drive 1 busy (drive B) + // bit4: Command busy + // + // + // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4 + // + Mask = (UINT8) ((FdcDev->Disk == FdcDisk0 ? MSR_DAB : MSR_DBB) | MSR_CB); + + Delay = ((Timeout * STALL_1_MSECOND) / 50) + 1; + do { + StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR); + if ((StatusRegister & Mask) == 0x00) { + break; + // + // not busy + // + } + + MicroSecondDelay (50); + Delay = Delay - 1; + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Determine whether FDC is ready to write or read. + + @param FdcDev Pointer to instance of FDC_BLK_IO_DEV + @param Dio BOOLEAN: Indicate the FDC is waiting to write or read + @param Timeout The time period for waiting + + @retval EFI_SUCCESS: FDC is ready to write or read + @retval EFI_NOT_READY: FDC is not ready within the specified time period + +**/ +EFI_STATUS +FddDRQReady ( + IN FDC_BLK_IO_DEV *FdcDev, + IN BOOLEAN Dio, + IN UINTN Timeout + ) +{ + UINTN Delay; + UINT8 StatusRegister; + UINT8 DataInOut; + + // + // Before writing to FDC or reading from FDC, the Host must examine + // the bit7(RQM) and bit6(DIO) of the Main Status Register. + // That is to say: + // command bytes can not be written to Data Register + // unless RQM is 1 and DIO is 0 + // result bytes can not be read from Data Register + // unless RQM is 1 and DIO is 1 + // + DataInOut = (UINT8) (Dio << 6); + // + // in order to compare bit6 + // + Delay = ((Timeout * STALL_1_MSECOND) / 50) + 1; + do { + StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR); + if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == DataInOut) { + break; + // + // FDC is ready + // + } + + MicroSecondDelay (50); + // + // Stall for 50 us + // + Delay = Delay - 1; + } while (Delay > 0); + + if (Delay == 0) { + return EFI_NOT_READY; + // + // FDC is not ready within the specified time period + // + } + + return EFI_SUCCESS; +} + +/** + Set FDC control structure's attribute according to result. + + @param Result Point to result structure + @param FdcDev FDC control structure + + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value + @retval EFI_SUCCESS - GC_TODO: Add description for return value + +**/ +EFI_STATUS +CheckResult ( + IN FDD_RESULT_PACKET *Result, + IN OUT FDC_BLK_IO_DEV *FdcDev + ) +{ + // + // Check Status Register0 + // + if ((Result->Status0 & STS0_IC) != IC_NT) { + if ((Result->Status0 & STS0_SE) == 0x20) { + // + // seek error + // + FdcDev->ControllerState->NeedRecalibrate = TRUE; + } + + FdcDev->ControllerState->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } + // + // Check Status Register1 + // + if ((Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) != 0) { + FdcDev->ControllerState->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } + // + // Check Status Register2 + // + if ((Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) != 0) { + FdcDev->ControllerState->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Check the drive status information. + + @param StatusRegister3 the value of Status Register 3 + + @retval EFI_SUCCESS The disk is not write protected + @retval EFI_WRITE_PROTECTED: The disk is write protected + +**/ +EFI_STATUS +CheckStatus3 ( + IN UINT8 StatusRegister3 + ) +{ + if ((StatusRegister3 & STS3_WP) != 0) { + return EFI_WRITE_PROTECTED; + } + + return EFI_SUCCESS; +} + +/** + Calculate the number of block in the same cylinder according to LBA. + + @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV + @param LBA EFI_LBA: The starting logic block address + @param NumberOfBlocks UINTN: The number of blocks + + @return The number of blocks in the same cylinder which the starting + logic block address is LBA + +**/ +UINTN +GetTransferBlockCount ( + IN FDC_BLK_IO_DEV *FdcDev, + IN EFI_LBA LBA, + IN UINTN NumberOfBlocks + ) +{ + UINT8 EndOfTrack; + UINT8 Head; + UINT8 SectorsInTrack; + + // + // Calculate the number of block in the same cylinder + // + EndOfTrack = DISK_1440K_EOT; + Head = (UINT8) ((UINTN) LBA / EndOfTrack % 2); + + SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) LBA % EndOfTrack)); + if (SectorsInTrack < NumberOfBlocks) { + return SectorsInTrack; + } else { + return NumberOfBlocks; + } +} + +/** + When the Timer(2s) off, turn the drive's motor off. + + @param Event EFI_EVENT: Event(the timer) whose notification function is being + invoked + @param Context VOID *: Pointer to the notification function's context + +**/ +VOID +EFIAPI +FddTimerProc ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + FDC_BLK_IO_DEV *FdcDev; + UINT8 Data; + + FdcDev = (FDC_BLK_IO_DEV *) Context; + + // + // Get the motor status + // + Data = FdcReadPort (FdcDev, FDC_REGISTER_DOR); + + if (((FdcDev->Disk == FdcDisk0) && ((Data & 0x10) != 0x10)) || + ((FdcDev->Disk == FdcDisk1) && ((Data & 0x21) != 0x21)) + ) { + return ; + } + // + // the motor is on, so need motor off + // + Data = 0x0C; + Data = (UINT8) (Data | (SELECT_DRV & FdcDev->Disk)); + FdcWritePort (FdcDev, FDC_REGISTER_DOR, Data); + MicroSecondDelay (500); +} + +/** + Read an I/O port of FDC. + + @param[in] FdcDev A pointer to FDC_BLK_IO_DEV. + @param[in] Offset The address offset of the I/O port. + + @retval 8-bit data read from the I/O port. +**/ +UINT8 +FdcReadPort ( + IN FDC_BLK_IO_DEV *FdcDev, + IN UINT32 Offset + ) +{ + EFI_STATUS Status; + UINT8 Data; + + Status = FdcDev->IsaIo->Io.Read ( + FdcDev->IsaIo, + EfiIsaIoWidthUint8, + FdcDev->BaseAddress + Offset, + 1, + &Data + ); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Write an I/O port of FDC. + + @param[in] FdcDev A pointer to FDC_BLK_IO_DEV + @param[in] Offset The address offset of the I/O port + @param[in] Data 8-bit Value written to the I/O port +**/ +VOID +FdcWritePort ( + IN FDC_BLK_IO_DEV *FdcDev, + IN UINT32 Offset, + IN UINT8 Data + ) +{ + EFI_STATUS Status; + + Status = FdcDev->IsaIo->Io.Write ( + FdcDev->IsaIo, + EfiIsaIoWidthUint8, + FdcDev->BaseAddress + Offset, + 1, + &Data + ); + ASSERT_EFI_ERROR (Status); +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf new file mode 100644 index 0000000000..65756209f5 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf @@ -0,0 +1,78 @@ +## @file +# Provides ISA Floppy Disk support. +# +# Provides ISA Floppy Disk UEFI Driver conforming to the UEFI driver model. The +# driver provides support for two drives per controller, DMA channel 2, diskette +# change line and write protect. Currently only 1.44MB drives are supported. +# +# 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 +# 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 = IsaFloppyDxe + MODULE_UNI_FILE = IsaFloppyDxe.uni + FILE_GUID = 0abd8284-6da3-4616-971a-83a5148067ba + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeIsaFloppy + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# DRIVER_BINDING = gFdcControllerDriver; +# COMPONENT_NAME = gIsaFloppyComponentName; +# COMPONENT_NAME2 = gIsaFloppyComponentName2; +# +[Sources] + ComponentName.c + ComponentName.h + IsaFloppyCtrl.c + IsaFloppyBlock.c + IsaFloppy.c + IsaFloppy.h + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + UefiLib + BaseLib + UefiDriverEntryPoint + DebugLib + TimerLib + PcdLib + +[Protocols] + gEfiIsaIoProtocolGuid ## TO_START + gEfiBlockIoProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## TO_START + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable ## CONSUMES + +# +# [Event] +# ## +# # Floppy motor control timer event. +# # +# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES +# + +[UserExtensions.TianoCore."ExtraFiles"] + IsaFloppyDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni new file mode 100644 index 0000000000..b33eb0ebad Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni new file mode 100644 index 0000000000..e9e4b5bfd1 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h new file mode 100644 index 0000000000..a6a7e42aee --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h @@ -0,0 +1,235 @@ +/** @file +Definition of FDC registers and structures. + +Copyright (c) 2006 - 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 _PEI_RECOVERY_FDC_H_ +#define _PEI_RECOVERY_FDC_H_ + +// +// FDC Registers +// +#define FDC_REGISTER_DOR 2 //Digital Output Register +#define FDC_REGISTER_MSR 4 //Main Status Register +#define FDC_REGISTER_DTR 5 //Data Register +#define FDC_REGISTER_CCR 7 //Configuration Control Register(data rate select) +#define FDC_REGISTER_DIR 7 //Digital Input Register(diskchange) +// +// FDC Register Bit Definitions +// +// +// Digital Out Register(WO) +// +#define SELECT_DRV BIT0 // Select Drive: 0=A 1=B +#define RESET_FDC BIT2 // Reset FDC +#define INT_DMA_ENABLE BIT3 // Enable Int & DMA +#define DRVA_MOTOR_ON BIT4 // Turn On Drive A Motor +#define DRVB_MOTOR_ON BIT5 // Turn On Drive B Motor +// +// Main Status Register(RO) +// +#define MSR_DAB BIT0 // Drive A Busy +#define MSR_DBB BIT1 // Drive B Busy +#define MSR_CB BIT4 // FDC Busy +#define MSR_NDM BIT5 // Non-DMA Mode +#define MSR_DIO BIT6 // Data Input/Output +#define MSR_RQM BIT7 // Request For Master +// +// Configuration Control Register(WO) +// +#define CCR_DRC (BIT0 | BIT1) // Data Rate select +// +// Digital Input Register(RO) +// +#define DIR_DCL BIT7 // Disk change line +#define DRC_500KBS 0x0 // 500K +#define DRC_300KBS 0x01 // 300K +#define DRC_250KBS 0x02 // 250K +// +// FDC Command Code +// +#define READ_DATA_CMD 0x06 +#define SEEK_CMD 0x0F +#define RECALIBRATE_CMD 0x07 +#define SENSE_INT_STATUS_CMD 0x08 +#define SPECIFY_CMD 0x03 +#define SENSE_DRV_STATUS_CMD 0x04 + +/// +/// CMD_MT: Multi_Track Selector +/// when set , this flag selects the multi-track operating mode. +/// In this mode, the FDC treats a complete cylinder under head0 and 1 as a single track +/// +#define CMD_MT BIT7 + +/// +/// CMD_MFM: MFM/FM Mode Selector +/// A one selects the double density(MFM) mode +/// A zero selects single density (FM) mode +/// +#define CMD_MFM BIT6 + +/// +/// CMD_SK: Skip Flag +/// When set to 1, sectors containing a deleted data address mark will automatically be skipped +/// during the execution of Read Data. +/// When set to 0, the sector is read or written the same as the read and write commands. +/// +#define CMD_SK BIT5 + +// +// FDC Status Register Bit Definitions +// +// +// Status Register 0 +// +#define STS0_IC (BIT7 | BIT6) // Interrupt Code +#define STS0_SE BIT5 // Seek End: the FDC completed a seek or recalibrate command +#define STS0_EC BIT4 // Equipment Check +#define STS0_NR BIT3 // Not Ready(unused), this bit is always 0 +#define STS0_HA BIT2 // Head Address: the current head address +// +// STS0_US1 & STS0_US0: Drive Select(the current selected drive) +// +#define STS0_US1 BIT1 // Unit Select1 +#define STS0_US0 BIT0 // Unit Select0 +// +// Status Register 1 +// +#define STS1_EN BIT7 // End of Cylinder +// +// BIT6 is unused +// +#define STS1_DE BIT5 // Data Error: The FDC detected a CRC error in either the ID field or data field of a sector +#define STS1_OR BIT4 // Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service within the required time interval +// +// BIT3 is unused +// +#define STS1_ND BIT2 // No data +#define STS1_NW BIT1 // Not Writable +#define STS1_MA BIT0 // Missing Address Mark + +// +// Status Register 2 +// +// BIT7 is unused +// +#define STS2_CM BIT6 // Control Mark +#define STS2_DD BIT5 // Data Error in Data Field: The FDC detected a CRC error in the data field +#define STS2_WC BIT4 // Wrong Cylinder: The track address from sector ID field is different from the track address maintained inside FDC +// +// BIT3 is unused +// BIT2 is unused +// +#define STS2_BC BIT1 // Bad Cylinder +#define STS2_MD BIT0 // Missing Address Mark in DataField + +// +// Status Register 3 +// +// BIT7 is unused +// +#define STS3_WP BIT6 // Write Protected +// +// BIT5 is unused +// +#define STS3_T0 BIT4 // Track 0 +// +// BIT3 is unused +// +#define STS3_HD BIT2 // Head Address +// +// STS3_US1 & STS3_US0 : Drive Select +// +#define STS3_US1 BIT1 // Unit Select1 +#define STS3_US0 BIT0 // Unit Select0 + +// +// Status Register 0 Interrupt Code Description +// +#define IC_NT 0x0 // Normal Termination of Command +#define IC_AT 0x40 // Abnormal Termination of Command +#define IC_IC 0x80 // Invalid Command +#define IC_ATRC 0xC0 // Abnormal Termination caused by Polling + +/// +/// Table of parameters for diskette +/// +typedef struct { + UINT8 EndOfTrack; ///< End of track + UINT8 GapLength; ///< Gap length + UINT8 DataLength; ///< Data length + UINT8 Number; ///< Number of bytes per sector + UINT8 MaxTrackNum; + UINT8 MotorStartTime; + UINT8 MotorOffTime; + UINT8 HeadSettlingTime; + UINT8 DataTransferRate; +} DISKET_PARA_TABLE; + +/// +/// Structure for FDC Command Packet 1 +/// +typedef struct { + UINT8 CommandCode; + UINT8 DiskHeadSel; + UINT8 Cylinder; + UINT8 Head; + UINT8 Sector; + UINT8 Number; + UINT8 EndOfTrack; + UINT8 GapLength; + UINT8 DataLength; +} FDC_COMMAND_PACKET1; + +/// +/// Structure for FDC Command Packet 2 +/// +typedef struct { + UINT8 CommandCode; + UINT8 DiskHeadSel; +} FDC_COMMAND_PACKET2; + +/// +/// Structure for FDC Specify Command +/// +typedef struct { + UINT8 CommandCode; + UINT8 SrtHut; + UINT8 HltNd; +} FDC_SPECIFY_CMD; + +/// +/// Structure for FDC Seek Command +/// +typedef struct { + UINT8 CommandCode; + UINT8 DiskHeadSel; + UINT8 NewCylinder; +} FDC_SEEK_CMD; + +/// +/// Structure for FDC Result Packet +/// +typedef struct { + UINT8 Status0; + UINT8 Status1; + UINT8 Status2; + UINT8 CylinderNumber; + UINT8 HeaderAddress; + UINT8 Record; + UINT8 Number; +} FDC_RESULT_PACKET; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.c new file mode 100644 index 0000000000..765a46dd31 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.c @@ -0,0 +1,1759 @@ +/** @file +Floppy Peim to support Recovery function from Floppy device. + +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 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 "FloppyPeim.h" + + +PEI_DMA_TABLE mRegisterTable[] = { + // + // DMA2: Clear Byte Ptr, Enable + // + { + R_8237_DMA_CBPR_CH4_7, + 0 + }, + { + R_8237_DMA_COMMAND_CH4_7, + 0 + }, + // + // DMA1: Clear Byte Ptr, Enable + // + { + R_8237_DMA_CBPR_CH0_3, + 0 + }, + { + R_8237_DMA_COMMAND_CH0_3, + 0 + }, + // + // Configure Channel 4 for Cascade Mode + // Clear DMA Request and enable DREQ + // + { + R_8237_DMA_CHMODE_CH4_7, + V_8237_DMA_CHMODE_CASCADE | 0 + }, + { + R_8237_DMA_STA_CH4_7, + 0 + }, + { + R_8237_DMA_WRSMSK_CH4_7, + 0 + }, + // + // Configure DMA1 (Channels 0-3) for Single Mode + // Clear DMA Request and enable DREQ + // + { + R_8237_DMA_CHMODE_CH0_3, + V_8237_DMA_CHMODE_SINGLE | 0 + }, + { + R_8237_DMA_STA_CH0_3, + 0 + }, + { + R_8237_DMA_WRSMSK_CH0_3, + 0 + }, + { + R_8237_DMA_CHMODE_CH0_3, + V_8237_DMA_CHMODE_SINGLE | 1 + }, + { + R_8237_DMA_STA_CH0_3, + 1 + }, + { + R_8237_DMA_WRSMSK_CH0_3, + 1 + }, + { + R_8237_DMA_CHMODE_CH0_3, + V_8237_DMA_CHMODE_SINGLE | 2 + }, + { + R_8237_DMA_STA_CH0_3, + 2 + }, + { + R_8237_DMA_WRSMSK_CH0_3, + 2 + }, + { + R_8237_DMA_CHMODE_CH0_3, + V_8237_DMA_CHMODE_SINGLE | 3 + }, + { + R_8237_DMA_STA_CH0_3, + 3 + }, + { + R_8237_DMA_WRSMSK_CH0_3, + 3 + }, + // + // Configure DMA2 (Channels 5-7) for Single Mode + // Clear DMA Request and enable DREQ + // + { + R_8237_DMA_CHMODE_CH4_7, + V_8237_DMA_CHMODE_SINGLE | 1 + }, + { + R_8237_DMA_STA_CH4_7, + 1 + }, + { + R_8237_DMA_WRSMSK_CH4_7, + 1 + }, + { + R_8237_DMA_CHMODE_CH4_7, + V_8237_DMA_CHMODE_SINGLE | 2 + }, + { + R_8237_DMA_STA_CH4_7, + 2 + }, + { + R_8237_DMA_WRSMSK_CH4_7, + 2 + }, + { + R_8237_DMA_CHMODE_CH4_7, + V_8237_DMA_CHMODE_SINGLE | 3 + }, + { + R_8237_DMA_STA_CH4_7, + 3 + }, + { + R_8237_DMA_WRSMSK_CH4_7, + 3 + } +}; + +// +// Table of diskette parameters of various diskette types +// +DISKET_PARA_TABLE DiskPara[9] = { + { + 0x09, + 0x50, + 0xff, + 0x2, + 0x27, + 0x4, + 0x25, + 0x14, + 0x80 + }, + { + 0x09, + 0x2a, + 0xff, + 0x2, + 0x27, + 0x4, + 0x25, + 0x0f, + 0x40 + }, + { + 0x0f, + 0x54, + 0xff, + 0x2, + 0x4f, + 0x4, + 0x25, + 0x0f, + 0x0 + }, + { + 0x09, + 0x50, + 0xff, + 0x2, + 0x4f, + 0x4, + 0x25, + 0x0f, + 0x80 + }, + { + 0x09, + 0x2a, + 0xff, + 0x2, + 0x4f, + 0x4, + 0x25, + 0x0f, + 0x80 + }, + { + 0x12, + 0x1b, + 0xff, + 0x2, + 0x4f, + 0x4, + 0x25, + 0x0f, + 0x0 + }, + { + 0x09, + 0x2a, + 0xff, + 0x2, + 0x4f, + 0x4, + 0x25, + 0x0f, + 0x80 + }, + { + 0x12, + 0x1b, + 0xff, + 0x2, + 0x4f, + 0x4, + 0x25, + 0x0f, + 0x0 + }, + { + 0x24, + 0x1b, + 0xff, + 0x2, + 0x4f, + 0x4, + 0x25, + 0x0f, + 0xc0 + } +}; + +// +// Byte per sector corresponding to various device types. +// +UINTN BytePerSector[6] = { 0, 256, 512, 1024, 2048, 4096 }; + +FDC_BLK_IO_DEV mBlockIoDevTemplate = { + FDC_BLK_IO_DEV_SIGNATURE, + { + FdcGetNumberOfBlockDevices, + FdcGetBlockDeviceMediaInfo, + FdcReadBlocks, + }, + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiVirtualBlockIoPpiGuid, + NULL + }, + 0, + {{0}} +}; + +/** + Wait and check if bits for DIO and RQM of FDC Main Status Register + indicates FDC is ready for read or write. + + Before writing to FDC or reading from FDC, the Host must examine + the bit7(RQM) and bit6(DIO) of the Main Status Register. + That is to say: + Command bytes can not be written to Data Register unless RQM is 1 and DIO is 0. + Result bytes can not be read from Data Register unless RQM is 1 and DIO is 1. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param DataIn Indicates data input or output. + TRUE means input. + FALSE means output. + @param TimeoutInMseconds Timeout value to wait. + + @retval EFI_SUCCESS FDC is ready. + @retval EFI_NOT_READY FDC is not ready within the specified time period. + +**/ +EFI_STATUS +FdcDRQReady ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN BOOLEAN DataIn, + IN UINTN TimeoutInMseconds + ) +{ + UINTN Delay; + UINT8 StatusRegister; + UINT8 BitInOut; + + // + // Check bit6 of Main Status Register. + // + BitInOut = 0; + if (DataIn) { + BitInOut = BIT6; + } + + Delay = ((TimeoutInMseconds * STALL_1_MSECOND) / FDC_CHECK_INTERVAL) + 1; + do { + StatusRegister = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_MSR)); + if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == BitInOut) { + // + // FDC is ready + // + break; + } + + MicroSecondDelay (FDC_SHORT_DELAY); + } while (--Delay > 0); + + if (Delay == 0) { + // + // FDC is not ready within the specified time period + // + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +/** + Read a byte from FDC data register. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param Pointer Pointer to buffer to hold data read from FDC. + + @retval EFI_SUCCESS Byte successfully read. + @retval EFI_DEVICE_ERROR FDC is not ready. + +**/ +EFI_STATUS +DataInByte ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + OUT UINT8 *Pointer + ) +{ + UINT8 Data; + + // + // Wait for 1ms and detect the FDC is ready to be read + // + if (FdcDRQReady (FdcBlkIoDev, TRUE, 1) != EFI_SUCCESS) { + // + // FDC is not ready. + // + return EFI_DEVICE_ERROR; + } + + Data = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DTR)); + MicroSecondDelay (FDC_SHORT_DELAY); + *Pointer = Data; + + return EFI_SUCCESS; +} + +/** + Write a byte to FDC data register. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param Pointer Pointer to data to write. + + @retval EFI_SUCCESS Byte successfully written. + @retval EFI_DEVICE_ERROR FDC is not ready. + +**/ +EFI_STATUS +DataOutByte ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN UINT8 *Pointer + ) +{ + UINT8 Data; + + // + // Wait for 1ms and detect the FDC is ready to be written + // + if (FdcDRQReady (FdcBlkIoDev, FALSE, 1) != EFI_SUCCESS) { + // + // FDC is not ready. + // + return EFI_DEVICE_ERROR; + } + + Data = *Pointer; + IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DTR), Data); + MicroSecondDelay (FDC_SHORT_DELAY); + + return EFI_SUCCESS; +} + +/** + Get Sts0 and Pcn status from FDC + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV + @param Sts0 Value of Sts0 + @param Pcn Value of Pcn + + @retval EFI_SUCCESS Successfully retrieved status value of Sts0 and Pcn. + @retval EFI_DEVICE_ERROR Fail to send SENSE_INT_STATUS_CMD. + @retval EFI_DEVICE_ERROR Fail to read Sts0. + @retval EFI_DEVICE_ERROR Fail to read Pcn. + +**/ +EFI_STATUS +SenseIntStatus ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + OUT UINT8 *Sts0, + OUT UINT8 *Pcn + ) +{ + UINT8 Command; + + Command = SENSE_INT_STATUS_CMD; + + if (DataOutByte (FdcBlkIoDev, &Command) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (DataInByte (FdcBlkIoDev, Sts0) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (DataInByte (FdcBlkIoDev, Pcn) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Issue Specify command. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + + @retval EFI_SUCCESS Specify command successfully issued. + @retval EFI_DEVICE_ERROR FDC device has errors. + +**/ +EFI_STATUS +Specify ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev + ) +{ + FDC_SPECIFY_CMD Command; + UINTN Index; + UINT8 *Pointer; + + ZeroMem (&Command, sizeof (FDC_SPECIFY_CMD)); + Command.CommandCode = SPECIFY_CMD; + // + // set SRT, HUT + // + Command.SrtHut = 0xdf; + // + // 0xdf; + // set HLT and DMA + // + Command.HltNd = 0x02; + + Pointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDC_SPECIFY_CMD); Index++) { + if (DataOutByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + +/** + Wait until busy bit is cleared. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param DevPos Position of FDC (Driver A or B) + @param TimeoutInMseconds Timeout value to wait. + + @retval EFI_SUCCESS Busy bit has been cleared before timeout. + @retval EFI_TIMEOUT Time goes out before busy bit is cleared. + +**/ +EFI_STATUS +FdcWaitForBSYClear ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN UINT8 DevPos, + IN UINTN TimeoutInMseconds + ) +{ + UINTN Delay; + UINT8 StatusRegister; + UINT8 Mask; + + // + // How to determine drive and command are busy or not: by the bits of Main Status Register + // bit0: Drive 0 busy (drive A) + // bit1: Drive 1 busy (drive B) + // bit4: Command busy + // + // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4 + // + Mask = (UINT8) ((DevPos == 0 ? MSR_DAB : MSR_DBB) | MSR_CB); + + Delay = ((TimeoutInMseconds * STALL_1_MSECOND) / FDC_CHECK_INTERVAL) + 1; + + do { + StatusRegister = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_MSR)); + + if ((StatusRegister & Mask) == 0x00) { + // + // not busy + // + break; + } + + MicroSecondDelay (FDC_SHORT_DELAY); + } while (--Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Reset FDC device. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV + @param DevPos Index of FDC device. + + @retval EFI_SUCCESS FDC device successfully reset. + @retval EFI_DEVICE_ERROR Fail to reset FDC device. + +**/ +EFI_STATUS +FdcReset ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN UINT8 DevPos + ) +{ + UINT8 Data; + UINT8 Sts0; + UINT8 Pcn; + UINTN Index; + + // + // Reset specified Floppy Logic Drive according to Fdd -> Disk + // Set Digital Output Register(DOR) to do reset work + // bit0 & bit1 of DOR : Drive Select + // bit2 : Reset bit + // bit3 : DMA and Int bit + // Reset : A "0" written to bit2 resets the FDC, this reset will remain active until + // a "1" is written to this bit. + // Reset step 1: + // use bit0 & bit1 to select the logic drive + // write "0" to bit2 + // + Data = 0x0; + Data = (UINT8) (Data | (SELECT_DRV & DevPos)); + IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DOR), Data); + + // + // Wait some time, at least 120us. + // + MicroSecondDelay (FDC_RESET_DELAY); + // + // Reset step 2: + // write "1" to bit2 + // write "1" to bit3 : enable DMA + // + Data |= 0x0C; + IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DOR), Data); + + MicroSecondDelay (FDC_RESET_DELAY); + + // + // Wait until specified floppy logic drive is not busy + // + if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // Set the Transfer Data Rate + // + IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_CCR), 0x0); + + MicroSecondDelay (FDC_MEDIUM_DELAY); + + // + // Issue Sense interrupt command for each drive (totally 4 drives) + // + for (Index = 0; Index < 4; Index++) { + if (SenseIntStatus (FdcBlkIoDev, &Sts0, &Pcn) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + // + // Issue Specify command + // + if (Specify (FdcBlkIoDev) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Turn on the motor of floppy drive. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param Info Information of floppy device. + + @retval EFI_SUCCESS Motor is successfully turned on. + @retval EFI_SUCCESS Motor is already on. + @retval EFI_DEVICE_ERROR Busy bit of FDC cannot be cleared. + +**/ +EFI_STATUS +MotorOn ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN OUT PEI_FLOPPY_DEVICE_INFO *Info + ) +{ + UINT8 Data; + UINT8 DevPos; + + // + // Control of the floppy drive motors is a big pain. If motor is off, you have to turn it + // on first. But you can not leave the motor on all the time, since that would wear out the + // disk. On the other hand, if you turn the motor off after each operation, the system performance + // will be awful. The compromise used in this driver is to leave the motor on for 2 seconds after + // each operation. If a new operation is started in that interval(2s), the motor need not be + // turned on again. If no new operation is started, a timer goes off and the motor is turned off. + // + DevPos = Info->DevPos; + + // + // If the Motor is already on, just return EFI_SUCCESS. + // + if (Info->MotorOn) { + return EFI_SUCCESS; + } + // + // The drive's motor is off, so need turn it on. + // First check if command and drive are busy or not. + // + if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // for drive A: 1CH, drive B: 2DH + // + Data = 0x0C; + Data = (UINT8) (Data | (SELECT_DRV & DevPos)); + if (DevPos == 0) { + Data |= DRVA_MOTOR_ON; + } else { + Data |= DRVB_MOTOR_ON; + } + + Info->MotorOn = FALSE; + + // + // Turn on the motor and wait for some time to ensure it takes effect. + // + IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DOR), Data); + MicroSecondDelay (FDC_LONG_DELAY); + + Info->MotorOn = TRUE; + + return EFI_SUCCESS; +} + +/** + Turn off the motor of floppy drive. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param Info Information of floppy device. + +**/ +VOID +MotorOff ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN OUT PEI_FLOPPY_DEVICE_INFO *Info + ) +{ + UINT8 Data; + UINT8 DevPos; + + DevPos = Info->DevPos; + + if (!Info->MotorOn) { + return; + } + // + // The motor is on, so need motor off + // + Data = 0x0C; + Data = (UINT8) (Data | (SELECT_DRV & DevPos)); + + IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DOR), Data); + MicroSecondDelay (FDC_SHORT_DELAY); + + Info->MotorOn = FALSE; +} + +/** + Recalibrate the FDC device. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param Info Information of floppy device. + + @retval EFI_SUCCESS FDC successfully recalibrated. + @retval EFI_DEVICE_ERROR Fail to send RECALIBRATE_CMD. + @retval EFI_DEVICE_ERROR Fail to get status value of Sts0 and Pcn. + @retval EFI_DEVICE_ERROR Fail to recalibrate FDC device. + +**/ +EFI_STATUS +Recalibrate ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN OUT PEI_FLOPPY_DEVICE_INFO *Info + ) +{ + FDC_COMMAND_PACKET2 Command; + UINTN Index; + UINT8 Sts0; + UINT8 Pcn; + UINT8 *Pointer; + UINT8 Count; + UINT8 DevPos; + + DevPos = Info->DevPos; + + // + // We would try twice. + // + Count = 2; + while (Count > 0) { + ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET2)); + Command.CommandCode = RECALIBRATE_CMD; + // + // drive select + // + if (DevPos == 0) { + Command.DiskHeadSel = 0; + } else { + Command.DiskHeadSel = 1; + } + + Pointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDC_COMMAND_PACKET2); Index++) { + if (DataOutByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + + MicroSecondDelay (FDC_RECALIBRATE_DELAY); + + if (SenseIntStatus (FdcBlkIoDev, &Sts0, &Pcn) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((Sts0 & 0xf0) == BIT5 && Pcn == 0) { + // + // Recalibration is successful. + // + Info->Pcn = 0; + Info->NeedRecalibrate = FALSE; + + return EFI_SUCCESS; + } else { + // + // Recalibration is not successful. Try again. + // If trial is used out, return EFI_DEVICE_ERROR. + // + Count--; + if (Count == 0) { + return EFI_DEVICE_ERROR; + } + } + } + + return EFI_SUCCESS; +} + +/** + Seek for the cylinder according to given LBA. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param Info Information of floppy device. + @param Lba LBA for which to seek for cylinder. + + @retval EFI_SUCCESS Successfully moved to the destination cylinder. + @retval EFI_SUCCESS Destination cylinder is just the present cylinder. + @retval EFI_DEVICE_ERROR Fail to move to the destination cylinder. + +**/ +EFI_STATUS +Seek ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN OUT PEI_FLOPPY_DEVICE_INFO *Info, + IN EFI_PEI_LBA Lba + ) +{ + FDC_SEEK_CMD Command; + DISKET_PARA_TABLE *Para; + UINT8 EndOfTrack; + UINT8 Head; + UINT8 Cylinder; + UINT8 Sts0; + UINT8 *Pointer; + UINT8 Pcn; + UINTN Index; + UINT8 Gap; + UINT8 DevPos; + + DevPos = Info->DevPos; + if (Info->NeedRecalibrate) { + if (Recalibrate (FdcBlkIoDev, Info) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // Recalibrate Success + // + Info->NeedRecalibrate = FALSE; + } + + // + // Get the base of disk parameter information corresponding to its type. + // + Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type); + EndOfTrack = Para->EndOfTrack; + // + // Calculate cylinder based on Lba and EOT + // + Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2); + + // + // If the dest cylinder is the present cylinder, unnecessary to do the seek operation + // + if (Info->Pcn == Cylinder) { + return EFI_SUCCESS; + } + + // + // Calculate the head : 0 or 1 + // + Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); + + ZeroMem (&Command, sizeof (FDC_SEEK_CMD)); + Command.CommandCode = SEEK_CMD; + if (DevPos == 0) { + Command.DiskHeadSel = 0; + } else { + Command.DiskHeadSel = 1; + } + + // + // Send command to move to destination cylinder. + // + Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2)); + Command.NewCylinder = Cylinder; + + Pointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDC_SEEK_CMD); Index++) { + if (DataOutByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + + MicroSecondDelay (FDC_SHORT_DELAY); + + // + // Calculate waiting time, which is proportional to the gap between destination + // cylinder and present cylinder. + // + if (Info->Pcn > Cylinder) { + Gap = (UINT8) (Info->Pcn - Cylinder); + } else { + Gap = (UINT8) (Cylinder - Info->Pcn); + } + + MicroSecondDelay ((Gap + 1) * FDC_LONG_DELAY); + + // + // Confirm if the new cylinder is the destination and status is correct. + // + if (SenseIntStatus (FdcBlkIoDev, &Sts0, &Pcn) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((Sts0 & 0xf0) == BIT5) { + Info->Pcn = Command.NewCylinder; + Info->NeedRecalibrate = FALSE; + return EFI_SUCCESS; + } else { + Info->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } +} + +/** + Check if diskette is changed. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV + @param Info Information of floppy device. + + @retval EFI_SUCCESS Diskette is not changed. + @retval EFI_MEDIA_CHANGED Diskette is changed. + @retval EFI_NO_MEDIA No diskette. + @retval EFI_DEVICE_ERROR Fail to do the seek or recalibrate operation. + +**/ +EFI_STATUS +DisketChanged ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN OUT PEI_FLOPPY_DEVICE_INFO *Info + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Check change line + // + Data = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DIR)); + + MicroSecondDelay (FDC_SHORT_DELAY); + + if ((Data & DIR_DCL) == DIR_DCL) { + if (Info->Pcn != 0) { + Status = Recalibrate (FdcBlkIoDev, Info); + } else { + Status = Seek (FdcBlkIoDev, Info, 0x30); + } + + if (Status != EFI_SUCCESS) { + // + // Fail to do the seek or recalibrate operation + // + return EFI_DEVICE_ERROR; + } + + Data = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DIR)); + + MicroSecondDelay (FDC_SHORT_DELAY); + + if ((Data & DIR_DCL) == DIR_DCL) { + return EFI_NO_MEDIA; + } + + return EFI_MEDIA_CHANGED; + } + + return EFI_SUCCESS; +} + +/** + Detects if FDC device exists. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV + @param Info Information of floppy device. + @param MediaInfo Information of floppy media. + + @retval TRUE FDC device exists and is working properly. + @retval FALSE FDC device does not exist or cannot work properly. + +**/ +BOOLEAN +DiscoverFdcDevice ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN OUT PEI_FLOPPY_DEVICE_INFO *Info, + OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo + ) +{ + EFI_STATUS Status; + DISKET_PARA_TABLE *Para; + + Status = MotorOn (FdcBlkIoDev, Info); + if (Status != EFI_SUCCESS) { + return FALSE; + } + + Status = Recalibrate (FdcBlkIoDev, Info); + + if (Status != EFI_SUCCESS) { + MotorOff (FdcBlkIoDev, Info); + return FALSE; + } + // + // Set Media Parameter + // + MediaInfo->DeviceType = LegacyFloppy; + MediaInfo->MediaPresent = TRUE; + + // + // Check Media + // + Status = DisketChanged (FdcBlkIoDev, Info); + if (Status == EFI_NO_MEDIA) { + // + // No diskette in floppy. + // + MediaInfo->MediaPresent = FALSE; + } else if (Status != EFI_MEDIA_CHANGED && Status != EFI_SUCCESS) { + // + // EFI_DEVICE_ERROR + // + MotorOff (FdcBlkIoDev, Info); + return FALSE; + } + + MotorOff (FdcBlkIoDev, Info); + + // + // Get the base of disk parameter information corresponding to its type. + // + Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type); + + MediaInfo->BlockSize = BytePerSector[Para->Number]; + MediaInfo->LastBlock = Para->EndOfTrack * 2 * (Para->MaxTrackNum + 1) - 1; + + return TRUE; +} + +/** + Enumerate floppy device + + @param FdcBlkIoDev Instance of floppy device controller + + @return Number of FDC devices. + +**/ +UINT8 +FdcEnumeration ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev + ) +{ + UINT8 DevPos; + UINT8 DevNo; + EFI_PEI_BLOCK_IO_MEDIA MediaInfo; + EFI_STATUS Status; + + DevNo = 0; + + // + // DevPos=0 means Drive A, 1 means Drive B. + // + for (DevPos = 0; DevPos < 2; DevPos++) { + // + // Detecting device presence + // + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_PRESENCE_DETECT); + + // + // Reset FDC + // + Status = FdcReset (FdcBlkIoDev, DevPos); + + if (EFI_ERROR (Status)) { + continue; + } + + FdcBlkIoDev->DeviceInfo[DevPos].DevPos = DevPos; + FdcBlkIoDev->DeviceInfo[DevPos].Pcn = 0; + FdcBlkIoDev->DeviceInfo[DevPos].MotorOn = FALSE; + FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate = TRUE; + FdcBlkIoDev->DeviceInfo[DevPos].Type = FdcType1440K1440K; + + // + // Discover FDC device + // + if (DiscoverFdcDevice (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DevPos]), &MediaInfo)) { + FdcBlkIoDev->DeviceInfo[DevNo].DevPos = DevPos; + + FdcBlkIoDev->DeviceInfo[DevNo].Pcn = FdcBlkIoDev->DeviceInfo[DevPos].Pcn; + FdcBlkIoDev->DeviceInfo[DevNo].MotorOn = FdcBlkIoDev->DeviceInfo[DevPos].MotorOn; + FdcBlkIoDev->DeviceInfo[DevNo].NeedRecalibrate = FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate; + FdcBlkIoDev->DeviceInfo[DevNo].Type = FdcBlkIoDev->DeviceInfo[DevPos].Type; + + CopyMem ( + &(FdcBlkIoDev->DeviceInfo[DevNo].MediaInfo), + &MediaInfo, + sizeof (EFI_PEI_BLOCK_IO_MEDIA) + ); + + DevNo++; + } else { + // + // Assume controller error + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_EC_CONTROLLER_ERROR + ); + } + } + + FdcBlkIoDev->DeviceCount = DevNo; + return DevNo; +} + +/** + Checks result reflected by FDC_RESULT_PACKET. + + @param Result FDC_RESULT_PACKET read from FDC after certain operation. + @param Info Information of floppy device. + + @retval EFI_SUCCESS Result is healthy. + @retval EFI_DEVICE_ERROR Result is not healthy. + +**/ +EFI_STATUS +CheckResult ( + IN FDC_RESULT_PACKET *Result, + OUT PEI_FLOPPY_DEVICE_INFO *Info + ) +{ + if ((Result->Status0 & STS0_IC) != IC_NT) { + if ((Result->Status0 & STS0_SE) == BIT5) { + // + // Seek error + // + Info->NeedRecalibrate = TRUE; + } + + Info->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } + // + // Check Status Register1 + // + if ((Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) != 0) { + Info->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } + // + // Check Status Register2 + // + if ((Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) != 0) { + Info->NeedRecalibrate = TRUE; + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Fill parameters for command packet. + + @param Info Information of floppy device. + @param Lba Logical block address. + @param Command Command for which for fill parameters. + +**/ +VOID +FillPara ( + IN PEI_FLOPPY_DEVICE_INFO *Info, + IN EFI_PEI_LBA Lba, + OUT FDC_COMMAND_PACKET1 *Command + ) +{ + DISKET_PARA_TABLE *Para; + UINT8 EndOfTrack; + UINT8 DevPos; + + DevPos = Info->DevPos; + + // + // Get the base of disk parameter information corresponding to its type. + // + Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type); + + EndOfTrack = Para->EndOfTrack; + + if (DevPos == 0) { + Command->DiskHeadSel = 0; + } else { + Command->DiskHeadSel = 1; + } + + Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2); + Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); + Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1); + Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2)); + Command->Number = Para->Number; + Command->EndOfTrack = Para->EndOfTrack; + Command->GapLength = Para->GapLength; + Command->DataLength = Para->DataLength; +} + +/** + Setup specifed FDC device. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param DevPos Index of FDC device. + + @retval EFI_SUCCESS FDC device successfully set up. + @retval EFI_DEVICE_ERROR FDC device has errors. + +**/ +EFI_STATUS +Setup ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN UINT8 DevPos + ) +{ + EFI_STATUS Status; + + IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_CCR), 0x0); + + MicroSecondDelay (FDC_MEDIUM_DELAY); + + Status = Specify (FdcBlkIoDev); + return Status; +} + +/** + Setup DMA channels to read data. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param Buffer Memory buffer for DMA transfer. + @param BlockSize the number of the bytes in one block. + @param NumberOfBlocks Number of blocks to read. + +**/ +VOID +SetDMA ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN VOID *Buffer, + IN UINTN BlockSize, + IN UINTN NumberOfBlocks + ) +{ + UINT8 Data; + UINTN Count; + + // + // Mask DMA channel 2; + // + IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, B_8237_DMA_WRSMSK_CMS | 2); + + // + // Clear first/last flip flop + // + IoWrite8 (R_8237_DMA_CBPR_CH0_3, B_8237_DMA_WRSMSK_CMS | 2); + + // + // Set mode + // + IoWrite8 (R_8237_DMA_CHMODE_CH0_3, V_8237_DMA_CHMODE_SINGLE | V_8237_DMA_CHMODE_IO2MEM | 2); + + // + // Set base address and page register + // + Data = (UINT8) (UINTN) Buffer; + IoWrite8 (R_8237_DMA_BASE_CA_CH2, Data); + Data = (UINT8) ((UINTN) Buffer >> 8); + IoWrite8 (R_8237_DMA_BASE_CA_CH2, Data); + + Data = (UINT8) ((UINTN) Buffer >> 16); + IoWrite8 (R_8237_DMA_MEM_LP_CH2, Data); + + // + // Set count register + // + Count = BlockSize * NumberOfBlocks - 1; + Data = (UINT8) (Count & 0xff); + IoWrite8 (R_8237_DMA_BASE_CC_CH2, Data); + Data = (UINT8) (Count >> 8); + IoWrite8 (R_8237_DMA_BASE_CC_CH2, Data); + + // + // Clear channel 2 mask + // + IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, 0x02); +} + + +/** + According to the block range specified by Lba and NumberOfBlocks, calculate + the number of blocks in the same sector, which can be transferred in a batch. + + @param Info Information of floppy device. + @param Lba Start address of block range. + @param NumberOfBlocks Number of blocks of the range. + + @return Number of blocks in the same sector. + +**/ +UINTN +GetTransferBlockCount ( + IN PEI_FLOPPY_DEVICE_INFO *Info, + IN EFI_PEI_LBA Lba, + IN UINTN NumberOfBlocks + ) +{ + DISKET_PARA_TABLE *Para; + UINT8 EndOfTrack; + UINT8 Head; + UINT8 SectorsInTrack; + + // + // Get the base of disk parameter information corresponding to its type. + // + Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type); + + EndOfTrack = Para->EndOfTrack; + Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); + + SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) Lba % EndOfTrack)); + if (SectorsInTrack < NumberOfBlocks) { + // + // Not all the block range locates in the same sector + // + return SectorsInTrack; + } else { + // + // All the block range is in the same sector. + // + return NumberOfBlocks; + } +} + +/** + Read data sector from FDC device. + + @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. + @param Info Information of floppy device. + @param Buffer Buffer to setup for DMA. + @param Lba The start address to read. + @param NumberOfBlocks Number of blocks to read. + + @retval EFI_SUCCESS Data successfully read out. + @retval EFI_DEVICE_ERROR FDC device has errors. + @retval EFI_TIMEOUT Command does not take effect in time. + +**/ +EFI_STATUS +ReadDataSector ( + IN FDC_BLK_IO_DEV *FdcBlkIoDev, + IN OUT PEI_FLOPPY_DEVICE_INFO *Info, + IN VOID *Buffer, + IN EFI_PEI_LBA Lba, + IN UINTN NumberOfBlocks + ) +{ + EFI_STATUS Status; + FDC_COMMAND_PACKET1 Command; + FDC_RESULT_PACKET Result; + UINTN Index; + UINTN Times; + UINT8 *Pointer; + + Status = Seek (FdcBlkIoDev, Info, Lba); + if (Status != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + // + // Set up DMA + // + SetDMA (FdcBlkIoDev, Buffer, Info->MediaInfo.BlockSize, NumberOfBlocks); + + // + // Allocate Read command packet + // + ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET1)); + Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK; + + // + // Fill parameters for command. + // + FillPara (Info, Lba, &Command); + + // + // Write command bytes to FDC + // + Pointer = (UINT8 *) (&Command); + for (Index = 0; Index < sizeof (FDC_COMMAND_PACKET1); Index++) { + if (DataOutByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + + // + // Wait for some time until command takes effect. + // + Times = (STALL_1_SECOND / FDC_CHECK_INTERVAL) + 1; + do { + if ((IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_MSR)) & 0xc0) == 0xc0) { + break; + } + + MicroSecondDelay (FDC_SHORT_DELAY); + } while (--Times > 0); + + if (Times == 0) { + // + // Command fails to take effect in time, return EFI_TIMEOUT. + // + return EFI_TIMEOUT; + } + + // + // Read result bytes from FDC + // + Pointer = (UINT8 *) (&Result); + for (Index = 0; Index < sizeof (FDC_RESULT_PACKET); Index++) { + if (DataInByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + + return CheckResult (&Result, Info); +} + +/** + Gets the count of block I/O devices that one specific block driver detects. + + This function is used for getting the count of block I/O devices that one + specific block driver detects. To the PEI ATAPI driver, it returns the number + of all the detected ATAPI devices it detects during the enumeration process. + To the PEI legacy floppy driver, it returns the number of all the legacy + devices it finds during its enumeration process. If no device is detected, + then the function will return zero. + + @param[in] PeiServices General-purpose services that are available + to every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI + instance. + @param[out] NumberBlockDevices The number of block I/O devices discovered. + + @retval EFI_SUCCESS Operation performed successfully. + +**/ +EFI_STATUS +EFIAPI +FdcGetNumberOfBlockDevices ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + OUT UINTN *NumberBlockDevices + ) +{ + FDC_BLK_IO_DEV *FdcBlkIoDev; + + FdcBlkIoDev = NULL; + + FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This); + + *NumberBlockDevices = FdcBlkIoDev->DeviceCount; + + return EFI_SUCCESS; +} + +/** + Gets a block device's media information. + + This function will provide the caller with the specified block device's media + information. If the media changes, calling this function will update the media + information accordingly. + + @param[in] PeiServices General-purpose services that are available to every + PEIM + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, the PPIs that + want to talk to a single device must specify the + device index that was assigned during the enumeration + process. This index is a number from one to + NumberBlockDevices. + @param[out] MediaInfo The media information of the specified block media. + The caller is responsible for the ownership of this + data structure. + + @retval EFI_SUCCESS Media information about the specified block device + was obtained successfully. + @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware + error. + @retval Others Other failure occurs. + +**/ +EFI_STATUS +EFIAPI +FdcGetBlockDeviceMediaInfo ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo + ) +{ + UINTN DeviceCount; + FDC_BLK_IO_DEV *FdcBlkIoDev; + BOOLEAN Healthy; + UINTN Index; + + FdcBlkIoDev = NULL; + + if (This == NULL || MediaInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + + FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This); + + DeviceCount = FdcBlkIoDev->DeviceCount; + + // + // DeviceIndex is a value from 1 to NumberBlockDevices. + // + if ((DeviceIndex < 1) || (DeviceIndex > DeviceCount) || (DeviceIndex > 2)) { + return EFI_INVALID_PARAMETER; + } + + Index = DeviceIndex - 1; + // + // Probe media and retrieve latest media information + // + Healthy = DiscoverFdcDevice ( + FdcBlkIoDev, + &FdcBlkIoDev->DeviceInfo[Index], + MediaInfo + ); + + if (!Healthy) { + return EFI_DEVICE_ERROR; + } + + CopyMem ( + &(FdcBlkIoDev->DeviceInfo[Index].MediaInfo), + MediaInfo, + sizeof (EFI_PEI_BLOCK_IO_MEDIA) + ); + + return EFI_SUCCESS; +} + +/** + Reads the requested number of blocks from the specified block device. + + The function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. If there is no media in the device, + the function returns EFI_NO_MEDIA. + + @param[in] PeiServices General-purpose services that are available to + every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, the PPIs that + want to talk to a single device must specify the device + index that was assigned during the enumeration process. + This index is a number from one to NumberBlockDevices. + @param[in] StartLBA The starting logical block address (LBA) to read from + on the device + @param[in] BufferSize The size of the Buffer in bytes. This number must be + a multiple of the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for the 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 attempting + to perform the read operation. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not properly aligned. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + +**/ +EFI_STATUS +EFIAPI +FdcReadBlocks ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_PEI_BLOCK_IO_MEDIA MediaInfo; + EFI_STATUS Status; + UINTN Count; + UINTN NumberOfBlocks; + UINTN BlockSize; + FDC_BLK_IO_DEV *FdcBlkIoDev; + VOID *MemPage; + + FdcBlkIoDev = NULL; + ZeroMem (&MediaInfo, sizeof (EFI_PEI_BLOCK_IO_MEDIA)); + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This); + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FdcGetBlockDeviceMediaInfo (PeiServices, This, DeviceIndex, &MediaInfo); + if (Status != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (!MediaInfo.MediaPresent) { + return EFI_NO_MEDIA; + } + + BlockSize = MediaInfo.BlockSize; + + // + // If BufferSize cannot be divided by block size of FDC device, + // return EFI_BAD_BUFFER_SIZE. + // + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + NumberOfBlocks = BufferSize / BlockSize; + + if ((StartLBA + NumberOfBlocks - 1) > FdcBlkIoDev->DeviceInfo[DeviceIndex - 1].MediaInfo.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + MemPage = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize)); + if ((MemPage == NULL) || ((UINTN) MemPage >= ISA_MAX_MEMORY_ADDRESS)) { + // + // If fail to allocate memory under ISA_MAX_MEMORY_ADDRESS, designate the address space for DMA + // + MemPage = (VOID *) ((UINTN) (UINT32) 0x0f00000); + } + Status = MotorOn (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1])); + if (Status != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + Status = Setup (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex - 1].DevPos); + if (Status != EFI_SUCCESS) { + MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1])); + return EFI_DEVICE_ERROR; + } + // + // Read data in batches. + // Blocks in the same cylinder are read out in a batch. + // + while ((Count = GetTransferBlockCount ( + &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1]), + StartLBA, + NumberOfBlocks + )) != 0 && Status == EFI_SUCCESS) { + Status = ReadDataSector ( + FdcBlkIoDev, + &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1]), + MemPage, + StartLBA, + Count + ); + CopyMem (Buffer, MemPage, BlockSize * Count); + StartLBA += Count; + NumberOfBlocks -= Count; + Buffer = (VOID *) ((UINTN) Buffer + Count * BlockSize); + } + + MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1])); + + switch (Status) { + case EFI_SUCCESS: + return EFI_SUCCESS; + + default: + FdcReset (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex - 1].DevPos); + return EFI_DEVICE_ERROR; + } +} + +/** + Initializes the floppy disk controller and installs FDC Block I/O PPI. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS Successfully initialized FDC and installed PPI. + @retval EFI_NOT_FOUND Cannot find FDC device. + @retval EFI_OUT_OF_RESOURCES Have no enough memory to create instance or descriptors. + @retval Other Fail to install FDC Block I/O PPI. + +**/ +EFI_STATUS +EFIAPI +FdcPeimEntry ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + FDC_BLK_IO_DEV *FdcBlkIoDev; + UINTN DeviceCount; + UINT32 Index; + + Status = PeiServicesRegisterForShadow (FileHandle); + if (!EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate memory for instance of FDC_BLK_IO_DEV and copy initial value + // from template to it. + // + FdcBlkIoDev = AllocatePages (EFI_SIZE_TO_PAGES(sizeof (FDC_BLK_IO_DEV))); + if (FdcBlkIoDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (FdcBlkIoDev, &mBlockIoDevTemplate, sizeof (mBlockIoDevTemplate)); + + // + // Initialize DMA controller to enable all channels. + // + for (Index = 0; Index < sizeof (mRegisterTable) / sizeof (PEI_DMA_TABLE); Index++) { + IoWrite8 (mRegisterTable[Index].Register, mRegisterTable[Index].Value); + } + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_INIT); + + // + // Enumerate FDC devices. + // + DeviceCount = FdcEnumeration (FdcBlkIoDev); + if (DeviceCount == 0) { + return EFI_NOT_FOUND; + } + + FdcBlkIoDev->PpiDescriptor.Ppi = &FdcBlkIoDev->FdcBlkIo; + + return PeiServicesInstallPpi (&FdcBlkIoDev->PpiDescriptor); +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.h new file mode 100644 index 0000000000..6477394efc --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.h @@ -0,0 +1,246 @@ +/** @file +Private include file for IsaFloppyPei PEIM. + +Copyright (c) 2006 - 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 _RECOVERY_FLOPPY_H_ +#define _RECOVERY_FLOPPY_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Fdc.h" + + +// +// Some PC AT Compatible Device definitions +// +// +// 8237 DMA registers +// +#define R_8237_DMA_BASE_CA_CH0 0x00 +#define R_8237_DMA_BASE_CA_CH1 0x02 +#define R_8237_DMA_BASE_CA_CH2 0x04 +#define R_8237_DMA_BASE_CA_CH3 0xd6 +#define R_8237_DMA_BASE_CA_CH5 0xc4 +#define R_8237_DMA_BASE_CA_CH6 0xc8 +#define R_8237_DMA_BASE_CA_CH7 0xcc + +#define R_8237_DMA_BASE_CC_CH0 0x01 +#define R_8237_DMA_BASE_CC_CH1 0x03 +#define R_8237_DMA_BASE_CC_CH2 0x05 +#define R_8237_DMA_BASE_CC_CH3 0xd7 +#define R_8237_DMA_BASE_CC_CH5 0xc6 +#define R_8237_DMA_BASE_CC_CH6 0xca +#define R_8237_DMA_BASE_CC_CH7 0xce + +#define R_8237_DMA_MEM_LP_CH0 0x87 +#define R_8237_DMA_MEM_LP_CH1 0x83 +#define R_8237_DMA_MEM_LP_CH2 0x81 +#define R_8237_DMA_MEM_LP_CH3 0x82 +#define R_8237_DMA_MEM_LP_CH5 0x8B +#define R_8237_DMA_MEM_LP_CH6 0x89 +#define R_8237_DMA_MEM_LP_CH7 0x8A + + +#define R_8237_DMA_COMMAND_CH0_3 0x08 +#define R_8237_DMA_COMMAND_CH4_7 0xd0 +#define B_8237_DMA_COMMAND_GAP 0x10 +#define B_8237_DMA_COMMAND_CGE 0x04 + + +#define R_8237_DMA_STA_CH0_3 0x09 +#define R_8237_DMA_STA_CH4_7 0xd2 + +#define R_8237_DMA_WRSMSK_CH0_3 0x0a +#define R_8237_DMA_WRSMSK_CH4_7 0xd4 +#define B_8237_DMA_WRSMSK_CMS 0x04 + + +#define R_8237_DMA_CHMODE_CH0_3 0x0b +#define R_8237_DMA_CHMODE_CH4_7 0xd6 +#define V_8237_DMA_CHMODE_DEMAND 0x00 +#define V_8237_DMA_CHMODE_SINGLE 0x40 +#define V_8237_DMA_CHMODE_CASCADE 0xc0 +#define B_8237_DMA_CHMODE_DECREMENT 0x20 +#define B_8237_DMA_CHMODE_INCREMENT 0x00 +#define B_8237_DMA_CHMODE_AE 0x10 +#define V_8237_DMA_CHMODE_VERIFY 0 +#define V_8237_DMA_CHMODE_IO2MEM 0x04 +#define V_8237_DMA_CHMODE_MEM2IO 0x08 + +#define R_8237_DMA_CBPR_CH0_3 0x0c +#define R_8237_DMA_CBPR_CH4_7 0xd8 + +#define R_8237_DMA_MCR_CH0_3 0x0d +#define R_8237_DMA_MCR_CH4_7 0xda + +#define R_8237_DMA_CLMSK_CH0_3 0x0e +#define R_8237_DMA_CLMSK_CH4_7 0xdc + +#define R_8237_DMA_WRMSK_CH0_3 0x0f +#define R_8237_DMA_WRMSK_CH4_7 0xde + +/// +/// ISA memory range +/// +#define ISA_MAX_MEMORY_ADDRESS 0x1000000 + +// +// Macro for time delay & interval +// +#define STALL_1_SECOND 1000000 +#define STALL_1_MSECOND 1000 +#define FDC_CHECK_INTERVAL 50 + +#define FDC_SHORT_DELAY 50 +#define FDC_MEDIUM_DELAY 100 +#define FDC_LONG_DELAY 4000 +#define FDC_RESET_DELAY 2000 +#define FDC_RECALIBRATE_DELAY 250000 + +typedef enum { + FdcType360K360K = 0, + FdcType360K1200K, + FdcType1200K1200K, + FdcType720K720K, + FdcType720K1440K, + FdcType1440K1440K, + FdcType720K2880K, + FdcType1440K2880K, + FdcType2880K2880K +} FDC_DISKET_TYPE; + +typedef struct { + UINT8 Register; + UINT8 Value; +} PEI_DMA_TABLE; + +typedef struct { + UINT8 DevPos; + UINT8 Pcn; + BOOLEAN MotorOn; + BOOLEAN NeedRecalibrate; + FDC_DISKET_TYPE Type; + EFI_PEI_BLOCK_IO_MEDIA MediaInfo; +} PEI_FLOPPY_DEVICE_INFO; + +#define FDC_BLK_IO_DEV_SIGNATURE SIGNATURE_32 ('F', 'b', 'i', 'o') + +typedef struct { + UINTN Signature; + EFI_PEI_RECOVERY_BLOCK_IO_PPI FdcBlkIo; + EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; + UINTN DeviceCount; + PEI_FLOPPY_DEVICE_INFO DeviceInfo[2]; +} FDC_BLK_IO_DEV; + +#define PEI_RECOVERY_FDC_FROM_BLKIO_THIS(a) CR (a, FDC_BLK_IO_DEV, FdcBlkIo, FDC_BLK_IO_DEV_SIGNATURE) + +// +// PEI Recovery Block I/O PPI +// + +/** + Get the number of FDC devices. + + This function implements EFI_PEI_RECOVERY_BLOCK_IO_PPI.GetNumberOfBlockDevices. + It get the number of FDC devices in the system. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to this PPI instance. + @param NumberBlockDevices Pointer to the the number of FDC devices for output. + + @retval EFI_SUCCESS Number of FDC devices is retrieved successfully. + @retval EFI_INVALID_PARAMETER Parameter This is NULL. + +**/ +EFI_STATUS +EFIAPI +FdcGetNumberOfBlockDevices ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + OUT UINTN *NumberBlockDevices + ); + +/** + Get the specified media information. + + This function implements EFI_PEI_RECOVERY_BLOCK_IO_PPI.GetBlockDeviceMediaInfo. + It gets the specified media information. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to this PPI instance. + @param DeviceIndex Index of FDC device to get information. + @param MediaInfo Pointer to the media info buffer for output. + + @retval EFI_SUCCESS Number of FDC devices is retrieved successfully. + @retval EFI_INVALID_PARAMETER Parameter This is NULL. + @retval EFI_INVALID_PARAMETER Parameter MediaInfo is NULL. + @retval EFI_INVALID_PARAMETER DeviceIndex is not valid. + @retval EFI_DEVICE_ERROR FDC device does not exist or has errors. + +**/ +EFI_STATUS +EFIAPI +FdcGetBlockDeviceMediaInfo ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo + ); + +/** + Get the requested number of blocks from the specified FDC device. + + This function implements EFI_PEI_RECOVERY_BLOCK_IO_PPI.ReadBlocks. + It reads the requested number of blocks from the specified FDC device. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to this PPI instance. + @param DeviceIndex Index of FDC device to get information. + @param StartLba The start LBA to read from. + @param BufferSize The size of range to read. + @param Buffer Buffer to hold the data read from FDC. + + @retval EFI_SUCCESS Number of FDC devices is retrieved successfully. + @retval EFI_INVALID_PARAMETER Parameter This is NULL. + @retval EFI_INVALID_PARAMETER Parameter Buffer is NULL. + @retval EFI_INVALID_PARAMETER Parameter BufferSize cannot be divided by block size of FDC device. + @retval EFI_NO_MEDIA No media present. + @retval EFI_DEVICE_ERROR FDC device has error. + @retval Others Fail to read blocks. + +**/ +EFI_STATUS +EFIAPI +FdcReadBlocks ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf new file mode 100644 index 0000000000..8d4db34fbe --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf @@ -0,0 +1,73 @@ +## @file +# ISA Floppy PEIM to support recovery boot via floppy disk. +# +# This module detects and supports ISA Floppy drives. If a drive is discovered +# the PEIM will install the BlockIo PPI. This module is only dispatched if it +# is in the Recovery Boot mode. +# +# 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 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 = IsaFloppyPei + MODULE_UNI_FILE = IsaFloppyPei.uni + FILE_GUID = 7F6E0A24-DBFD-43df-9755-0292D7D3DD48 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + + ENTRY_POINT = FdcPeimEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only) +# + +[Sources] + FloppyPeim.c + FloppyPeim.h + Fdc.h + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + IoLib + TimerLib + ReportStatusCodeLib + BaseMemoryLib + PeiServicesLib + PeimEntryPoint + DebugLib + MemoryAllocationLib + PcdLib + +[Ppis] + gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFdcBaseAddress ## CONSUMES + +[Depex] + gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid + +[UserExtensions.TianoCore."ExtraFiles"] + IsaFloppyPeiExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni new file mode 100644 index 0000000000..57f64d6e12 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni new file mode 100644 index 0000000000..cbef982a66 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c new file mode 100644 index 0000000000..97c196037a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c @@ -0,0 +1,182 @@ +/** @file + UEFI Component Name(2) protocol implementation for Isa driver. + +Copyright (c) 2010 - 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 "IsaDriver.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaIoComponentName = { + IsaIoComponentNameGetDriverName, + IsaIoComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaIoComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaIoComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaIoComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaIoDriverNameTable[] = { + { + "eng;en", + L"ISA IO Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +IsaIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mIsaIoDriverNameTable, + DriverName, + (BOOLEAN)(This == &gIsaIoComponentName) + ); +} + +/** + 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 +IsaIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h new file mode 100644 index 0000000000..8e8178773b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h @@ -0,0 +1,148 @@ +/** @file + Header file for implementation of UEFI Component Name(2) protocol. + +Copyright (c) 2010 - 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 _COMPONENT_NAME_H_ +#define _COMPONENT_NAME_H_ + +extern EFI_COMPONENT_NAME_PROTOCOL gIsaIoComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gIsaIoComponentName2; + +/** + 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 +IsaIoComponentNameGetDriverName ( + 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 +IsaIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c new file mode 100644 index 0000000000..8c58b318c6 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c @@ -0,0 +1,326 @@ +/** @file + IsaIo UEFI driver. + + Produce an instance of the ISA I/O Protocol for every SIO controller. + +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 "IsaDriver.h" + +// +// IsaIo Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gIsaIoDriver = { + IsaIoDriverSupported, + IsaIoDriverStart, + IsaIoDriverStop, + 0xa, + NULL, + NULL +}; + +/** + The main entry point for the IsaIo 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 EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. +**/ +EFI_STATUS +EFIAPI +InitializeIsaIo ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gIsaIoDriver, + ImageHandle, + &gIsaIoComponentName, + &gIsaIoComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Tests to see if a controller can be managed by the IsaIo driver. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of the controller to test. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The device is supported by this driver. + @retval EFI_ALREADY_STARTED The device is already being managed by this driver. + @retval EFI_ACCESS_DENIED The device is already being managed by a different driver + or an application that requires exclusive access. + @retval EFI_UNSUPPORTED The device is is not supported by this driver. + +**/ +EFI_STATUS +EFIAPI +IsaIoDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SIO_PROTOCOL *Sio; + EFI_HANDLE PciHandle; + + // + // Try to open EFI DEVICE PATH protocol on the controller + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + // + // Get the PciIo protocol from its parent controller. + // + Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &DevicePath, &PciHandle); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Try to open the Super IO protocol on the controller + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSioProtocolGuid, + (VOID **) &Sio, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiSioProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + return Status; +} + +/** + Start this driver on ControllerHandle. + + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, but the following calling + restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + This parameter is ignored by device drivers, and is optional for bus drivers. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. +**/ +EFI_STATUS +EFIAPI +IsaIoDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE PciHandle; + EFI_SIO_PROTOCOL *Sio; + ACPI_RESOURCE_HEADER_PTR Resources; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + ISA_IO_DEVICE *IsaIoDevice; + + PciIo = NULL; + Sio = NULL; + + // + // Open Device Path Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the PciIo protocol from its parent controller. + // + TempDevicePath = DevicePath; + Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &TempDevicePath, &PciHandle); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol (PciHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo); + ASSERT_EFI_ERROR (Status); + + // + // Open Super IO Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSioProtocolGuid, + (VOID **) &Sio, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + } + + if (EFI_ERROR (Status)) { + // + // Fail due to LocateDevicePath(...) or OpenProtocol(Sio, BY_DRIVER) + // + return Status; + } + + Status = Sio->GetResources (Sio, &Resources); + ASSERT_EFI_ERROR (Status); + + IsaIoDevice = AllocatePool (sizeof (ISA_IO_DEVICE)); + ASSERT (IsaIoDevice != NULL); + + IsaIoDevice->Signature = ISA_IO_DEVICE_SIGNATURE; + IsaIoDevice->PciIo = PciIo; + + // + // Initialize the ISA I/O instance structure + // + InitializeIsaIoInstance (IsaIoDevice, DevicePath, Resources); + + // + // Install the ISA I/O protocol on the Controller handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Stop this driver on ControllerHandle. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +IsaIoDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + EFI_ISA_IO_PROTOCOL *IsaIo; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->CloseProtocol ( + Controller, + &gEfiSioProtocolGuid, + This->DriverBindingHandle, + Controller + ); + FreePool (IsaIoDevice->IsaIo.ResourceList); + FreePool (IsaIoDevice); + } + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h new file mode 100644 index 0000000000..64f710bcec --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h @@ -0,0 +1,263 @@ +/** @file + The header file for ISA driver + +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 _ISA_DRIVER_H_ +#define _ISA_DRIVER_H_ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ComponentName.h" + +// +// 8237 DMA registers +// +#define R_8237_DMA_BASE_CA_CH0 0x00 +#define R_8237_DMA_BASE_CA_CH1 0x02 +#define R_8237_DMA_BASE_CA_CH2 0x04 +#define R_8237_DMA_BASE_CA_CH3 0xd6 +#define R_8237_DMA_BASE_CA_CH5 0xc4 +#define R_8237_DMA_BASE_CA_CH6 0xc8 +#define R_8237_DMA_BASE_CA_CH7 0xcc + +#define R_8237_DMA_BASE_CC_CH0 0x01 +#define R_8237_DMA_BASE_CC_CH1 0x03 +#define R_8237_DMA_BASE_CC_CH2 0x05 +#define R_8237_DMA_BASE_CC_CH3 0xd7 +#define R_8237_DMA_BASE_CC_CH5 0xc6 +#define R_8237_DMA_BASE_CC_CH6 0xca +#define R_8237_DMA_BASE_CC_CH7 0xce + +#define R_8237_DMA_MEM_LP_CH0 0x87 +#define R_8237_DMA_MEM_LP_CH1 0x83 +#define R_8237_DMA_MEM_LP_CH2 0x81 +#define R_8237_DMA_MEM_LP_CH3 0x82 +#define R_8237_DMA_MEM_LP_CH5 0x8B +#define R_8237_DMA_MEM_LP_CH6 0x89 +#define R_8237_DMA_MEM_LP_CH7 0x8A + + +#define R_8237_DMA_COMMAND_CH0_3 0x08 +#define R_8237_DMA_COMMAND_CH4_7 0xd0 +#define B_8237_DMA_COMMAND_GAP 0x10 +#define B_8237_DMA_COMMAND_CGE 0x04 + + +#define R_8237_DMA_STA_CH0_3 0xd8 +#define R_8237_DMA_STA_CH4_7 0xd0 + +#define R_8237_DMA_WRSMSK_CH0_3 0x0a +#define R_8237_DMA_WRSMSK_CH4_7 0xd4 +#define B_8237_DMA_WRSMSK_CMS 0x04 + + +#define R_8237_DMA_CHMODE_CH0_3 0x0b +#define R_8237_DMA_CHMODE_CH4_7 0xd6 +#define V_8237_DMA_CHMODE_DEMAND 0x00 +#define V_8237_DMA_CHMODE_SINGLE 0x40 +#define V_8237_DMA_CHMODE_CASCADE 0xc0 +#define B_8237_DMA_CHMODE_DECREMENT 0x20 +#define B_8237_DMA_CHMODE_INCREMENT 0x00 +#define B_8237_DMA_CHMODE_AE 0x10 +#define V_8237_DMA_CHMODE_VERIFY 0 +#define V_8237_DMA_CHMODE_IO2MEM 0x04 +#define V_8237_DMA_CHMODE_MEM2IO 0x08 + +#define R_8237_DMA_CBPR_CH0_3 0x0c +#define R_8237_DMA_CBPR_CH4_7 0xd8 + +#define R_8237_DMA_MCR_CH0_3 0x0d +#define R_8237_DMA_MCR_CH4_7 0xda + +#define R_8237_DMA_CLMSK_CH0_3 0x0e +#define R_8237_DMA_CLMSK_CH4_7 0xdc + +#define R_8237_DMA_WRMSK_CH0_3 0x0f +#define R_8237_DMA_WRMSK_CH4_7 0xde + +typedef enum { + IsaAccessTypeUnknown, + IsaAccessTypeIo, + IsaAccessTypeMem, + IsaAccessTypeMaxType +} ISA_ACCESS_TYPE; + +typedef struct { + UINT8 Address; + UINT8 Page; + UINT8 Count; +} EFI_ISA_DMA_REGISTERS; + +// +// ISA I/O Device Structure +// +#define ISA_IO_DEVICE_SIGNATURE SIGNATURE_32 ('i', 's', 'a', 'i') + +typedef struct { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_ISA_IO_PROTOCOL IsaIo; + EFI_PCI_IO_PROTOCOL *PciIo; +} ISA_IO_DEVICE; + +#define ISA_IO_DEVICE_FROM_ISA_IO_THIS(a) CR (a, ISA_IO_DEVICE, IsaIo, ISA_IO_DEVICE_SIGNATURE) + +// +// Mapping structure for performing ISA DMA to a buffer above 16 MB +// +typedef struct { + EFI_ISA_IO_PROTOCOL_OPERATION Operation; + UINTN NumberOfBytes; + UINTN NumberOfPages; + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS MappedHostAddress; +} ISA_MAP_INFO; + +// +// EFI Driver Binding Protocol Interface Functions +// + +/** + Tests to see if a controller can be managed by the ISA Driver. + + How the Start() function of a driver is implemented can affect how the Supported() function is implemented. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of the controller to test. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The device is supported by this driver. + @retval EFI_ALREADY_STARTED The device is already being managed by this driver. + @retval EFI_ACCESS_DENIED The device is already being managed by a different driver + or an application that requires exclusive access. + @retval EFI_UNSUPPORTED The device is is not supported by this driver. + +**/ +EFI_STATUS +EFIAPI +IsaIoDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Start this driver on ControllerHandle. + + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, but the following calling + restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + This parameter is ignored by device drivers, and is optional for bus drivers. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. +**/ +EFI_STATUS +EFIAPI +IsaIoDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Stop this driver on ControllerHandle. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +IsaIoDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer OPTIONAL + ); + +// +// Function Prototypes +// + +/** + Initializes an ISA I/O Instance + + @param[in] IsaIoDevice The isa device to be initialized. + @param[in] DevicePath The device path of the isa device. + @param[in] Resources The ACPI resource list. + +**/ +VOID +InitializeIsaIoInstance ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN ACPI_RESOURCE_HEADER_PTR Resources + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c new file mode 100644 index 0000000000..2e4361fc0d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c @@ -0,0 +1,1803 @@ +/** @file + The implementation for EFI_ISA_IO_PROTOCOL. + +Copyright (c) 2010 - 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 "IsaIo.h" + +// +// Module Variables +// +EFI_ISA_IO_PROTOCOL mIsaIoInterface = { + { + IsaIoMemRead, + IsaIoMemWrite + }, + { + IsaIoIoRead, + IsaIoIoWrite + }, + IsaIoCopyMem, + IsaIoMap, + IsaIoUnmap, + IsaIoAllocateBuffer, + IsaIoFreeBuffer, + IsaIoFlush, + NULL, + 0, + NULL +}; + +EFI_ISA_DMA_REGISTERS mDmaRegisters[8] = { + { + 0x00, + 0x87, + 0x01 + }, + { + 0x02, + 0x83, + 0x03 + }, + { + 0x04, + 0x81, + 0x05 + }, + { + 0x06, + 0x82, + 0x07 + }, + { + 0x00, + 0x00, + 0x00 + }, // Channel 4 is invalid + { + 0xC4, + 0x8B, + 0xC6 + }, + { + 0xC8, + 0x89, + 0xCA + }, + { + 0xCC, + 0x8A, + 0xCE + }, +}; + +/** + Verifies access to an ISA device + + @param[in] IsaIoDevice The ISA device to be verified. + @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. + @param[in] Width The width of the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Offset The offset in ISA memory space to start the memory operation. + + @retval EFI_SUCCESS Verify success. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The device ont support the access type. +**/ +EFI_STATUS +IsaIoVerifyAccess ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN ISA_ACCESS_TYPE Type, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT32 Offset + ) +{ + EFI_ISA_ACPI_RESOURCE *Item; + EFI_STATUS Status; + + if ((UINT32)Width >= EfiIsaIoWidthMaximum || + Width == EfiIsaIoWidthReserved || + Width == EfiIsaIoWidthFifoReserved || + Width == EfiIsaIoWidthFillReserved + ) { + return EFI_INVALID_PARAMETER; + } + + // + // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX + // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX + // + if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) { + Count = 1; + } + + Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03); + + Status = EFI_UNSUPPORTED; + Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem; + while (Item->Type != EfiIsaAcpiResourceEndOfList) { + if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) || + (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) { + if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) { + return EFI_SUCCESS; + } + + if (Offset >= Item->StartRange && Offset <= Item->EndRange) { + Status = EFI_INVALID_PARAMETER; + } + } + + Item++; + } + + return Status; +} + +/** + Convert the IO Information in ACPI descriptor to IO ISA Attribute. + + @param[in] Information The IO Information in ACPI descriptor + + @return UINT32 The IO ISA Attribute +**/ +UINT32 +IsaIoAttribute ( + IN UINT8 Information + ) +{ + UINT32 Attribute; + + Attribute = 0; + + switch (Information & EFI_ACPI_IO_DECODE_MASK) { + case EFI_ACPI_IO_DECODE_16_BIT: + Attribute |= EFI_ISA_ACPI_IO_DECODE_16_BITS; + break; + + case EFI_ACPI_IO_DECODE_10_BIT: + Attribute |= EFI_ISA_ACPI_IO_DECODE_10_BITS; + break; + } + + return Attribute; +} + +/** + Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute. + + @param[in] Information The IRQ Information in ACPI descriptor + + @return UINT32 The IRQ ISA Attribute +**/ +UINT32 +IsaIrqAttribute ( + IN UINT8 Information + ) +{ + UINT32 Attribute; + + Attribute = 0; + + if ((Information & EFI_ACPI_IRQ_POLARITY_MASK) == EFI_ACPI_IRQ_HIGH_TRUE) { + if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) { + Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE; + } else { + Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE; + } + } else { + if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) { + Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE; + } else { + Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE; + } + } + return Attribute; +} + +/** + Convert the Memory Information in ACPI descriptor to Memory ISA Attribute. + + @param[in] Information The Memory Information in ACPI descriptor + + @return UINT32 The Memory ISA Attribute +**/ +UINT32 +IsaMemoryAttribute ( + IN UINT8 Information + ) +{ + UINT32 Attribute; + + Attribute = 0; + + switch (Information & EFI_ACPI_MEMORY_WRITE_STATUS_MASK) { + case EFI_ACPI_MEMORY_WRITABLE: + Attribute |= EFI_ISA_ACPI_MEMORY_WRITEABLE; + break; + } + + return Attribute; +} + +/** + Convert the DMA Information in ACPI descriptor to DMA ISA Attribute. + + @param[in] Information The DMA Information in ACPI descriptor + + @return UINT32 The DMA ISA Attribute +**/ +UINT32 +IsaDmaAttribute ( + IN UINT8 Information + ) +{ + UINT32 Attribute; + + Attribute = EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE; + + switch (Information & EFI_ACPI_DMA_SPEED_TYPE_MASK) { + case EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE; + break; + case EFI_ACPI_DMA_SPEED_TYPE_A: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A; + break; + case EFI_ACPI_DMA_SPEED_TYPE_B: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B; + break; + case EFI_ACPI_DMA_SPEED_TYPE_F: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C; + break; + } + + switch (Information & EFI_ACPI_DMA_TRANSFER_TYPE_MASK) { + case EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8; + break; + case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16; + break; + } + + return Attribute; +} + +/** + Convert the ACPI resource descriptor to ISA resource descriptor. + + @param[in] AcpiResource Pointer to the ACPI resource descriptor + @param[out] IsaResource The optional pointer to the buffer to + store the converted ISA resource descriptor + + @return UINTN Number of ISA resource descriptor needed +**/ +UINTN +AcpiResourceToIsaResource ( + IN ACPI_RESOURCE_HEADER_PTR AcpiResource, + OUT EFI_ISA_ACPI_RESOURCE *IsaResource OPTIONAL + ) +{ + UINT32 Index; + UINTN Count; + UINT32 LastIndex; + EFI_ACPI_IO_PORT_DESCRIPTOR *Io; + EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIo; + EFI_ACPI_IRQ_DESCRIPTOR *Irq; + EFI_ACPI_DMA_DESCRIPTOR *Dma; + EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *Memory; + EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *FixedMemory; + + Count = 0; + LastIndex = 0; + + switch (AcpiResource.SmallHeader->Byte) { + case ACPI_DMA_DESCRIPTOR: + Dma = (EFI_ACPI_DMA_DESCRIPTOR *) AcpiResource.SmallHeader; + for (Index = 0; Index < sizeof (Dma->ChannelMask) * 8; Index++) { + if (Dma->ChannelMask & (1 << Index)) { + if ((Count > 0) && (LastIndex + 1 == Index)) { + if (IsaResource != NULL) { + IsaResource[Count - 1].EndRange ++; + } + } else { + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceDma; + IsaResource[Count].Attribute = IsaDmaAttribute (Dma->Information); + IsaResource[Count].StartRange = Index; + IsaResource[Count].EndRange = Index; + } + Count ++; + } + + LastIndex = Index; + } + } + break; + + case ACPI_IO_PORT_DESCRIPTOR: + Io = (EFI_ACPI_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader; + if (Io->Length != 0) { + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceIo; + IsaResource[Count].Attribute = IsaIoAttribute (Io->Information); + IsaResource[Count].StartRange = Io->BaseAddressMin; + IsaResource[Count].EndRange = Io->BaseAddressMin + Io->Length - 1; + } + Count ++; + } + break; + + case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR: + FixedIo = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader; + if (FixedIo->Length != 0) { + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceIo; + IsaResource[Count].Attribute = EFI_ISA_ACPI_IO_DECODE_10_BITS; + IsaResource[Count].StartRange = FixedIo->BaseAddress; + IsaResource[Count].EndRange = FixedIo->BaseAddress + FixedIo->Length - 1; + } + Count ++; + } + break; + + case ACPI_IRQ_DESCRIPTOR: + case ACPI_IRQ_NOFLAG_DESCRIPTOR: + Irq = (EFI_ACPI_IRQ_DESCRIPTOR *) AcpiResource.SmallHeader; + for (Index = 0; Index < sizeof (Irq->Mask) * 8; Index++) { + if (Irq->Mask & (1 << Index)) { + if ((Count > 0) && (LastIndex + 1 == Index)) { + if (IsaResource != NULL) { + IsaResource[Count - 1].EndRange ++; + } + } else { + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceInterrupt; + if (AcpiResource.SmallHeader->Byte == ACPI_IRQ_DESCRIPTOR) { + IsaResource[Count].Attribute = IsaIrqAttribute (Irq->Information); + } else { + IsaResource[Count].Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE; + } + IsaResource[Count].StartRange = Index; + IsaResource[Count].EndRange = Index; + } + Count++; + } + + LastIndex = Index; + } + } + break; + + case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR: + Memory = (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader; + if (Memory->Length != 0) { + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceMemory; + IsaResource[Count].Attribute = IsaMemoryAttribute (Memory->Information); + IsaResource[Count].StartRange = Memory->BaseAddressMin; + IsaResource[Count].EndRange = Memory->BaseAddressMin + Memory->Length - 1; + } + Count ++; + } + break; + + case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR: + FixedMemory = (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader; + if (FixedMemory->Length != 0) { + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceMemory; + IsaResource[Count].Attribute = IsaMemoryAttribute (FixedMemory->Information); + IsaResource[Count].StartRange = FixedMemory->BaseAddress; + IsaResource[Count].EndRange = FixedMemory->BaseAddress + FixedMemory->Length - 1; + } + Count ++; + } + break; + + case ACPI_END_TAG_DESCRIPTOR: + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceEndOfList; + IsaResource[Count].Attribute = 0; + IsaResource[Count].StartRange = 0; + IsaResource[Count].EndRange = 0; + } + Count ++; + break; + } + + return Count; +} + +/** + Initializes an ISA I/O Instance + + @param[in] IsaIoDevice The isa device to be initialized. + @param[in] DevicePath The device path of the isa device. + @param[in] Resources The ACPI resource list. + +**/ +VOID +InitializeIsaIoInstance ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN ACPI_RESOURCE_HEADER_PTR Resources + ) +{ + UINTN Index; + ACPI_HID_DEVICE_PATH *AcpiNode; + ACPI_RESOURCE_HEADER_PTR ResourcePtr; + + // + // Use the ISA IO Protocol structure template to initialize the ISA IO instance + // + CopyMem ( + &IsaIoDevice->IsaIo, + &mIsaIoInterface, + sizeof (EFI_ISA_IO_PROTOCOL) + ); + + // + // Count the resources including the ACPI End Tag + // + ResourcePtr = Resources; + Index = 0; + while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) { + + Index += AcpiResourceToIsaResource (ResourcePtr, NULL); + + if (ResourcePtr.SmallHeader->Bits.Type == 0) { + ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader + + ResourcePtr.SmallHeader->Bits.Length + + sizeof (*ResourcePtr.SmallHeader)); + } else { + ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader + + ResourcePtr.LargeHeader->Length + + sizeof (*ResourcePtr.LargeHeader)); + } + + } + // + // Get the Isa Resource count for ACPI End Tag + // + Index += AcpiResourceToIsaResource (ResourcePtr, NULL); + + // + // Initialize the ResourceList + // + IsaIoDevice->IsaIo.ResourceList = AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST) + Index * sizeof (EFI_ISA_ACPI_RESOURCE)); + ASSERT (IsaIoDevice->IsaIo.ResourceList != NULL); + IsaIoDevice->IsaIo.ResourceList->ResourceItem = (EFI_ISA_ACPI_RESOURCE *) (IsaIoDevice->IsaIo.ResourceList + 1); + + AcpiNode = (ACPI_HID_DEVICE_PATH *) ((UINT8 *) DevicePath + GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH - sizeof (ACPI_HID_DEVICE_PATH)); + IsaIoDevice->IsaIo.ResourceList->Device.HID = AcpiNode->HID; + IsaIoDevice->IsaIo.ResourceList->Device.UID = AcpiNode->UID; + + ResourcePtr = Resources; + Index = 0; + while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) { + + Index += AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]); + + if (ResourcePtr.SmallHeader->Bits.Type == 0) { + ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader + + ResourcePtr.SmallHeader->Bits.Length + + sizeof (*ResourcePtr.SmallHeader)); + } else { + ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader + + ResourcePtr.LargeHeader->Length + + sizeof (*ResourcePtr.LargeHeader)); + } + } + + // + // Convert the ACPI End Tag + // + AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]); +} + +/** + Performs an ISA I/O Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeIo, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Io.Read ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Performs an ISA I/O Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was writen to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeIo, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Io.Write ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Writes an 8-bit I/O Port + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Offset The offset in ISA IO space to start the IO operation. + @param[in] Value The data to write port. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WritePort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + Status = IsaIoDevice->PciIo->Io.Write ( + IsaIoDevice->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + 1, + &Value + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + return Status; + } + + // + // Wait for 50 microseconds to take affect. + // + gBS->Stall (50); + + return EFI_SUCCESS; +} + +/** + Writes I/O operation base address and count number to a 8 bit I/O Port. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] AddrOffset The address' offset. + @param[in] PageOffset The page's offest. + @param[in] CountOffset The count's offset. + @param[in] BaseAddress The base address. + @param[in] Count The number of I/O operations to perform. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WriteDmaPort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 AddrOffset, + IN UINT32 PageOffset, + IN UINT32 CountOffset, + IN UINT32 BaseAddress, + IN UINT16 Count + ) +{ + EFI_STATUS Status; + + Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff)); + return Status; +} + +/** + Unmaps a memory region for DMA + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +EFI_STATUS +EFIAPI +IsaIoUnmap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + ISA_MAP_INFO *IsaMapInfo; + + // + // Check if DMA is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { + return EFI_UNSUPPORTED; + } + + // + // See if the Map() operation associated with this Unmap() required a mapping + // buffer.If a mapping buffer was not required, then this function simply + // returns EFI_SUCCESS. + // + if (Mapping != NULL) { + // + // Get the MAP_INFO structure from Mapping + // + IsaMapInfo = (ISA_MAP_INFO *) Mapping; + + // + // If this is a write operation from the Agent's point of view, + // then copy the contents of the mapped buffer into the real buffer + // so the processor can read the contents of the real buffer. + // + if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->HostAddress, + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // Free the mapped buffer and the MAP_INFO structure. + // + gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages); + FreePool (IsaMapInfo); + } + + return EFI_SUCCESS; +} + +/** + Flushes any posted write data to the system memory. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. +**/ +EFI_STATUS +EFIAPI +IsaIoFlush ( + IN EFI_ISA_IO_PROTOCOL *This + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Performs an ISA Memory Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device successfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify the Isa Io Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Mem.Read ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Performs an ISA Memory Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was written to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Mem.Write ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory copy operation. + @param[in] DestOffset The offset of the destination + @param[in] SrcOffset The offset of the source + @param[in] Count The number of memory copy operations to perform + + @retval EFI_SUCCESS The data was copied sucessfully. + @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoCopyMem ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access for destination and source + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + DestOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + SrcOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->CopyMem ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + DestOffset, + EFI_PCI_IO_PASS_THROUGH_BAR, + SrcOffset, + Count + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Maps a memory region for DMA, note this implementation + only supports slave read/write operation to save code size. + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +IsaIoMapOnlySupportSlaveReadWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + ISA_MAP_INFO *IsaMapInfo; + UINT8 DmaMode; + UINTN MaxNumberOfBytes; + UINT32 BaseAddress; + UINT16 Count; + UINT8 DmaMask; + UINT8 DmaClear; + UINT8 DmaChannelMode; + + if ((NULL == This) || + (NULL == HostAddress) || + (NULL == NumberOfBytes) || + (NULL == DeviceAddress) || + (NULL == Mapping) + ) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure the Operation parameter is valid. + // Light IsaIo only supports two operations. + // + if (!(Operation == EfiIsaIoOperationSlaveRead || + Operation == EfiIsaIoOperationSlaveWrite)) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber >= 4) { + // + // The Light IsaIo doesn't support channelNumber larger than 4. + // + return EFI_INVALID_PARAMETER; + } + + // + // Map the HostAddress to a DeviceAddress. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + if ((PhysicalAddress + *NumberOfBytes) > BASE_16MB) { + // + // Common Buffer operations can not be remapped. If the common buffer + // is above 16MB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + // + // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() + // is called later. + // + IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); + if (IsaMapInfo == NULL) { + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = IsaMapInfo; + + // + // Initialize the MAP_INFO structure + // + IsaMapInfo->Operation = Operation; + IsaMapInfo->NumberOfBytes = *NumberOfBytes; + IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + IsaMapInfo->HostAddress = PhysicalAddress; + IsaMapInfo->MappedHostAddress = BASE_16MB - 1; + + // + // Allocate a buffer below 16MB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + IsaMapInfo->NumberOfPages, + &IsaMapInfo->MappedHostAddress + ); + if (EFI_ERROR (Status)) { + FreePool (IsaMapInfo); + *NumberOfBytes = 0; + *Mapping = NULL; + return Status; + } + // + // If this is a read operation from the DMA agents's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the DMA agent can read the contents of the real buffer. + // + if (Operation == EfiIsaIoOperationSlaveRead) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + (VOID *) (UINTN) IsaMapInfo->HostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // The DeviceAddress is the address of the maped buffer below 16 MB + // + *DeviceAddress = IsaMapInfo->MappedHostAddress; + } else { + // + // The transfer is below 16 MB, so the DeviceAddress is simply the + // HostAddress + // + *DeviceAddress = PhysicalAddress; + } + + // + // Figure out what to program into the DMA Channel Mode Register + // + DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); + if (Operation == EfiIsaIoOperationSlaveRead) { + DmaMode |= V_8237_DMA_CHMODE_MEM2IO; + } else { + DmaMode |= V_8237_DMA_CHMODE_IO2MEM; + } + // + // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo + // + DmaMode |= V_8237_DMA_CHMODE_SINGLE; + + // + // A Slave DMA transfer can not cross a 64K boundary. + // Compute *NumberOfBytes based on this restriction. + // + MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); + if (*NumberOfBytes > MaxNumberOfBytes) { + *NumberOfBytes = MaxNumberOfBytes; + } + // + // Compute the values to program into the BaseAddress and Count registers + // of the Slave DMA controller + // + BaseAddress = (UINT32) (*DeviceAddress); + Count = (UINT16) (*NumberOfBytes - 1); + // + // Program the DMA Write Single Mask Register for ChannelNumber + // Clear the DMA Byte Pointer Register + // + DmaMask = R_8237_DMA_WRSMSK_CH0_3; + DmaClear = R_8237_DMA_CBPR_CH0_3; + DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; + + Status = WritePort ( + This, + DmaMask, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaClear, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, DmaChannelMode, DmaMode); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteDmaPort ( + This, + mDmaRegisters[ChannelNumber].Address, + mDmaRegisters[ChannelNumber].Page, + mDmaRegisters[ChannelNumber].Count, + BaseAddress, + Count + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (ChannelNumber & 0x03) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Maps a memory region for DMA. This implementation implement the + the full mapping support. + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. +**/ +EFI_STATUS +IsaIoMapFullSupport ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + BOOLEAN Master; + BOOLEAN Read; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + ISA_MAP_INFO *IsaMapInfo; + UINT8 DmaMode; + UINTN MaxNumberOfBytes; + UINT32 BaseAddress; + UINT16 Count; + UINT8 DmaMask; + UINT8 DmaClear; + UINT8 DmaChannelMode; + + if ((NULL == This) || + (NULL == HostAddress) || + (NULL == NumberOfBytes) || + (NULL == DeviceAddress) || + (NULL == Mapping) + ) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure the Operation parameter is valid + // + if ((UINT32)Operation >= EfiIsaIoOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber >= 8) { + return EFI_INVALID_PARAMETER; + } + + // + // See if this is a Slave DMA Operation + // + Master = TRUE; + Read = FALSE; + if (Operation == EfiIsaIoOperationSlaveRead) { + Operation = EfiIsaIoOperationBusMasterRead; + Master = FALSE; + Read = TRUE; + } + + if (Operation == EfiIsaIoOperationSlaveWrite) { + Operation = EfiIsaIoOperationBusMasterWrite; + Master = FALSE; + Read = FALSE; + } + + if (!Master) { + // + // Make sure that ChannelNumber is a valid channel number + // Channel 4 is used to cascade, so it is illegal. + // + if (ChannelNumber == 4 || ChannelNumber > 7) { + return EFI_INVALID_PARAMETER; + } + // + // This implementation only support COMPATIBLE DMA Transfers + // + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((ChannelAttributes & + (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A | + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B | + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber < 4) { + // + // If this is Channel 0..3, then the width must be 8 bit + // + if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) || + ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0) + ) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // If this is Channel 4..7, then the width must be 16 bit + // + if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) || + ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) { + return EFI_INVALID_PARAMETER; + } + } + // + // Either Demand Mode or Single Mode must be selected, but not both + // + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { + return EFI_INVALID_PARAMETER; + } + } else { + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) { + return EFI_INVALID_PARAMETER; + } + } + } + // + // Map the HostAddress to a DeviceAddress. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + if ((PhysicalAddress +*NumberOfBytes) > BASE_16MB) { + // + // Common Buffer operations can not be remapped. If the common buffer + // is above 16MB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + // + // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() + // is called later. + // + IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); + if (IsaMapInfo == NULL) { + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = IsaMapInfo; + + // + // Initialize the MAP_INFO structure + // + IsaMapInfo->Operation = Operation; + IsaMapInfo->NumberOfBytes = *NumberOfBytes; + IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + IsaMapInfo->HostAddress = PhysicalAddress; + IsaMapInfo->MappedHostAddress = BASE_16MB - 1; + + // + // Allocate a buffer below 16MB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + IsaMapInfo->NumberOfPages, + &IsaMapInfo->MappedHostAddress + ); + if (EFI_ERROR (Status)) { + FreePool (IsaMapInfo); + *NumberOfBytes = 0; + *Mapping = NULL; + return Status; + } + // + // If this is a read operation from the DMA agents's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the DMA agent can read the contents of the real buffer. + // + if (Operation == EfiIsaIoOperationBusMasterRead) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + (VOID *) (UINTN) IsaMapInfo->HostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // The DeviceAddress is the address of the maped buffer below 16 MB + // + *DeviceAddress = IsaMapInfo->MappedHostAddress; + } else { + // + // The transfer is below 16 MB, so the DeviceAddress is simply the + // HostAddress + // + *DeviceAddress = PhysicalAddress; + } + // + // If this is a Bus Master operation then return + // + if (Master) { + return EFI_SUCCESS; + } + // + // Figure out what to program into the DMA Channel Mode Register + // + DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); + if (Read) { + DmaMode |= V_8237_DMA_CHMODE_MEM2IO; + } else { + DmaMode |= V_8237_DMA_CHMODE_IO2MEM; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) { + DmaMode |= B_8237_DMA_CHMODE_AE; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { + DmaMode |= V_8237_DMA_CHMODE_DEMAND; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { + DmaMode |= V_8237_DMA_CHMODE_SINGLE; + } + // + // A Slave DMA transfer can not cross a 64K boundary. + // Compute *NumberOfBytes based on this restriction. + // + MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); + if (*NumberOfBytes > MaxNumberOfBytes) { + *NumberOfBytes = MaxNumberOfBytes; + } + // + // Compute the values to program into the BaseAddress and Count registers + // of the Slave DMA controller + // + if (ChannelNumber < 4) { + BaseAddress = (UINT32) (*DeviceAddress); + Count = (UINT16) (*NumberOfBytes - 1); + } else { + BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1)); + Count = (UINT16) ((*NumberOfBytes - 1) >> 1); + } + // + // Program the DMA Write Single Mask Register for ChannelNumber + // Clear the DMA Byte Pointer Register + // + if (ChannelNumber < 4) { + DmaMask = R_8237_DMA_WRSMSK_CH0_3; + DmaClear = R_8237_DMA_CBPR_CH0_3; + DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; + } else { + DmaMask = R_8237_DMA_WRSMSK_CH4_7; + DmaClear = R_8237_DMA_CBPR_CH4_7; + DmaChannelMode = R_8237_DMA_CHMODE_CH4_7; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaClear, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, DmaChannelMode, DmaMode); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteDmaPort ( + This, + mDmaRegisters[ChannelNumber].Address, + mDmaRegisters[ChannelNumber].Page, + mDmaRegisters[ChannelNumber].Count, + BaseAddress, + Count + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (ChannelNumber & 0x03) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Maps a memory region for DMA + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoMap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + // + // Check if DMA is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { + return EFI_UNSUPPORTED; + } + // + // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for + // ISA Bus Master. + // + // So we just return EFI_UNSUPPORTED for these functions. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) { + return IsaIoMapOnlySupportSlaveReadWrite ( + This, + Operation, + ChannelNumber, + ChannelAttributes, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + + } else { + return IsaIoMapFullSupport ( + This, + Operation, + ChannelNumber, + ChannelAttributes, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + } +} + +/** + Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Type The type allocation to perform. + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base address of the allocated range. + @param[in] Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL + @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified + by HostAddress, Pages, and Type is not available for common buffer use. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoAllocateBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + // + // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for + // ISA Bus Master. + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || + ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { + return EFI_UNSUPPORTED; + } + + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32)Type >= MaxAllocateType) { + return EFI_INVALID_PARAMETER; + } + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + // + if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { + return EFI_INVALID_PARAMETER; + } + + if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) { + return EFI_UNSUPPORTED; + } + + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (BASE_16MB - 1); + if (Type == AllocateAddress) { + if ((UINTN) (*HostAddress) >= BASE_16MB) { + return EFI_UNSUPPORTED; + } else { + PhysicalAddress = (UINTN) (*HostAddress); + } + } + + if (Type == AllocateAnyPages) { + Type = AllocateMaxAddress; + } + + Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + return Status; + } + + *HostAddress = (VOID *) (UINTN) PhysicalAddress; + return Status; +} + +/** + Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Pages The number of pages to free. + @param[in] HostAddress The base address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). +**/ +EFI_STATUS +EFIAPI +IsaIoFreeBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + EFI_STATUS Status; + + // + // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for + // ISA Bus Master. + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || + ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { + return EFI_UNSUPPORTED; + } + + Status = gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, + Pages + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h new file mode 100644 index 0000000000..cc4a1f8b80 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h @@ -0,0 +1,331 @@ +/** @file + The header file for EFI_ISA_IO protocol implementation. + +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 _ISA_IO_H_ +#define _ISA_IO_H_ + +#include "IsaDriver.h" + +// +// Bits definition of PcdIsaBusSupportedFeatures +// +#define PCD_ISA_BUS_SUPPORT_DMA BIT0 +#define PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA BIT1 +#define PCD_ISA_BUS_SUPPORT_ISA_MEMORY BIT2 + +// +// ISA I/O Support Function Prototypes +// + +/** + Verifies access to an ISA device + + @param[in] IsaIoDevice The ISA device to be verified. + @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. + @param[in] Width The width of the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Offset The offset in ISA memory space to start the memory operation. + + @retval EFI_SUCCESS Verify success. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The device ont support the access type. +**/ +EFI_STATUS +IsaIoVerifyAccess ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN ISA_ACCESS_TYPE Type, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT32 Offset + ); + +/** + Performs an ISA I/O Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Performs an ISA I/O Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was writen to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Maps a memory region for DMA + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoMap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Unmaps a memory region for DMA + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +EFI_STATUS +EFIAPI +IsaIoUnmap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Flushes any posted write data to the system memory. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. +**/ +EFI_STATUS +EFIAPI +IsaIoFlush ( + IN EFI_ISA_IO_PROTOCOL *This + ); + +/** + Writes I/O operation base address and count number to a 8 bit I/O Port. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] AddrOffset The address' offset. + @param[in] PageOffset The page's offest. + @param[in] CountOffset The count's offset. + @param[in] BaseAddress The base address. + @param[in] Count The number of I/O operations to perform. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WriteDmaPort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 AddrOffset, + IN UINT32 PageOffset, + IN UINT32 CountOffset, + IN UINT32 BaseAddress, + IN UINT16 Count + ); + +/** + Writes an 8-bit I/O Port + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Offset The offset in ISA IO space to start the IO operation. + @param[in] Value The data to write port. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WritePort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 Value + ); + +/** + Performs an ISA Memory Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device successfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ); + + +/** + Performs an ISA Memory Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was written to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory copy operation. + @param[in] DestOffset The offset of the destination + @param[in] SrcOffset The offset of the source + @param[in] Count The number of memory copy operations to perform + + @retval EFI_SUCCESS The data was copied sucessfully. + @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoCopyMem ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ); + +/** + Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Type The type allocation to perform. + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base address of the allocated range. + @param[in] Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL + @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified + by HostAddress, Pages, and Type is not available for common buffer use. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoAllocateBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Pages The number of pages to free. + @param[in] HostAddress The base address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). +**/ +EFI_STATUS +EFIAPI +IsaIoFreeBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf new file mode 100644 index 0000000000..499cf434f5 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf @@ -0,0 +1,71 @@ +## @file +# Produces an instance of the ISA I/O Protocol for every SIO controller. +# +# Produces an instance of the ISA I/O Protocol for every SIO controller. The ISA +# I/O protocols are installed based off of the information provided by each +# instance of the SIO Protocol found. +# +# 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 +# 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 = IsaIoDxe + MODULE_UNI_FILE = IsaIoDxe.uni + FILE_GUID = 61AD3083-DCAD-4850-A50C-73B23B3B14F9 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeIsaIo + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# DRIVER_BINDING = gIsaIoDriver +# COMPONENT_NAME = gIsaIoComponentName; +# COMPONENT_NAME2 = gIsaIoComponentName2; +# + +[Sources] + ComponentName.h + ComponentName.c + IsaIo.h + IsaIo.c + IsaDriver.h + IsaDriver.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PcdLib + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + DevicePathLib + UefiLib + UefiDriverEntryPoint + DebugLib + +[Protocols] + gEfiIsaIoProtocolGuid ## BY_START + gEfiSioProtocolGuid ## TO_START + gEfiPciIoProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## TO_START + gEfiGenericMemTestProtocolGuid ## TO_START + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures ## CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + IsaIoDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.uni new file mode 100644 index 0000000000..9cfecb2395 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni new file mode 100644 index 0000000000..6b6dc83e89 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/ComponentName.c new file mode 100644 index 0000000000..ef24008f6b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/ComponentName.c @@ -0,0 +1,272 @@ +/** @file + UEFI Component Name and Name2 protocol for Isa serial driver. + +Copyright (c) 2006 - 2015, Intel 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 "Serial.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaSerialComponentName = { + IsaSerialComponentNameGetDriverName, + IsaSerialComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaSerialComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaSerialComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaSerialComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaSerialDriverNameTable[] = { + { + "eng;en", + L"ISA Serial Driver" + }, + { + NULL, + NULL + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 mSerialPortName[] = L"ISA Serial Port # "; + +/** + 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 +IsaSerialComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mIsaSerialDriverNameTable, + DriverName, + (BOOLEAN)(This == &gIsaSerialComponentName) + ); +} + +/** + 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 +IsaSerialComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + SERIAL_DEV *SerialDevice; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + // + // Make sure this driver is currently managing ControllerHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gSerialControllerDriver.DriverBindingHandle, + &gEfiIsaIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ControllerNameTable = NULL; + if (ChildHandle != NULL) { + Status = EfiTestChildHandle ( + ControllerHandle, + ChildHandle, + &gEfiIsaIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the Serial I/O Protocol from the child handle + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + gSerialControllerDriver.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the Serial Controller's Device structure + // + SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo); + ControllerNameTable = SerialDevice->ControllerNameTable; + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gIsaSerialComponentName) + ); +} + +/** + Add the ISO639-2 and RFC4646 component name both for the Serial IO device + + @param SerialDevice A pointer to the SERIAL_DEV instance. + + @param IsaIo A pointer to the EFI_ISA_IO_PROTOCOL instance. + +**/ +VOID +AddName ( + IN SERIAL_DEV *SerialDevice, + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + mSerialPortName[(sizeof (mSerialPortName) / 2) - 2] = (CHAR16) (L'0' + (UINT8) IsaIo->ResourceList->Device.UID); + AddUnicodeString2 ( + "eng", + gIsaSerialComponentName.SupportedLanguages, + &SerialDevice->ControllerNameTable, + mSerialPortName, + TRUE + ); + AddUnicodeString2 ( + "en", + gIsaSerialComponentName2.SupportedLanguages, + &SerialDevice->ControllerNameTable, + mSerialPortName, + FALSE + ); + +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf new file mode 100644 index 0000000000..4abaac9ff8 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf @@ -0,0 +1,80 @@ +## @file +# Serial driver for standard UARTS on an ISA bus. +# +# Produces the Serial I/O protocol for standard UARTS using ISA I/O. This driver +# supports the 8250, 16450, 16550 and 16550A UART types. +# +# Copyright (c) 2007 - 2015, Intel 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 = IsaSerialDxe + MODULE_UNI_FILE = IsaSerialDxe.uni + FILE_GUID = 93B80003-9FB3-11d4-9A3A-0090273FC14D + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeIsaSerial + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gSerialControllerDriver +# COMPONENT_NAME = gIsaSerialComponentName +# COMPONENT_NAME2 = gIsaSerialComponentName2 +# + +[Sources] + ComponentName.c + Serial.h + Serial.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + PcdLib + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + DevicePathLib + UefiLib + UefiDriverEntryPoint + DebugLib + +[Guids] + gEfiUartDevicePathGuid ## SOMETIMES_CONSUMES ## GUID + +[Protocols] + gEfiIsaIoProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## TO_START + gEfiSerialIoProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## BY_START + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE ## CONSUMES + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8 ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1 ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1 ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|1843200 ## CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + IsaSerialDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni new file mode 100644 index 0000000000..6b99f490e5 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni new file mode 100644 index 0000000000..47bc80b42b Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c new file mode 100644 index 0000000000..57ee669d14 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c @@ -0,0 +1,2038 @@ +/** @file + Serial driver for standard UARTS on an ISA bus. + +Copyright (c) 2006 - 2015, Intel 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 "Serial.h" + +// +// ISA Serial Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = { + SerialControllerDriverSupported, + SerialControllerDriverStart, + SerialControllerDriverStop, + 0xa, + NULL, + NULL +}; + + +SERIAL_DEV gSerialDevTempate = { + SERIAL_DEV_SIGNATURE, + NULL, + { // SerialIo + SERIAL_IO_INTERFACE_REVISION, + IsaSerialReset, + IsaSerialSetAttributes, + IsaSerialSetControl, + IsaSerialGetControl, + IsaSerialWrite, + IsaSerialRead, + NULL + }, + { // SerialMode + SERIAL_PORT_SUPPORT_CONTROL_MASK, + SERIAL_PORT_DEFAULT_TIMEOUT, + 0, + SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH, + 0, + 0, + 0 + }, + NULL, + NULL, + { // UartDevicePath + { + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + { + (UINT8) (sizeof (UART_DEVICE_PATH)), + (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) + } + }, + 0, + 0, + 0, + 0, + 0 + }, + NULL, + 0, //BaseAddress + { + 0, + 0, + SERIAL_MAX_BUFFER_SIZE, + { 0 } + }, + { + 0, + 0, + SERIAL_MAX_BUFFER_SIZE, + { 0 } + }, + FALSE, + FALSE, + Uart16550A, + NULL +}; + +/** + Check the device path node whether it's the Flow Control node or not. + + @param[in] FlowControl The device path node to be checked. + + @retval TRUE It's the Flow Control node. + @retval FALSE It's not. + +**/ +BOOLEAN +IsUartFlowControlNode ( + IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl + ) +{ + return (BOOLEAN) ( + (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) && + (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid)) + ); +} + +/** + Check the device path node whether it contains Flow Control node or not. + + @param[in] DevicePath The device path to be checked. + + @retval TRUE It contains the Flow Control node. + @retval FALSE It doesn't. + +**/ +BOOLEAN +ContainsFlowControl ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + while (!IsDevicePathEnd (DevicePath)) { + if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) { + return TRUE; + } + DevicePath = NextDevicePathNode (DevicePath); + } + + return FALSE; +} + +/** + The user Entry Point for module IsaSerial. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeIsaSerial ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gSerialControllerDriver, + ImageHandle, + &gIsaSerialComponentName, + &gIsaSerialComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + // + // Initialize UART default setting in gSerialDevTempate + // + gSerialDevTempate.SerialMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); + gSerialDevTempate.SerialMode.DataBits = PcdGet8 (PcdUartDefaultDataBits); + gSerialDevTempate.SerialMode.Parity = PcdGet8 (PcdUartDefaultParity); + gSerialDevTempate.SerialMode.StopBits = PcdGet8 (PcdUartDefaultStopBits); + gSerialDevTempate.UartDevicePath.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); + gSerialDevTempate.UartDevicePath.DataBits = PcdGet8 (PcdUartDefaultDataBits); + gSerialDevTempate.UartDevicePath.Parity = PcdGet8 (PcdUartDefaultParity); + gSerialDevTempate.UartDevicePath.StopBits = PcdGet8 (PcdUartDefaultStopBits); + + return Status; +} + +/** + Check to see if this driver supports the given controller + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @return EFI_SUCCESS This driver can support the given controller + +**/ +EFI_STATUS +EFIAPI +SerialControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) + +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_ISA_IO_PROTOCOL *IsaIo; + UART_DEVICE_PATH *UartNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; + BOOLEAN HasFlowControl; + + // + // Check RemainingDevicePath validation + // + if (RemainingDevicePath != NULL) { + // + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, go on checking other conditions + // + if (!IsDevicePathEnd (RemainingDevicePath)) { + // + // If RemainingDevicePath isn't the End of Device Path Node, + // check its validation + // + Status = EFI_UNSUPPORTED; + + UartNode = (UART_DEVICE_PATH *) RemainingDevicePath; + if (UartNode->Header.Type != MESSAGING_DEVICE_PATH || + UartNode->Header.SubType != MSG_UART_DP || + sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UartNode) + ) { + goto Error; + } + + if (UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) { + goto Error; + } + + if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) { + goto Error; + } + + if (UartNode->DataBits < 5 || UartNode->DataBits > 8) { + goto Error; + } + + if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) { + goto Error; + } + + if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) { + goto Error; + } + + if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) { + goto Error; + } + + FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode); + if (IsUartFlowControlNode (FlowControlNode)) { + // + // If the second node is Flow Control Node, + // return error when it request other than hardware flow control. + // + if ((ReadUnaligned32 (&FlowControlNode->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) { + goto Error; + } + } + } + } + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) { + // + // If RemainingDevicePath is NULL or is the End of Device Path Node + // + return EFI_SUCCESS; + } + // + // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node, + // return unsupported, and vice versa. + // + Status = gBS->OpenProtocolInformation ( + Controller, + &gEfiIsaIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + Status = gBS->OpenProtocol ( + OpenInfoBuffer[Index].ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + HasFlowControl = ContainsFlowControl (RemainingDevicePath); + if (HasFlowControl ^ ContainsFlowControl (DevicePath)) { + Status = EFI_UNSUPPORTED; + } + } + break; + } + } + FreePool (OpenInfoBuffer); + return Status; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Open the EFI Device Path protocol needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Use the ISA I/O Protocol to see if Controller is standard ISA UART that + // can be managed by this driver. + // + Status = EFI_SUCCESS; + if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x501)) { + Status = EFI_UNSUPPORTED; + goto Error; + } + +Error: + // + // Close protocol, don't use device path protocol in the Support() function + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Start to management the controller passed in + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @return EFI_SUCCESS Driver is started successfully + +**/ +EFI_STATUS +EFIAPI +SerialControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) + +{ + EFI_STATUS Status; + EFI_ISA_IO_PROTOCOL *IsaIo; + SERIAL_DEV *SerialDevice; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + UART_DEVICE_PATH *Uart; + UINT32 FlowControlMap; + UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + UINT32 Control; + + SerialDevice = NULL; + // + // Get the Parent Device Path + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + // + // Report status code enable the serial + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT, + ParentDevicePath + ); + + // + // Grab the IO abstraction we need to get any work done + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + goto Error; + } + + if (Status == EFI_ALREADY_STARTED) { + + if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) { + // + // If RemainingDevicePath is NULL or is the End of Device Path Node + // + return EFI_SUCCESS; + } + + // + // Make sure a child handle does not already exist. This driver can only + // produce one child per serial port. + // + Status = gBS->OpenProtocolInformation ( + Controller, + &gEfiIsaIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = EFI_ALREADY_STARTED; + for (Index = 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + Status = gBS->OpenProtocol ( + OpenInfoBuffer[Index].ControllerHandle, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Uart = (UART_DEVICE_PATH *) RemainingDevicePath; + Status = SerialIo->SetAttributes ( + SerialIo, + Uart->BaudRate, + SerialIo->Mode->ReceiveFifoDepth, + SerialIo->Mode->Timeout, + (EFI_PARITY_TYPE) Uart->Parity, + Uart->DataBits, + (EFI_STOP_BITS_TYPE) Uart->StopBits + ); + + FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); + if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) { + Status = SerialIo->GetControl (SerialIo, &Control); + if (!EFI_ERROR (Status)) { + if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) { + Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } else { + Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } + // + // Clear the bits that are not allowed to pass to SetControl + // + Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | + EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE); + Status = SerialIo->SetControl (SerialIo, Control); + } + } + } + break; + } + } + + FreePool (OpenInfoBuffer); + return Status; + } + + if (RemainingDevicePath != NULL) { + if (IsDevicePathEnd (RemainingDevicePath)) { + // + // If RemainingDevicePath is the End of Device Path Node, + // skip enumerate any device and return EFI_SUCESSS + // + return EFI_SUCCESS; + } + } + + // + // Initialize the serial device instance + // + SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTempate); + if (SerialDevice == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode); + SerialDevice->IsaIo = IsaIo; + SerialDevice->ParentDevicePath = ParentDevicePath; + FlowControl = NULL; + FlowControlMap = 0; + + // + // Check if RemainingDevicePath is NULL, + // if yes, use the values from the gSerialDevTempate as no remaining device path was + // passed in. + // + if (RemainingDevicePath != NULL) { + // + // If RemainingDevicePath isn't NULL, + // match the configuration of the RemainingDevicePath. IsHandleSupported() + // already checked to make sure the RemainingDevicePath contains settings + // that we can support. + // + CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); + FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath); + if (IsUartFlowControlNode (FlowControl)) { + FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap); + } else { + FlowControl = NULL; + } + } + + AddName (SerialDevice, IsaIo); + + for (Index = 0; SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) { + if (SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) { + SerialDevice->BaseAddress = (UINT16) SerialDevice->IsaIo->ResourceList->ResourceItem[Index].StartRange; + } + } + + SerialDevice->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE); + + // + // Report status code the serial present + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT, + ParentDevicePath + ); + + if (!IsaSerialPortPresent (SerialDevice)) { + Status = EFI_DEVICE_ERROR; + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE, + EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT, + ParentDevicePath + ); + goto Error; + } + + // + // Build the device path by appending the UART node to the ParentDevicePath. + // The Uart setings are zero here, since SetAttribute() will update them to match + // the default setings. + // + SerialDevice->DevicePath = AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath + ); + // + // Only produce the Flow Control node when remaining device path has it + // + if (FlowControl != NULL) { + TempDevicePath = SerialDevice->DevicePath; + if (TempDevicePath != NULL) { + SerialDevice->DevicePath = AppendDevicePathNode ( + TempDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) FlowControl + ); + FreePool (TempDevicePath); + } + } + if (SerialDevice->DevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + // + // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. + // + SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate; + SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits; + SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity; + SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits; + + // + // Issue a reset to initialize the COM port + // + Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE, + EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT, + ParentDevicePath + ); + goto Error; + } + // + // Install protocol interfaces for the serial device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &SerialDevice->Handle, + &gEfiDevicePathProtocolGuid, + SerialDevice->DevicePath, + &gEfiSerialIoProtocolGuid, + &SerialDevice->SerialIo, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // Open For Child Device + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + SerialDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + +Error: + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (SerialDevice != NULL) { + if (SerialDevice->DevicePath != NULL) { + gBS->FreePool (SerialDevice->DevicePath); + } + + FreeUnicodeStringTable (SerialDevice->ControllerNameTable); + gBS->FreePool (SerialDevice); + } + } + + return Status; +} + +/** + Disconnect this driver with the controller, uninstall related protocol instance + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param NumberOfChildren Number of child device. + @param ChildHandleBuffer A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS Operation successfully + @retval EFI_DEVICE_ERROR Cannot stop the driver successfully + +**/ +EFI_STATUS +EFIAPI +SerialControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) + +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + SERIAL_DEV *SerialDevice; + EFI_ISA_IO_PROTOCOL *IsaIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + + // + // Report the status code disable the serial + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT, + DevicePath + ); + + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + SerialDevice->DevicePath, + &gEfiSerialIoProtocolGuid, + &SerialDevice->SerialIo, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + if (SerialDevice->DevicePath != NULL) { + gBS->FreePool (SerialDevice->DevicePath); + } + + FreeUnicodeStringTable (SerialDevice->ControllerNameTable); + gBS->FreePool (SerialDevice); + } + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Detect whether specific FIFO is full or not. + + @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO + + @return whether specific FIFO is full or not + +**/ +BOOLEAN +IsaSerialFifoFull ( + IN SERIAL_DEV_FIFO *Fifo + ) + +{ + if (Fifo->Surplus == 0) { + return TRUE; + } + + return FALSE; +} + +/** + Detect whether specific FIFO is empty or not. + + @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO + + @return whether specific FIFO is empty or not + +**/ +BOOLEAN +IsaSerialFifoEmpty ( + IN SERIAL_DEV_FIFO *Fifo + ) + +{ + if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) { + return TRUE; + } + + return FALSE; +} + +/** + Add data to specific FIFO. + + @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO + @param Data the data added to FIFO + + @retval EFI_SUCCESS Add data to specific FIFO successfully + @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full + +**/ +EFI_STATUS +IsaSerialFifoAdd ( + IN SERIAL_DEV_FIFO *Fifo, + IN UINT8 Data + ) + +{ + // + // if FIFO full can not add data + // + if (IsaSerialFifoFull (Fifo)) { + return EFI_OUT_OF_RESOURCES; + } + // + // FIFO is not full can add data + // + Fifo->Data[Fifo->Last] = Data; + Fifo->Surplus--; + Fifo->Last++; + if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) { + Fifo->Last = 0; + } + + return EFI_SUCCESS; +} + +/** + Remove data from specific FIFO. + + @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO + @param Data the data removed from FIFO + + @retval EFI_SUCCESS Remove data from specific FIFO successfully + @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty + +**/ +EFI_STATUS +IsaSerialFifoRemove ( + IN SERIAL_DEV_FIFO *Fifo, + OUT UINT8 *Data + ) + +{ + // + // if FIFO is empty, no data can remove + // + if (IsaSerialFifoEmpty (Fifo)) { + return EFI_OUT_OF_RESOURCES; + } + // + // FIFO is not empty, can remove data + // + *Data = Fifo->Data[Fifo->First]; + Fifo->Surplus++; + Fifo->First++; + if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) { + Fifo->First = 0; + } + + return EFI_SUCCESS; +} + +/** + Reads and writes all avaliable data. + + @param SerialDevice The device to flush + + @retval EFI_SUCCESS Data was read/written successfully. + @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when + this happens, pending writes are not done. + +**/ +EFI_STATUS +IsaSerialReceiveTransmit ( + IN SERIAL_DEV *SerialDevice + ) + +{ + SERIAL_PORT_LSR Lsr; + UINT8 Data; + BOOLEAN ReceiveFifoFull; + SERIAL_PORT_MSR Msr; + SERIAL_PORT_MCR Mcr; + UINTN TimeOut; + + Data = 0; + + // + // Begin the read or write + // + if (SerialDevice->SoftwareLoopbackEnable) { + do { + ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive); + if (!IsaSerialFifoEmpty (&SerialDevice->Transmit)) { + IsaSerialFifoRemove (&SerialDevice->Transmit, &Data); + if (ReceiveFifoFull) { + return EFI_OUT_OF_RESOURCES; + } + + IsaSerialFifoAdd (&SerialDevice->Receive, Data); + } + } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit)); + } else { + ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive); + // + // For full handshake flow control, tell the peer to send data + // if receive buffer is available. + // + if (SerialDevice->HardwareFlowControl && + !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)&& + !ReceiveFifoFull + ) { + Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Mcr.Bits.Rts = 1; + WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); + } + do { + Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + + // + // Flush incomming data to prevent a an overrun during a long write + // + if ((Lsr.Bits.Dr == 1) && !ReceiveFifoFull) { + ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive); + if (!ReceiveFifoFull) { + if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Oe == 1 || Lsr.Bits.Pe == 1 || Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE, + EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT, + SerialDevice->DevicePath + ); + if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Pe == 1|| Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) { + Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + continue; + } + } + + Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + + IsaSerialFifoAdd (&SerialDevice->Receive, Data); + + // + // For full handshake flow control, if receive buffer full + // tell the peer to stop sending data. + // + if (SerialDevice->HardwareFlowControl && + !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake) && + IsaSerialFifoFull (&SerialDevice->Receive) + ) { + Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Mcr.Bits.Rts = 0; + WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); + } + + + continue; + } else { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT, + SerialDevice->DevicePath + ); + } + } + // + // Do the write + // + if (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) { + // + // Make sure the transmit data will not be missed + // + if (SerialDevice->HardwareFlowControl) { + // + // For half handshake flow control assert RTS before sending. + // + if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) { + Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Mcr.Bits.Rts= 0; + WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); + } + // + // Wait for CTS + // + TimeOut = 0; + Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + while ((Msr.Bits.Dcd == 1) && ((Msr.Bits.Cts == 0) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) { + gBS->Stall (TIMEOUT_STALL_INTERVAL); + TimeOut++; + if (TimeOut > 5) { + break; + } + + Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + } + + if ((Msr.Bits.Dcd == 0) || ((Msr.Bits.Cts == 1) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) { + IsaSerialFifoRemove (&SerialDevice->Transmit, &Data); + WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data); + } + + // + // For half handshake flow control, tell DCE we are done. + // + if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) { + Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Mcr.Bits.Rts = 1; + WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); + } + } else { + IsaSerialFifoRemove (&SerialDevice->Transmit, &Data); + WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data); + } + } + } while (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)); + } + + return EFI_SUCCESS; +} + +// +// Interface Functions +// +/** + Reset serial device. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + + @retval EFI_SUCCESS Reset successfully + @retval EFI_DEVICE_ERROR Failed to reset + +**/ +EFI_STATUS +EFIAPI +IsaSerialReset ( + IN EFI_SERIAL_IO_PROTOCOL *This + ) +{ + EFI_STATUS Status; + SERIAL_DEV *SerialDevice; + SERIAL_PORT_LCR Lcr; + SERIAL_PORT_IER Ier; + SERIAL_PORT_MCR Mcr; + SERIAL_PORT_FCR Fcr; + EFI_TPL Tpl; + UINT32 Control; + + SerialDevice = SERIAL_DEV_FROM_THIS (This); + + // + // Report the status code reset the serial + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT, + SerialDevice->DevicePath + ); + + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Make sure DLAB is 0. + // + Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Lcr.Bits.DLab = 0; + WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data); + + // + // Turn off all interrupts + // + Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Ier.Bits.Ravie = 0; + Ier.Bits.Theie = 0; + Ier.Bits.Rie = 0; + Ier.Bits.Mie = 0; + WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data); + + // + // Disable the FIFO. + // + Fcr.Bits.TrFIFOE = 0; + WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data); + + // + // Turn off loopback and disable device interrupt. + // + Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Mcr.Bits.Out1 = 0; + Mcr.Bits.Out2 = 0; + Mcr.Bits.Lme = 0; + WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); + + // + // Clear the scratch pad register + // + WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0); + + // + // Go set the current attributes + // + Status = This->SetAttributes ( + This, + This->Mode->BaudRate, + This->Mode->ReceiveFifoDepth, + This->Mode->Timeout, + (EFI_PARITY_TYPE) This->Mode->Parity, + (UINT8) This->Mode->DataBits, + (EFI_STOP_BITS_TYPE) This->Mode->StopBits + ); + + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + // + // Go set the current control bits + // + Control = 0; + if (SerialDevice->HardwareFlowControl) { + Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } + if (SerialDevice->SoftwareLoopbackEnable) { + Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE; + } + Status = This->SetControl ( + This, + Control + ); + + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + // + // for 16550A enable FIFO, 16550 disable FIFO + // + Fcr.Bits.TrFIFOE = 1; + Fcr.Bits.ResetRF = 1; + Fcr.Bits.ResetTF = 1; + WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data); + + // + // Reset the software FIFO + // + SerialDevice->Receive.First = 0; + SerialDevice->Receive.Last = 0; + SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE; + SerialDevice->Transmit.First = 0; + SerialDevice->Transmit.Last = 0; + SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE; + + gBS->RestoreTPL (Tpl); + + // + // Device reset is complete + // + return EFI_SUCCESS; +} + +/** + Set new attributes to a serial device. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param BaudRate The baudrate of the serial device + @param ReceiveFifoDepth The depth of receive FIFO buffer + @param Timeout The request timeout for a single char + @param Parity The type of parity used in serial device + @param DataBits Number of databits used in serial device + @param StopBits Number of stopbits used in serial device + + @retval EFI_SUCCESS The new attributes were set + @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value + @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6 + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return) + +**/ +EFI_STATUS +EFIAPI +IsaSerialSetAttributes ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ) +{ + EFI_STATUS Status; + SERIAL_DEV *SerialDevice; + UINT32 Divisor; + UINT32 Remained; + SERIAL_PORT_LCR Lcr; + UART_DEVICE_PATH *Uart; + EFI_TPL Tpl; + + SerialDevice = SERIAL_DEV_FROM_THIS (This); + + // + // Check for default settings and fill in actual values. + // + if (BaudRate == 0) { + BaudRate = PcdGet64 (PcdUartDefaultBaudRate); + } + + if (ReceiveFifoDepth == 0) { + ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH; + } + + if (Timeout == 0) { + Timeout = SERIAL_PORT_DEFAULT_TIMEOUT; + } + + if (Parity == DefaultParity) { + Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity); + } + + if (DataBits == 0) { + DataBits = PcdGet8 (PcdUartDefaultDataBits); + } + + if (StopBits == DefaultStopBits) { + StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits); + } + // + // 5 and 6 data bits can not be verified on a 16550A UART + // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings. + // + if ((DataBits == 5) || (DataBits == 6)) { + return EFI_INVALID_PARAMETER; + } + // + // Make sure all parameters are valid + // + if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) { + return EFI_INVALID_PARAMETER; + } + // + // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200, + // 38400,57600,115200 + // + if (BaudRate < 75) { + BaudRate = 50; + } else if (BaudRate < 110) { + BaudRate = 75; + } else if (BaudRate < 134) { + BaudRate = 110; + } else if (BaudRate < 150) { + BaudRate = 134; + } else if (BaudRate < 300) { + BaudRate = 150; + } else if (BaudRate < 600) { + BaudRate = 300; + } else if (BaudRate < 1200) { + BaudRate = 600; + } else if (BaudRate < 1800) { + BaudRate = 1200; + } else if (BaudRate < 2000) { + BaudRate = 1800; + } else if (BaudRate < 2400) { + BaudRate = 2000; + } else if (BaudRate < 3600) { + BaudRate = 2400; + } else if (BaudRate < 4800) { + BaudRate = 3600; + } else if (BaudRate < 7200) { + BaudRate = 4800; + } else if (BaudRate < 9600) { + BaudRate = 7200; + } else if (BaudRate < 19200) { + BaudRate = 9600; + } else if (BaudRate < 38400) { + BaudRate = 19200; + } else if (BaudRate < 57600) { + BaudRate = 38400; + } else if (BaudRate < 115200) { + BaudRate = 57600; + } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) { + BaudRate = 115200; + } + + if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) { + return EFI_INVALID_PARAMETER; + } + + if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) { + return EFI_INVALID_PARAMETER; + } + + if ((Parity < NoParity) || (Parity > SpaceParity)) { + return EFI_INVALID_PARAMETER; + } + + if ((DataBits < 5) || (DataBits > 8)) { + return EFI_INVALID_PARAMETER; + } + + if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) { + return EFI_INVALID_PARAMETER; + } + + // + // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits + // + if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) { + return EFI_INVALID_PARAMETER; + } + + // + // Compute divisor use to program the baud rate using a round determination + // + Divisor = (UINT32) DivU64x32Remainder ( + PcdGet32 (PcdSerialClockRate), + ((UINT32) BaudRate * 16), + &Remained + ); + if (Remained != 0) { + Divisor += 1; + } + + if ((Divisor == 0) || ((Divisor & 0xffff0000) != 0)) { + return EFI_INVALID_PARAMETER; + } + + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Compute the actual baud rate that the serial port will be programmed for. + // + BaudRate = PcdGet32 (PcdSerialClockRate) / Divisor / 16; + + // + // Put serial port on Divisor Latch Mode + // + Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Lcr.Bits.DLab = 1; + WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data); + + // + // Write the divisor to the serial port + // + WRITE_DLL (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) (Divisor & 0xff)); + WRITE_DLM (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) ((Divisor >> 8) & 0xff)); + + // + // Put serial port back in normal mode and set remaining attributes. + // + Lcr.Bits.DLab = 0; + + switch (Parity) { + case NoParity: + Lcr.Bits.ParEn = 0; + Lcr.Bits.EvenPar = 0; + Lcr.Bits.SticPar = 0; + break; + + case EvenParity: + Lcr.Bits.ParEn = 1; + Lcr.Bits.EvenPar = 1; + Lcr.Bits.SticPar = 0; + break; + + case OddParity: + Lcr.Bits.ParEn = 1; + Lcr.Bits.EvenPar = 0; + Lcr.Bits.SticPar = 0; + break; + + case SpaceParity: + Lcr.Bits.ParEn = 1; + Lcr.Bits.EvenPar = 1; + Lcr.Bits.SticPar = 1; + break; + + case MarkParity: + Lcr.Bits.ParEn = 1; + Lcr.Bits.EvenPar = 0; + Lcr.Bits.SticPar = 1; + break; + + default: + break; + } + + switch (StopBits) { + case OneStopBit: + Lcr.Bits.StopB = 0; + break; + + case OneFiveStopBits: + case TwoStopBits: + Lcr.Bits.StopB = 1; + break; + + default: + break; + } + // + // DataBits + // + Lcr.Bits.SerialDB = (UINT8) ((DataBits - 5) & 0x03); + WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data); + + // + // Set the Serial I/O mode + // + This->Mode->BaudRate = BaudRate; + This->Mode->ReceiveFifoDepth = ReceiveFifoDepth; + This->Mode->Timeout = Timeout; + This->Mode->Parity = Parity; + This->Mode->DataBits = DataBits; + This->Mode->StopBits = StopBits; + + // + // See if Device Path Node has actually changed + // + if (SerialDevice->UartDevicePath.BaudRate == BaudRate && + SerialDevice->UartDevicePath.DataBits == DataBits && + SerialDevice->UartDevicePath.Parity == Parity && + SerialDevice->UartDevicePath.StopBits == StopBits + ) { + gBS->RestoreTPL (Tpl); + return EFI_SUCCESS; + } + // + // Update the device path + // + SerialDevice->UartDevicePath.BaudRate = BaudRate; + SerialDevice->UartDevicePath.DataBits = DataBits; + SerialDevice->UartDevicePath.Parity = (UINT8) Parity; + SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits; + + Status = EFI_SUCCESS; + if (SerialDevice->Handle != NULL) { + Uart = (UART_DEVICE_PATH *) ( + (UINTN) SerialDevice->DevicePath + + GetDevicePathSize (SerialDevice->ParentDevicePath) + - END_DEVICE_PATH_LENGTH + ); + CopyMem (Uart, &SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH)); + Status = gBS->ReinstallProtocolInterface ( + SerialDevice->Handle, + &gEfiDevicePathProtocolGuid, + SerialDevice->DevicePath, + SerialDevice->DevicePath + ); + } + + gBS->RestoreTPL (Tpl); + + return Status; +} + +/** + Set Control Bits. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param Control Control bits that can be settable + + @retval EFI_SUCCESS New Control bits were set successfully + @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported + +**/ +EFI_STATUS +EFIAPI +IsaSerialSetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ) +{ + SERIAL_DEV *SerialDevice; + SERIAL_PORT_MCR Mcr; + EFI_TPL Tpl; + UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; + EFI_STATUS Status; + + // + // The control bits that can be set are : + // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO + // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO + // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW + // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW + // EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE: 0x4000 // RW + // + SerialDevice = SERIAL_DEV_FROM_THIS (This); + + // + // first determine the parameter is invalid + // + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | + EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) { + return EFI_UNSUPPORTED; + } + + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + + Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + Mcr.Bits.DtrC = 0; + Mcr.Bits.Rts = 0; + Mcr.Bits.Lme = 0; + SerialDevice->SoftwareLoopbackEnable = FALSE; + SerialDevice->HardwareFlowControl = FALSE; + + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { + Mcr.Bits.DtrC = 1; + } + + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { + Mcr.Bits.Rts = 1; + } + + if ((Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) { + Mcr.Bits.Lme = 1; + } + + if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) { + SerialDevice->HardwareFlowControl = TRUE; + } + + WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); + + if ((Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) { + SerialDevice->SoftwareLoopbackEnable = TRUE; + } + + Status = EFI_SUCCESS; + if (SerialDevice->Handle != NULL) { + FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) ( + (UINTN) SerialDevice->DevicePath + + GetDevicePathSize (SerialDevice->ParentDevicePath) + - END_DEVICE_PATH_LENGTH + + sizeof (UART_DEVICE_PATH) + ); + if (IsUartFlowControlNode (FlowControl) && + ((ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) ^ SerialDevice->HardwareFlowControl)) { + // + // Flow Control setting is changed, need to reinstall device path protocol + // + WriteUnaligned32 (&FlowControl->FlowControlMap, SerialDevice->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0); + Status = gBS->ReinstallProtocolInterface ( + SerialDevice->Handle, + &gEfiDevicePathProtocolGuid, + SerialDevice->DevicePath, + SerialDevice->DevicePath + ); + } + } + + gBS->RestoreTPL (Tpl); + + return Status; +} + +/** + Get ControlBits. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param Control Control signals of the serial device + + @retval EFI_SUCCESS Get Control signals successfully + +**/ +EFI_STATUS +EFIAPI +IsaSerialGetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ) +{ + SERIAL_DEV *SerialDevice; + SERIAL_PORT_MSR Msr; + SERIAL_PORT_MCR Mcr; + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + + SerialDevice = SERIAL_DEV_FROM_THIS (This); + + *Control = 0; + + // + // Read the Modem Status Register + // + Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + + if (Msr.Bits.Cts == 1) { + *Control |= EFI_SERIAL_CLEAR_TO_SEND; + } + + if (Msr.Bits.Dsr == 1) { + *Control |= EFI_SERIAL_DATA_SET_READY; + } + + if (Msr.Bits.Ri == 1) { + *Control |= EFI_SERIAL_RING_INDICATE; + } + + if (Msr.Bits.Dcd == 1) { + *Control |= EFI_SERIAL_CARRIER_DETECT; + } + // + // Read the Modem Control Register + // + Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + + if (Mcr.Bits.DtrC == 1) { + *Control |= EFI_SERIAL_DATA_TERMINAL_READY; + } + + if (Mcr.Bits.Rts == 1) { + *Control |= EFI_SERIAL_REQUEST_TO_SEND; + } + + if (Mcr.Bits.Lme == 1) { + *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE; + } + + if (SerialDevice->HardwareFlowControl) { + *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } + // + // See if the Transmit FIFO is empty + // + IsaSerialReceiveTransmit (SerialDevice); + + if (IsaSerialFifoEmpty (&SerialDevice->Transmit)) { + *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + // + // See if the Receive FIFO is empty. + // + IsaSerialReceiveTransmit (SerialDevice); + + if (IsaSerialFifoEmpty (&SerialDevice->Receive)) { + *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; + } + + if (SerialDevice->SoftwareLoopbackEnable) { + *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE; + } + + gBS->RestoreTPL (Tpl); + + return EFI_SUCCESS; +} + +/** + Write the specified number of bytes to serial device. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param BufferSize On input the size of Buffer, on output the amount of + data actually written + @param Buffer The buffer of data to write + + @retval EFI_SUCCESS The data were written successfully + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_TIMEOUT The write operation was stopped due to timeout + +**/ +EFI_STATUS +EFIAPI +IsaSerialWrite ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + SERIAL_DEV *SerialDevice; + UINT8 *CharBuffer; + UINT32 Index; + UINTN Elapsed; + UINTN ActualWrite; + EFI_TPL Tpl; + UINTN Timeout; + UINTN BitsPerCharacter; + + SerialDevice = SERIAL_DEV_FROM_THIS (This); + Elapsed = 0; + ActualWrite = 0; + + if (*BufferSize == 0) { + return EFI_SUCCESS; + } + + if (Buffer == NULL) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE, + EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT, + SerialDevice->DevicePath + ); + + return EFI_DEVICE_ERROR; + } + + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + + CharBuffer = (UINT8 *) Buffer; + + // + // Compute the number of bits in a single character. This is a start bit, + // followed by the number of data bits, followed by the number of stop bits. + // The number of stop bits is specified by an enumeration that includes + // support for 1.5 stop bits. Treat 1.5 stop bits as 2 stop bits. + // + BitsPerCharacter = + 1 + + This->Mode->DataBits + + ((This->Mode->StopBits == TwoStopBits) ? 2 : This->Mode->StopBits); + + // + // Compute the timeout in microseconds to wait for a single byte to be + // transmitted. The Mode structure contans a Timeout field that is the + // maximum time to transmit or receive a character. However, many UARTs + // have a FIFO for transmits, so the time required to add one new character + // to the transmit FIFO may be the time required to flush a full FIFO. If + // the Timeout in the Mode structure is smaller than the time required to + // flush a full FIFO at the current baud rate, then use a timeout value that + // is required to flush a full transmit FIFO. + // + Timeout = MAX ( + This->Mode->Timeout, + (UINTN)DivU64x64Remainder ( + BitsPerCharacter * (SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH + 1) * 1000000, + This->Mode->BaudRate, + NULL + ) + ); + + for (Index = 0; Index < *BufferSize; Index++) { + IsaSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]); + + while (IsaSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !IsaSerialFifoEmpty (&SerialDevice->Transmit)) { + // + // Unsuccessful write so check if timeout has expired, if not, + // stall for a bit, increment time elapsed, and try again + // + if (Elapsed >= Timeout) { + *BufferSize = ActualWrite; + gBS->RestoreTPL (Tpl); + return EFI_TIMEOUT; + } + + gBS->Stall (TIMEOUT_STALL_INTERVAL); + + Elapsed += TIMEOUT_STALL_INTERVAL; + } + + ActualWrite++; + // + // Successful write so reset timeout + // + Elapsed = 0; + } + + gBS->RestoreTPL (Tpl); + + return EFI_SUCCESS; +} + +/** + Read the specified number of bytes from serial device. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param BufferSize On input the size of Buffer, on output the amount of + data returned in buffer + @param Buffer The buffer to return the data into + + @retval EFI_SUCCESS The data were read successfully + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_TIMEOUT The read operation was stopped due to timeout + +**/ +EFI_STATUS +EFIAPI +IsaSerialRead ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + SERIAL_DEV *SerialDevice; + UINT32 Index; + UINT8 *CharBuffer; + UINTN Elapsed; + EFI_STATUS Status; + EFI_TPL Tpl; + + SerialDevice = SERIAL_DEV_FROM_THIS (This); + Elapsed = 0; + + if (*BufferSize == 0) { + return EFI_SUCCESS; + } + + if (Buffer == NULL) { + return EFI_DEVICE_ERROR; + } + + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = IsaSerialReceiveTransmit (SerialDevice); + + if (EFI_ERROR (Status)) { + *BufferSize = 0; + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE, + EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT, + SerialDevice->DevicePath + ); + + gBS->RestoreTPL (Tpl); + + return EFI_DEVICE_ERROR; + } + + CharBuffer = (UINT8 *) Buffer; + for (Index = 0; Index < *BufferSize; Index++) { + while (IsaSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) { + // + // Unsuccessful read so check if timeout has expired, if not, + // stall for a bit, increment time elapsed, and try again + // Need this time out to get conspliter to work. + // + if (Elapsed >= This->Mode->Timeout) { + *BufferSize = Index; + gBS->RestoreTPL (Tpl); + return EFI_TIMEOUT; + } + + gBS->Stall (TIMEOUT_STALL_INTERVAL); + Elapsed += TIMEOUT_STALL_INTERVAL; + + Status = IsaSerialReceiveTransmit (SerialDevice); + if (Status == EFI_DEVICE_ERROR) { + *BufferSize = Index; + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + } + // + // Successful read so reset timeout + // + Elapsed = 0; + } + + IsaSerialReceiveTransmit (SerialDevice); + + gBS->RestoreTPL (Tpl); + + return EFI_SUCCESS; +} + +/** + Use scratchpad register to test if this serial port is present. + + @param SerialDevice Pointer to serial device structure + + @return if this serial port is present +**/ +BOOLEAN +IsaSerialPortPresent ( + IN SERIAL_DEV *SerialDevice + ) + +{ + UINT8 Temp; + BOOLEAN Status; + + Status = TRUE; + + // + // Save SCR reg + // + Temp = READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); + WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0xAA); + + if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0xAA) { + Status = FALSE; + } + + WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0x55); + + if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0x55) { + Status = FALSE; + } + // + // Restore SCR + // + WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Temp); + return Status; +} + +/** + Use IsaIo protocol to read serial port. + + @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance + @param BaseAddress Serial port register group base address + @param Offset Offset in register group + + @return Data read from serial port + +**/ +UINT8 +IsaSerialReadPort ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT16 BaseAddress, + IN UINT32 Offset + ) +{ + UINT8 Data; + + // + // Use IsaIo to access IO + // + IsaIo->Io.Read ( + IsaIo, + EfiIsaIoWidthUint8, + BaseAddress + Offset, + 1, + &Data + ); + return Data; +} + +/** + Use IsaIo protocol to write serial port. + + @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance + @param BaseAddress Serial port register group base address + @param Offset Offset in register group + @param Data data which is to be written to some serial port register + +**/ +VOID +IsaSerialWritePort ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT16 BaseAddress, + IN UINT32 Offset, + IN UINT8 Data + ) +{ + // + // Use IsaIo to access IO + // + IsaIo->Io.Write ( + IsaIo, + EfiIsaIoWidthUint8, + BaseAddress + Offset, + 1, + &Data + ); +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.h b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.h new file mode 100644 index 0000000000..9d50ca9e27 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.h @@ -0,0 +1,842 @@ +/** @file + Include for Serial Driver + +Copyright (c) 2006 - 2015, Intel 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 _SERIAL_H_ +#define _SERIAL_H_ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Driver Binding Externs +// +extern EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver; +extern EFI_COMPONENT_NAME_PROTOCOL gIsaSerialComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gIsaSerialComponentName2; + +// +// Internal Data Structures +// +#define SERIAL_DEV_SIGNATURE SIGNATURE_32 ('s', 'e', 'r', 'd') +#define SERIAL_MAX_BUFFER_SIZE 16 +#define TIMEOUT_STALL_INTERVAL 10 + +// +// Name: SERIAL_DEV_FIFO +// Purpose: To define Receive FIFO and Transmit FIFO +// Context: Used by serial data transmit and receive +// Fields: +// First UINT32: The index of the first data in array Data[] +// Last UINT32: The index, which you can put a new data into array Data[] +// Surplus UINT32: Identify how many data you can put into array Data[] +// Data[] UINT8 : An array, which used to store data +// +typedef struct { + UINT32 First; + UINT32 Last; + UINT32 Surplus; + UINT8 Data[SERIAL_MAX_BUFFER_SIZE]; +} SERIAL_DEV_FIFO; + +typedef enum { + Uart8250 = 0, + Uart16450 = 1, + Uart16550 = 2, + Uart16550A= 3 +} EFI_UART_TYPE; + +// +// Name: SERIAL_DEV +// Purpose: To provide device specific information +// Context: +// Fields: +// Signature UINTN: The identity of the serial device +// SerialIo SERIAL_IO_PROTOCOL: Serial I/O protocol interface +// SerialMode SERIAL_IO_MODE: +// DevicePath EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device +// Handle EFI_HANDLE: The handle instance attached to serial device +// BaseAddress UINT16: The base address of specific serial device +// Receive SERIAL_DEV_FIFO: The FIFO used to store data, +// which is received by UART +// Transmit SERIAL_DEV_FIFO: The FIFO used to store data, +// which you want to transmit by UART +// SoftwareLoopbackEnable BOOLEAN: +// Type EFI_UART_TYPE: Specify the UART type of certain serial device +// +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_SERIAL_IO_PROTOCOL SerialIo; + EFI_SERIAL_IO_MODE SerialMode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + UART_DEVICE_PATH UartDevicePath; + EFI_ISA_IO_PROTOCOL *IsaIo; + + UINT16 BaseAddress; + SERIAL_DEV_FIFO Receive; + SERIAL_DEV_FIFO Transmit; + BOOLEAN SoftwareLoopbackEnable; + BOOLEAN HardwareFlowControl; + EFI_UART_TYPE Type; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} SERIAL_DEV; + +#define SERIAL_DEV_FROM_THIS(a) CR (a, SERIAL_DEV, SerialIo, SERIAL_DEV_SIGNATURE) + +// +// Serial Driver Defaults +// +#define SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH 1 +#define SERIAL_PORT_DEFAULT_TIMEOUT 1000000 +#define SERIAL_PORT_SUPPORT_CONTROL_MASK (EFI_SERIAL_CLEAR_TO_SEND | \ + EFI_SERIAL_DATA_SET_READY | \ + EFI_SERIAL_RING_INDICATE | \ + EFI_SERIAL_CARRIER_DETECT | \ + EFI_SERIAL_REQUEST_TO_SEND | \ + EFI_SERIAL_DATA_TERMINAL_READY | \ + EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | \ + EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \ + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE | \ + EFI_SERIAL_OUTPUT_BUFFER_EMPTY | \ + EFI_SERIAL_INPUT_BUFFER_EMPTY) + +// +// 115200 baud with rounding errors +// +#define SERIAL_PORT_MAX_BAUD_RATE 115400 +#define SERIAL_PORT_MIN_BAUD_RATE 50 + +#define SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH 16 +#define SERIAL_PORT_MIN_TIMEOUT 1 // 1 uS +#define SERIAL_PORT_MAX_TIMEOUT 100000000 // 100 seconds +// +// UART Registers +// +#define SERIAL_REGISTER_THR 0 // WO Transmit Holding Register +#define SERIAL_REGISTER_RBR 0 // RO Receive Buffer Register +#define SERIAL_REGISTER_DLL 0 // R/W Divisor Latch LSB +#define SERIAL_REGISTER_DLM 1 // R/W Divisor Latch MSB +#define SERIAL_REGISTER_IER 1 // R/W Interrupt Enable Register +#define SERIAL_REGISTER_IIR 2 // RO Interrupt Identification Register +#define SERIAL_REGISTER_FCR 2 // WO FIFO Cotrol Register +#define SERIAL_REGISTER_LCR 3 // R/W Line Control Register +#define SERIAL_REGISTER_MCR 4 // R/W Modem Control Register +#define SERIAL_REGISTER_LSR 5 // R/W Line Status Register +#define SERIAL_REGISTER_MSR 6 // R/W Modem Status Register +#define SERIAL_REGISTER_SCR 7 // R/W Scratch Pad Register +#pragma pack(1) +// +// Name: SERIAL_PORT_IER_BITS +// Purpose: Define each bit in Interrupt Enable Register +// Context: +// Fields: +// Ravie Bit0: Receiver Data Available Interrupt Enable +// Theie Bit1: Transmistter Holding Register Empty Interrupt Enable +// Rie Bit2: Receiver Interrupt Enable +// Mie Bit3: Modem Interrupt Enable +// Reserved Bit4-Bit7: Reserved +// +typedef struct { + UINT8 Ravie : 1; + UINT8 Theie : 1; + UINT8 Rie : 1; + UINT8 Mie : 1; + UINT8 Reserved : 4; +} SERIAL_PORT_IER_BITS; + +// +// Name: SERIAL_PORT_IER +// Purpose: +// Context: +// Fields: +// Bits SERIAL_PORT_IER_BITS: Bits of the IER +// Data UINT8: the value of the IER +// +typedef union { + SERIAL_PORT_IER_BITS Bits; + UINT8 Data; +} SERIAL_PORT_IER; + +// +// Name: SERIAL_PORT_FCR_BITS +// Purpose: Define each bit in FIFO Control Register +// Context: +// Fields: +// TrFIFOE Bit0: Transmit and Receive FIFO Enable +// ResetRF Bit1: Reset Reciever FIFO +// ResetTF Bit2: Reset Transmistter FIFO +// Dms Bit3: DMA Mode Select +// Reserved Bit4-Bit5: Reserved +// Rtb Bit6-Bit7: Receive Trigger Bits +// +typedef struct { + UINT8 TrFIFOE : 1; + UINT8 ResetRF : 1; + UINT8 ResetTF : 1; + UINT8 Dms : 1; + UINT8 Reserved : 2; + UINT8 Rtb : 2; +} SERIAL_PORT_FCR_BITS; + +// +// Name: SERIAL_PORT_FCR +// Purpose: +// Context: +// Fields: +// Bits SERIAL_PORT_FCR_BITS: Bits of the FCR +// Data UINT8: the value of the FCR +// +typedef union { + SERIAL_PORT_FCR_BITS Bits; + UINT8 Data; +} SERIAL_PORT_FCR; + +// +// Name: SERIAL_PORT_LCR_BITS +// Purpose: Define each bit in Line Control Register +// Context: +// Fields: +// SerialDB Bit0-Bit1: Number of Serial Data Bits +// StopB Bit2: Number of Stop Bits +// ParEn Bit3: Parity Enable +// EvenPar Bit4: Even Parity Select +// SticPar Bit5: Sticky Parity +// BrCon Bit6: Break Control +// DLab Bit7: Divisor Latch Access Bit +// +typedef struct { + UINT8 SerialDB : 2; + UINT8 StopB : 1; + UINT8 ParEn : 1; + UINT8 EvenPar : 1; + UINT8 SticPar : 1; + UINT8 BrCon : 1; + UINT8 DLab : 1; +} SERIAL_PORT_LCR_BITS; + +// +// Name: SERIAL_PORT_LCR +// Purpose: +// Context: +// Fields: +// Bits SERIAL_PORT_LCR_BITS: Bits of the LCR +// Data UINT8: the value of the LCR +// +typedef union { + SERIAL_PORT_LCR_BITS Bits; + UINT8 Data; +} SERIAL_PORT_LCR; + +// +// Name: SERIAL_PORT_MCR_BITS +// Purpose: Define each bit in Modem Control Register +// Context: +// Fields: +// DtrC Bit0: Data Terminal Ready Control +// Rts Bit1: Request To Send Control +// Out1 Bit2: Output1 +// Out2 Bit3: Output2, used to disable interrupt +// Lme; Bit4: Loopback Mode Enable +// Reserved Bit5-Bit7: Reserved +// +typedef struct { + UINT8 DtrC : 1; + UINT8 Rts : 1; + UINT8 Out1 : 1; + UINT8 Out2 : 1; + UINT8 Lme : 1; + UINT8 Reserved : 3; +} SERIAL_PORT_MCR_BITS; + +// +// Name: SERIAL_PORT_MCR +// Purpose: +// Context: +// Fields: +// Bits SERIAL_PORT_MCR_BITS: Bits of the MCR +// Data UINT8: the value of the MCR +// +typedef union { + SERIAL_PORT_MCR_BITS Bits; + UINT8 Data; +} SERIAL_PORT_MCR; + +// +// Name: SERIAL_PORT_LSR_BITS +// Purpose: Define each bit in Line Status Register +// Context: +// Fields: +// Dr Bit0: Receiver Data Ready Status +// Oe Bit1: Overrun Error Status +// Pe Bit2: Parity Error Status +// Fe Bit3: Framing Error Status +// Bi Bit4: Break Interrupt Status +// Thre Bit5: Transmistter Holding Register Status +// Temt Bit6: Transmitter Empty Status +// FIFOe Bit7: FIFO Error Status +// +typedef struct { + UINT8 Dr : 1; + UINT8 Oe : 1; + UINT8 Pe : 1; + UINT8 Fe : 1; + UINT8 Bi : 1; + UINT8 Thre : 1; + UINT8 Temt : 1; + UINT8 FIFOe : 1; +} SERIAL_PORT_LSR_BITS; + +// +// Name: SERIAL_PORT_LSR +// Purpose: +// Context: +// Fields: +// Bits SERIAL_PORT_LSR_BITS: Bits of the LSR +// Data UINT8: the value of the LSR +// +typedef union { + SERIAL_PORT_LSR_BITS Bits; + UINT8 Data; +} SERIAL_PORT_LSR; + +// +// Name: SERIAL_PORT_MSR_BITS +// Purpose: Define each bit in Modem Status Register +// Context: +// Fields: +// DeltaCTS Bit0: Delta Clear To Send Status +// DeltaDSR Bit1: Delta Data Set Ready Status +// TrailingEdgeRI Bit2: Trailing Edge of Ring Indicator Status +// DeltaDCD Bit3: Delta Data Carrier Detect Status +// Cts Bit4: Clear To Send Status +// Dsr Bit5: Data Set Ready Status +// Ri Bit6: Ring Indicator Status +// Dcd Bit7: Data Carrier Detect Status +// +typedef struct { + UINT8 DeltaCTS : 1; + UINT8 DeltaDSR : 1; + UINT8 TrailingEdgeRI : 1; + UINT8 DeltaDCD : 1; + UINT8 Cts : 1; + UINT8 Dsr : 1; + UINT8 Ri : 1; + UINT8 Dcd : 1; +} SERIAL_PORT_MSR_BITS; + +// +// Name: SERIAL_PORT_MSR +// Purpose: +// Context: +// Fields: +// Bits SERIAL_PORT_MSR_BITS: Bits of the MSR +// Data UINT8: the value of the MSR +// +typedef union { + SERIAL_PORT_MSR_BITS Bits; + UINT8 Data; +} SERIAL_PORT_MSR; + +#pragma pack() +// +// Define serial register I/O macros +// +#define READ_RBR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_RBR) +#define READ_DLL(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_DLL) +#define READ_DLM(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_DLM) +#define READ_IER(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_IER) +#define READ_IIR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_IIR) +#define READ_LCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_LCR) +#define READ_MCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_MCR) +#define READ_LSR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_LSR) +#define READ_MSR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_MSR) +#define READ_SCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_SCR) + +#define WRITE_THR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_THR, D) +#define WRITE_DLL(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_DLL, D) +#define WRITE_DLM(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_DLM, D) +#define WRITE_IER(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_IER, D) +#define WRITE_FCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_FCR, D) +#define WRITE_LCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_LCR, D) +#define WRITE_MCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_MCR, D) +#define WRITE_LSR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_LSR, D) +#define WRITE_MSR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_MSR, D) +#define WRITE_SCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_SCR, D) + +// +// Prototypes +// Driver model protocol interface +// +/** + Check to see if this driver supports the given controller + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @return EFI_SUCCESS This driver can support the given controller + +**/ +EFI_STATUS +EFIAPI +SerialControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start to management the controller passed in + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @return EFI_SUCCESS Driver is started successfully +**/ +EFI_STATUS +EFIAPI +SerialControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Disconnect this driver with the controller, uninstall related protocol instance + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param NumberOfChildren Number of child device. + @param ChildHandleBuffer A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS Operation successfully + @retval EFI_DEVICE_ERROR Cannot stop the driver successfully + +**/ +EFI_STATUS +EFIAPI +SerialControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Serial I/O Protocol Interface +// +/** + Reset serial device. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + + @retval EFI_SUCCESS Reset successfully + @retval EFI_DEVICE_ERROR Failed to reset + +**/ +EFI_STATUS +EFIAPI +IsaSerialReset ( + IN EFI_SERIAL_IO_PROTOCOL *This + ); + +/** + Set new attributes to a serial device. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param BaudRate The baudrate of the serial device + @param ReceiveFifoDepth The depth of receive FIFO buffer + @param Timeout The request timeout for a single char + @param Parity The type of parity used in serial device + @param DataBits Number of databits used in serial device + @param StopBits Number of stopbits used in serial device + + @retval EFI_SUCCESS The new attributes were set + @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value + @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6 + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return) + +**/ +EFI_STATUS +EFIAPI +IsaSerialSetAttributes ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ); + +/** + Set Control Bits. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param Control Control bits that can be settable + + @retval EFI_SUCCESS New Control bits were set successfully + @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported + +**/ +EFI_STATUS +EFIAPI +IsaSerialSetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ); + +/** + Get ControlBits. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param Control Control signals of the serial device + + @retval EFI_SUCCESS Get Control signals successfully + +**/ +EFI_STATUS +EFIAPI +IsaSerialGetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ); + +/** + Write the specified number of bytes to serial device. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param BufferSize On input the size of Buffer, on output the amount of + data actually written + @param Buffer The buffer of data to write + + @retval EFI_SUCCESS The data were written successfully + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_TIMEOUT The write operation was stopped due to timeout + +**/ +EFI_STATUS +EFIAPI +IsaSerialWrite ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Read the specified number of bytes from serial device. + + @param This Pointer to EFI_SERIAL_IO_PROTOCOL + @param BufferSize On input the size of Buffer, on output the amount of + data returned in buffer + @param Buffer The buffer to return the data into + + @retval EFI_SUCCESS The data were read successfully + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_TIMEOUT The read operation was stopped due to timeout + +**/ +EFI_STATUS +EFIAPI +IsaSerialRead ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +// +// Internal Functions +// +/** + Use scratchpad register to test if this serial port is present. + + @param SerialDevice Pointer to serial device structure + + @return if this serial port is present +**/ +BOOLEAN +IsaSerialPortPresent ( + IN SERIAL_DEV *SerialDevice + ); + +/** + Detect whether specific FIFO is full or not. + + @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO + + @return whether specific FIFO is full or not + +**/ +BOOLEAN +IsaSerialFifoFull ( + IN SERIAL_DEV_FIFO *Fifo + ); + +/** + Detect whether specific FIFO is empty or not. + + @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO + + @return whether specific FIFO is empty or not + +**/ +BOOLEAN +IsaSerialFifoEmpty ( + IN SERIAL_DEV_FIFO *Fifo + ); + +/** + Add data to specific FIFO. + + @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO + @param Data the data added to FIFO + + @retval EFI_SUCCESS Add data to specific FIFO successfully + @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full + +**/ +EFI_STATUS +IsaSerialFifoAdd ( + IN SERIAL_DEV_FIFO *Fifo, + IN UINT8 Data + ); + +/** + Remove data from specific FIFO. + + @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO + @param Data the data removed from FIFO + + @retval EFI_SUCCESS Remove data from specific FIFO successfully + @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty + +**/ +EFI_STATUS +IsaSerialFifoRemove ( + IN SERIAL_DEV_FIFO *Fifo, + OUT UINT8 *Data + ); + +/** + Reads and writes all avaliable data. + + @param SerialDevice The device to flush + + @retval EFI_SUCCESS Data was read/written successfully. + @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when + this happens, pending writes are not done. + +**/ +EFI_STATUS +IsaSerialReceiveTransmit ( + IN SERIAL_DEV *SerialDevice + ); + +/** + Use IsaIo protocol to read serial port. + + @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance + @param BaseAddress Serial port register group base address + @param Offset Offset in register group + + @return Data read from serial port + +**/ +UINT8 +IsaSerialReadPort ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT16 BaseAddress, + IN UINT32 Offset + ); + +/** + Use IsaIo protocol to write serial port. + + @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance + @param BaseAddress Serial port register group base address + @param Offset Offset in register group + @param Data data which is to be written to some serial port register + +**/ +VOID +IsaSerialWritePort ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT16 BaseAddress, + IN UINT32 Offset, + IN UINT8 Data + ); + + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +IsaSerialComponentNameGetDriverName ( + 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 +IsaSerialComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/** + Add the component name for the serial io device + + @param SerialDevice A pointer to the SERIAL_DEV instance. + + @param IsaIo A pointer to the EFI_ISA_IO_PROTOCOL instance. + +**/ +VOID +AddName ( + IN SERIAL_DEV *SerialDevice, + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c new file mode 100644 index 0000000000..e6c739e2ba --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c @@ -0,0 +1,372 @@ +/** @file + Routines related Component Name protocol. + +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 "Ps2Keyboard.h" + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +Ps2KeyboardComponentNameGetDriverName ( + 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 +Ps2KeyboardComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPs2KeyboardComponentName = { + Ps2KeyboardComponentNameGetDriverName, + Ps2KeyboardComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPs2KeyboardComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ps2KeyboardComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ps2KeyboardComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPs2KeyboardDriverNameTable[] = { + { + "eng;en", + L"PS/2 Keyboard Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +Ps2KeyboardComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mPs2KeyboardDriverNameTable, + DriverName, + (BOOLEAN)(This == &gPs2KeyboardComponentName) + ); +} + +/** + 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 +Ps2KeyboardComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; + EFI_ISA_IO_PROTOCOL *IsaIoProtocol; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + // + // Check Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIoProtocol, + gKeyboardControllerDriver.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiIsaIoProtocolGuid, + gKeyboardControllerDriver.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &ConIn, + gKeyboardControllerDriver.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + ConsoleIn->ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gPs2KeyboardComponentName) + ); +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c new file mode 100644 index 0000000000..2a20b789a7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c @@ -0,0 +1,1908 @@ +/** @file + Routines that access 8042 keyboard controller + +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 "Ps2Keyboard.h" + +struct { + UINT8 ScanCode; ///< follows value defined in Scan Code Set1 + UINT16 EfiScanCode; + CHAR16 UnicodeChar; + CHAR16 ShiftUnicodeChar; +} +ConvertKeyboardScanCodeToEfiKey[] = { + + { + 0x01, // Escape + SCAN_ESC, + 0x0000, + 0x0000 + }, + { + 0x02, + SCAN_NULL, + L'1', + L'!' + }, + { + 0x03, + SCAN_NULL, + L'2', + L'@' + }, + { + 0x04, + SCAN_NULL, + L'3', + L'#' + }, + { + 0x05, + SCAN_NULL, + L'4', + L'$' + }, + { + 0x06, + SCAN_NULL, + L'5', + L'%' + }, + { + 0x07, + SCAN_NULL, + L'6', + L'^' + }, + { + 0x08, + SCAN_NULL, + L'7', + L'&' + }, + { + 0x09, + SCAN_NULL, + L'8', + L'*' + }, + { + 0x0A, + SCAN_NULL, + L'9', + L'(' + }, + { + 0x0B, + SCAN_NULL, + L'0', + L')' + }, + { + 0x0C, + SCAN_NULL, + L'-', + L'_' + }, + { + 0x0D, + SCAN_NULL, + L'=', + L'+' + }, + { + 0x0E, // BackSpace + SCAN_NULL, + 0x0008, + 0x0008 + }, + { + 0x0F, // Tab + SCAN_NULL, + 0x0009, + 0x0009 + }, + { + 0x10, + SCAN_NULL, + L'q', + L'Q' + }, + { + 0x11, + SCAN_NULL, + L'w', + L'W' + }, + { + 0x12, + SCAN_NULL, + L'e', + L'E' + }, + { + 0x13, + SCAN_NULL, + L'r', + L'R' + }, + { + 0x14, + SCAN_NULL, + L't', + L'T' + }, + { + 0x15, + SCAN_NULL, + L'y', + L'Y' + }, + { + 0x16, + SCAN_NULL, + L'u', + L'U' + }, + { + 0x17, + SCAN_NULL, + L'i', + L'I' + }, + { + 0x18, + SCAN_NULL, + L'o', + L'O' + }, + { + 0x19, + SCAN_NULL, + L'p', + L'P' + }, + { + 0x1a, + SCAN_NULL, + L'[', + L'{' + }, + { + 0x1b, + SCAN_NULL, + L']', + L'}' + }, + { + 0x1c, // Enter + SCAN_NULL, + 0x000d, + 0x000d + }, + { + 0x1d, + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x1e, + SCAN_NULL, + L'a', + L'A' + }, + { + 0x1f, + SCAN_NULL, + L's', + L'S' + }, + { + 0x20, + SCAN_NULL, + L'd', + L'D' + }, + { + 0x21, + SCAN_NULL, + L'f', + L'F' + }, + { + 0x22, + SCAN_NULL, + L'g', + L'G' + }, + { + 0x23, + SCAN_NULL, + L'h', + L'H' + }, + { + 0x24, + SCAN_NULL, + L'j', + L'J' + }, + { + 0x25, + SCAN_NULL, + L'k', + L'K' + }, + { + 0x26, + SCAN_NULL, + L'l', + L'L' + }, + { + 0x27, + SCAN_NULL, + L';', + L':' + }, + { + 0x28, + SCAN_NULL, + L'\'', + L'"' + }, + { + 0x29, + SCAN_NULL, + L'`', + L'~' + }, + { + 0x2a, // Left Shift + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x2b, + SCAN_NULL, + L'\\', + L'|' + }, + { + 0x2c, + SCAN_NULL, + L'z', + L'Z' + }, + { + 0x2d, + SCAN_NULL, + L'x', + L'X' + }, + { + 0x2e, + SCAN_NULL, + L'c', + L'C' + }, + { + 0x2f, + SCAN_NULL, + L'v', + L'V' + }, + { + 0x30, + SCAN_NULL, + L'b', + L'B' + }, + { + 0x31, + SCAN_NULL, + L'n', + L'N' + }, + { + 0x32, + SCAN_NULL, + L'm', + L'M' + }, + { + 0x33, + SCAN_NULL, + L',', + L'<' + }, + { + 0x34, + SCAN_NULL, + L'.', + L'>' + }, + { + 0x35, + SCAN_NULL, + L'/', + L'?' + }, + { + 0x36, //Right Shift + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x37, // Numeric Keypad * + SCAN_NULL, + L'*', + L'*' + }, + { + 0x38, //Left Alt/Extended Right Alt + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x39, + SCAN_NULL, + L' ', + L' ' + }, + { + 0x3A, //CapsLock + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x3B, + SCAN_F1, + 0x0000, + 0x0000 + }, + { + 0x3C, + SCAN_F2, + 0x0000, + 0x0000 + }, + { + 0x3D, + SCAN_F3, + 0x0000, + 0x0000 + }, + { + 0x3E, + SCAN_F4, + 0x0000, + 0x0000 + }, + { + 0x3F, + SCAN_F5, + 0x0000, + 0x0000 + }, + { + 0x40, + SCAN_F6, + 0x0000, + 0x0000 + }, + { + 0x41, + SCAN_F7, + 0x0000, + 0x0000 + }, + { + 0x42, + SCAN_F8, + 0x0000, + 0x0000 + }, + { + 0x43, + SCAN_F9, + 0x0000, + 0x0000 + }, + { + 0x44, + SCAN_F10, + 0x0000, + 0x0000 + }, + { + 0x45, // NumLock + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x46, // ScrollLock + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x47, + SCAN_HOME, + L'7', + L'7' + }, + { + 0x48, + SCAN_UP, + L'8', + L'8' + }, + { + 0x49, + SCAN_PAGE_UP, + L'9', + L'9' + }, + { + 0x4a, + SCAN_NULL, + L'-', + L'-' + }, + { + 0x4b, + SCAN_LEFT, + L'4', + L'4' + }, + { + 0x4c, // Numeric Keypad 5 + SCAN_NULL, + L'5', + L'5' + }, + { + 0x4d, + SCAN_RIGHT, + L'6', + L'6' + }, + { + 0x4e, + SCAN_NULL, + L'+', + L'+' + }, + { + 0x4f, + SCAN_END, + L'1', + L'1' + }, + { + 0x50, + SCAN_DOWN, + L'2', + L'2' + }, + { + 0x51, + SCAN_PAGE_DOWN, + L'3', + L'3' + }, + { + 0x52, + SCAN_INSERT, + L'0', + L'0' + }, + { + 0x53, + SCAN_DELETE, + L'.', + L'.' + }, + { + 0x57, + SCAN_F11, + 0x0000, + 0x0000 + }, + { + 0x58, + SCAN_F12, + 0x0000, + 0x0000 + }, + { + 0x5B, //Left LOGO + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x5C, //Right LOGO + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + 0x5D, //Menu key + SCAN_NULL, + 0x0000, + 0x0000 + }, + { + TABLE_END, + TABLE_END, + SCAN_NULL, + SCAN_NULL + }, +}; + +// +// The WaitForValue time out +// +UINTN mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT; + +BOOLEAN mEnableMouseInterface; + + + +/** + Return the count of scancode in the queue. + + @param Queue Pointer to instance of SCAN_CODE_QUEUE. + + @return Count of the scancode. +**/ +UINTN +GetScancodeBufCount ( + IN SCAN_CODE_QUEUE *Queue + ) +{ + if (Queue->Head <= Queue->Tail) { + return Queue->Tail - Queue->Head; + } else { + return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head; + } +} + +/** + Read several bytes from the scancode buffer without removing them. + This function is called to see if there are enough bytes of scancode + representing a single key. + + @param Queue Pointer to instance of SCAN_CODE_QUEUE. + @param Count Number of bytes to be read + @param Buf Store the results + + @retval EFI_SUCCESS success to scan the keyboard code + @retval EFI_NOT_READY invalid parameter +**/ +EFI_STATUS +GetScancodeBufHead ( + IN SCAN_CODE_QUEUE *Queue, + IN UINTN Count, + OUT UINT8 *Buf + ) +{ + UINTN Index; + UINTN Pos; + + // + // check the valid range of parameter 'Count' + // + if (GetScancodeBufCount (Queue) < Count) { + return EFI_NOT_READY; + } + // + // retrieve the values + // + for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) { + Buf[Index] = Queue->Buffer[Pos]; + } + + return EFI_SUCCESS; +} + +/** + + Read & remove several bytes from the scancode buffer. + This function is usually called after GetScancodeBufHead() + + @param Queue Pointer to instance of SCAN_CODE_QUEUE. + @param Count Number of bytes to be read + @param Buf Store the results + + @retval EFI_SUCCESS success to scan the keyboard code + @retval EFI_NOT_READY invalid parameter +**/ +EFI_STATUS +PopScancodeBufHead ( + IN SCAN_CODE_QUEUE *Queue, + IN UINTN Count, + OUT UINT8 *Buf OPTIONAL + ) +{ + UINTN Index; + + // + // Check the valid range of parameter 'Count' + // + if (GetScancodeBufCount (Queue) < Count) { + return EFI_NOT_READY; + } + // + // Retrieve and remove the values + // + for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) { + if (Buf != NULL) { + Buf[Index] = Queue->Buffer[Queue->Head]; + } + } + + return EFI_SUCCESS; +} + +/** + Push one byte to the scancode buffer. + + @param Queue Pointer to instance of SCAN_CODE_QUEUE. + @param Scancode The byte to push. +**/ +VOID +PushScancodeBufTail ( + IN SCAN_CODE_QUEUE *Queue, + IN UINT8 Scancode + ) +{ + if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) { + PopScancodeBufHead (Queue, 1, NULL); + } + + Queue->Buffer[Queue->Tail] = Scancode; + Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT; +} + +/** + Read data register . + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + + @return return the value + +**/ +UINT8 +KeyReadDataRegister ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ) + +{ + EFI_ISA_IO_PROTOCOL *IsaIo; + UINT8 Data; + + // + // Use IsaIo protocol to perform IO operations + // + IsaIo = ConsoleIn->IsaIo; + + IsaIo->Io.Read ( + IsaIo, + EfiIsaIoWidthUint8, + ConsoleIn->DataRegisterAddress, + 1, + &Data + ); + + return Data; +} + +/** + Write data register. + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + @param Data value wanted to be written + +**/ +VOID +KeyWriteDataRegister ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + IN UINT8 Data + ) +{ + ConsoleIn->IsaIo->Io.Write ( + ConsoleIn->IsaIo, + EfiIsaIoWidthUint8, + ConsoleIn->DataRegisterAddress, + 1, + &Data + ); +} + +/** + Read status register. + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + + @return value in status register + +**/ +UINT8 +KeyReadStatusRegister ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ) +{ + UINT8 Data; + ConsoleIn->IsaIo->Io.Read ( + ConsoleIn->IsaIo, + EfiIsaIoWidthUint8, + ConsoleIn->StatusRegisterAddress, + 1, + &Data + ); + return Data; +} + +/** + Write command register . + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + @param Data The value wanted to be written + +**/ +VOID +KeyWriteCommandRegister ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + IN UINT8 Data + ) +{ + ConsoleIn->IsaIo->Io.Write ( + ConsoleIn->IsaIo, + EfiIsaIoWidthUint8, + ConsoleIn->CommandRegisterAddress, + 1, + &Data + ); +} + +/** + Display error message. + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + @param ErrMsg Unicode string of error message + +**/ +VOID +KeyboardError ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + IN CHAR16 *ErrMsg + ) +{ + ConsoleIn->KeyboardErr = TRUE; +} + +/** + Timer event handler: read a series of scancodes from 8042 + and put them into memory scancode buffer. + it read as much scancodes to either fill + the memory buffer or empty the keyboard buffer. + It is registered as running under TPL_NOTIFY + + @param Event The timer event + @param Context A KEYBOARD_CONSOLE_IN_DEV pointer + +**/ +VOID +EFIAPI +KeyboardTimerHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) + +{ + UINT8 Data; + EFI_TPL OldTpl; + KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; + + ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context; + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) { + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return ; + } + + // + // To let KB driver support Hot plug, here should skip the 'resend' command for the case that + // KB is not connected to system. If KB is not connected to system, driver will find there's something + // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since + // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected. + // Just skip the 'resend' process simply. + // + + while ((KeyReadStatusRegister (ConsoleIn) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) == + KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA + ) { + // + // Read one byte of the scan code and store it into the memory buffer + // + Data = KeyReadDataRegister (ConsoleIn); + PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data); + } + KeyGetchar (ConsoleIn); + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); +} + +/** + Read key value . + + @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + @param Data - Pointer to outof buffer for keeping key value + + @retval EFI_TIMEOUT Status resigter time out + @retval EFI_SUCCESS Success to read keyboard + +**/ +EFI_STATUS +KeyboardRead ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + OUT UINT8 *Data + ) + +{ + UINT32 TimeOut; + UINT32 RegFilled; + + TimeOut = 0; + RegFilled = 0; + + // + // wait till output buffer full then perform the read + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if (KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) { + RegFilled = 1; + *Data = KeyReadDataRegister (ConsoleIn); + break; + } + + MicroSecondDelay (30); + } + + if (RegFilled == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + write key to keyboard + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + @param Data value wanted to be written + + @retval EFI_TIMEOUT The input buffer register is full for putting new value util timeout + @retval EFI_SUCCESS The new value is sucess put into input buffer register. + +**/ +EFI_STATUS +KeyboardWrite ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + IN UINT8 Data + ) +{ + UINT32 TimeOut; + UINT32 RegEmptied; + + TimeOut = 0; + RegEmptied = 0; + + // + // wait for input buffer empty + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) { + RegEmptied = 1; + break; + } + + MicroSecondDelay (30); + } + + if (RegEmptied == 0) { + return EFI_TIMEOUT; + } + // + // Write it + // + KeyWriteDataRegister (ConsoleIn, Data); + + return EFI_SUCCESS; +} + +/** + Issue keyboard command. + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + @param Data The buff holding the command + + @retval EFI_TIMEOUT Keyboard is not ready to issuing + @retval EFI_SUCCESS Success to issue keyboard command + +**/ +EFI_STATUS +KeyboardCommand ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + IN UINT8 Data + ) +{ + UINT32 TimeOut; + UINT32 RegEmptied; + + TimeOut = 0; + RegEmptied = 0; + + // + // Wait For Input Buffer Empty + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) { + RegEmptied = 1; + break; + } + + MicroSecondDelay (30); + } + + if (RegEmptied == 0) { + return EFI_TIMEOUT; + } + // + // issue the command + // + KeyWriteCommandRegister (ConsoleIn, Data); + + // + // Wait For Input Buffer Empty again + // + RegEmptied = 0; + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) { + RegEmptied = 1; + break; + } + + MicroSecondDelay (30); + } + + if (RegEmptied == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + wait for a specific value to be presented on + 8042 Data register by keyboard and then read it, + used in keyboard commands ack + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + @param Value the value wanted to be waited. + + @retval EFI_TIMEOUT Fail to get specific value in given time + @retval EFI_SUCCESS Success to get specific value in given time. + +**/ +EFI_STATUS +KeyboardWaitForValue ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + IN UINT8 Value + ) +{ + UINT8 Data; + UINT32 TimeOut; + UINT32 SumTimeOut; + UINT32 GotIt; + + GotIt = 0; + TimeOut = 0; + SumTimeOut = 0; + + // + // Make sure the initial value of 'Data' is different from 'Value' + // + Data = 0; + if (Data == Value) { + Data = 1; + } + // + // Read from 8042 (multiple times if needed) + // until the expected value appears + // use SumTimeOut to control the iteration + // + while (1) { + // + // Perform a read + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if (KeyReadStatusRegister (ConsoleIn) & 0x01) { + Data = KeyReadDataRegister (ConsoleIn); + break; + } + + MicroSecondDelay (30); + } + + SumTimeOut += TimeOut; + + if (Data == Value) { + GotIt = 1; + break; + } + + if (SumTimeOut >= mWaitForValueTimeOut) { + break; + } + } + // + // Check results + // + if (GotIt == 1) { + return EFI_SUCCESS; + } else { + return EFI_TIMEOUT; + } + +} + +/** + Show keyboard status lights according to + indicators in ConsoleIn. + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + + @return status of updating keyboard register + +**/ +EFI_STATUS +UpdateStatusLights ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ) +{ + EFI_STATUS Status; + UINT8 Command; + + // + // Send keyboard command + // + Status = KeyboardWrite (ConsoleIn, 0xed); + if (EFI_ERROR (Status)) { + return Status; + } + + KeyboardWaitForValue (ConsoleIn, 0xfa); + + // + // Light configuration + // + Command = 0; + if (ConsoleIn->CapsLock) { + Command |= 4; + } + + if (ConsoleIn->NumLock) { + Command |= 2; + } + + if (ConsoleIn->ScrollLock) { + Command |= 1; + } + + Status = KeyboardWrite (ConsoleIn, Command); + + if (EFI_ERROR (Status)) { + return Status; + } + + KeyboardWaitForValue (ConsoleIn, 0xfa); + return Status; +} + +/** + Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec. + + The function is always called in TPL_NOTIFY. + + @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer + +**/ +VOID +KeyGetchar ( + IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ) +{ + EFI_STATUS Status; + UINT16 ScanCode; + BOOLEAN Extend0; + BOOLEAN Extend1; + UINTN Index; + EFI_KEY_DATA KeyData; + LIST_ENTRY *Link; + KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + // + // 3 bytes most + // + UINT8 ScancodeArr[3]; + UINT32 ScancodeArrPos; + + // + // Check if there are enough bytes of scancode representing a single key + // available in the buffer + // + while (TRUE) { + Extend0 = FALSE; + Extend1 = FALSE; + ScancodeArrPos = 0; + Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr); + if (EFI_ERROR (Status)) { + return ; + } + + if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) { + // + // E0 to look ahead 2 bytes + // + Extend0 = TRUE; + ScancodeArrPos = 1; + Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr); + if (EFI_ERROR (Status)) { + return ; + } + } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) { + // + // E1 to look ahead 3 bytes + // + Extend1 = TRUE; + ScancodeArrPos = 2; + Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr); + if (EFI_ERROR (Status)) { + return ; + } + } + // + // if we reach this position, scancodes for a key is in buffer now,pop them + // + Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr); + ASSERT_EFI_ERROR (Status); + + // + // store the last available byte, this byte of scancode will be checked + // + ScanCode = ScancodeArr[ScancodeArrPos]; + + if (!Extend1) { + // + // Check for special keys and update the driver state. + // + switch (ScanCode) { + + case SCANCODE_CTRL_MAKE: + if (Extend0) { + ConsoleIn->RightCtrl = TRUE; + } else { + ConsoleIn->LeftCtrl = TRUE; + } + break; + case SCANCODE_CTRL_BREAK: + if (Extend0) { + ConsoleIn->RightCtrl = FALSE; + } else { + ConsoleIn->LeftCtrl = FALSE; + } + break; + + case SCANCODE_ALT_MAKE: + if (Extend0) { + ConsoleIn->RightAlt = TRUE; + } else { + ConsoleIn->LeftAlt = TRUE; + } + break; + case SCANCODE_ALT_BREAK: + if (Extend0) { + ConsoleIn->RightAlt = FALSE; + } else { + ConsoleIn->LeftAlt = FALSE; + } + break; + + case SCANCODE_LEFT_SHIFT_MAKE: + // + // To avoid recognize PRNT_SCRN key as a L_SHIFT key + // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code. + // If it the second byte of the PRNT_ScRN skip it. + // + if (!Extend0) { + ConsoleIn->LeftShift = TRUE; + break; + } + continue; + + case SCANCODE_LEFT_SHIFT_BREAK: + if (!Extend0) { + ConsoleIn->LeftShift = FALSE; + } + break; + + case SCANCODE_RIGHT_SHIFT_MAKE: + ConsoleIn->RightShift = TRUE; + break; + case SCANCODE_RIGHT_SHIFT_BREAK: + ConsoleIn->RightShift = FALSE; + break; + + case SCANCODE_LEFT_LOGO_MAKE: + ConsoleIn->LeftLogo = TRUE; + break; + case SCANCODE_LEFT_LOGO_BREAK: + ConsoleIn->LeftLogo = FALSE; + break; + + case SCANCODE_RIGHT_LOGO_MAKE: + ConsoleIn->RightLogo = TRUE; + break; + case SCANCODE_RIGHT_LOGO_BREAK: + ConsoleIn->RightLogo = FALSE; + break; + + case SCANCODE_MENU_MAKE: + ConsoleIn->Menu = TRUE; + break; + case SCANCODE_MENU_BREAK: + ConsoleIn->Menu = FALSE; + break; + + case SCANCODE_SYS_REQ_MAKE: + if (Extend0) { + ConsoleIn->SysReq = TRUE; + } + break; + case SCANCODE_SYS_REQ_BREAK: + if (Extend0) { + ConsoleIn->SysReq = FALSE; + } + break; + + case SCANCODE_SYS_REQ_MAKE_WITH_ALT: + ConsoleIn->SysReq = TRUE; + break; + case SCANCODE_SYS_REQ_BREAK_WITH_ALT: + ConsoleIn->SysReq = FALSE; + break; + + case SCANCODE_CAPS_LOCK_MAKE: + ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock; + UpdateStatusLights (ConsoleIn); + break; + case SCANCODE_NUM_LOCK_MAKE: + ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock; + UpdateStatusLights (ConsoleIn); + break; + case SCANCODE_SCROLL_LOCK_MAKE: + if (!Extend0) { + ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock; + UpdateStatusLights (ConsoleIn); + } + break; + } + } + + // + // If this is above the valid range, ignore it + // + if (ScanCode >= SCANCODE_MAX_MAKE) { + continue; + } else { + break; + } + } + + // + // Handle Ctrl+Alt+Del hotkey + // + if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) && + (ConsoleIn->LeftAlt || ConsoleIn->RightAlt ) && + ScanCode == SCANCODE_DELETE_MAKE + ) { + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + + // + // Save the Shift/Toggle state + // + KeyData.KeyState.KeyShiftState = (UINT32) (EFI_SHIFT_STATE_VALID + | (ConsoleIn->LeftCtrl ? EFI_LEFT_CONTROL_PRESSED : 0) + | (ConsoleIn->RightCtrl ? EFI_RIGHT_CONTROL_PRESSED : 0) + | (ConsoleIn->LeftAlt ? EFI_LEFT_ALT_PRESSED : 0) + | (ConsoleIn->RightAlt ? EFI_RIGHT_ALT_PRESSED : 0) + | (ConsoleIn->LeftShift ? EFI_LEFT_SHIFT_PRESSED : 0) + | (ConsoleIn->RightShift ? EFI_RIGHT_SHIFT_PRESSED : 0) + | (ConsoleIn->LeftLogo ? EFI_LEFT_LOGO_PRESSED : 0) + | (ConsoleIn->RightLogo ? EFI_RIGHT_LOGO_PRESSED : 0) + | (ConsoleIn->Menu ? EFI_MENU_KEY_PRESSED : 0) + | (ConsoleIn->SysReq ? EFI_SYS_REQ_PRESSED : 0) + ); + KeyData.KeyState.KeyToggleState = (EFI_KEY_TOGGLE_STATE) (EFI_TOGGLE_STATE_VALID + | (ConsoleIn->CapsLock ? EFI_CAPS_LOCK_ACTIVE : 0) + | (ConsoleIn->NumLock ? EFI_NUM_LOCK_ACTIVE : 0) + | (ConsoleIn->ScrollLock ? EFI_SCROLL_LOCK_ACTIVE : 0) + | (ConsoleIn->IsSupportPartialKey ? EFI_KEY_STATE_EXPOSED : 0) + ); + + KeyData.Key.ScanCode = SCAN_NULL; + KeyData.Key.UnicodeChar = CHAR_NULL; + + // + // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" has E0 prefix + // + if (Extend0 && ScanCode == 0x35) { + KeyData.Key.UnicodeChar = L'/'; + KeyData.Key.ScanCode = SCAN_NULL; + + // + // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix + // + } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) { + KeyData.Key.UnicodeChar = CHAR_NULL; + KeyData.Key.ScanCode = SCAN_PAUSE; + + // + // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL pressed) has E0 prefix + // + } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) { + KeyData.Key.UnicodeChar = CHAR_NULL; + KeyData.Key.ScanCode = SCAN_PAUSE; + + // + // PRNT_SCRN shares the same scancode as that of Key Pad "*" except PRNT_SCRN has E0 prefix + // + } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) { + KeyData.Key.UnicodeChar = CHAR_NULL; + KeyData.Key.ScanCode = SCAN_NULL; + + // + // Except the above special case, all others can be handled by convert table + // + } else { + for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index++) { + if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) { + KeyData.Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode; + KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar; + + if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) && + (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) { + KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar; + // + // Need not return associated shift state if a class of printable characters that + // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F' + // + KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED); + } + // + // alphabetic key is affected by CapsLock State + // + if (ConsoleIn->CapsLock) { + if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { + KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A'); + } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { + KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a'); + } + } + break; + } + } + } + + // + // distinguish numeric key pad keys' 'up symbol' and 'down symbol' + // + if (ScanCode >= 0x47 && ScanCode <= 0x53) { + if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) && !Extend0) { + KeyData.Key.ScanCode = SCAN_NULL; + } else if (ScanCode != 0x4a && ScanCode != 0x4e) { + KeyData.Key.UnicodeChar = CHAR_NULL; + } + } + + // + // If the key can not be converted then just return. + // + if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { + if (!ConsoleIn->IsSupportPartialKey) { + return ; + } + } + + // + // Invoke notification functions if exist + // + for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) { + CurrentNotify = CR ( + Link, + KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { + CurrentNotify->KeyNotificationFn (&KeyData); + } + } + + PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData); +} + +/** + Perform 8042 controller and keyboard Initialization. + If ExtendedVerification is TRUE, do additional test for + the keyboard interface + + @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer + @param ExtendedVerification - indicates a thorough initialization + + @retval EFI_DEVICE_ERROR Fail to init keyboard + @retval EFI_SUCCESS Success to init keyboard +**/ +EFI_STATUS +InitKeyboard ( + IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + UINT8 CommandByte; + EFI_PS2_POLICY_PROTOCOL *Ps2Policy; + UINT32 TryTime; + + Status = EFI_SUCCESS; + mEnableMouseInterface = TRUE; + TryTime = 0; + + // + // Get Ps2 policy to set this + // + gBS->LocateProtocol ( + &gEfiPs2PolicyProtocolGuid, + NULL, + (VOID **) &Ps2Policy + ); + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER, + ConsoleIn->DevicePath + ); + + // + // Perform a read to cleanup the Status Register's + // output buffer full bits within MAX TRY times + // + if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) { + while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) { + Status = KeyboardRead (ConsoleIn, &CommandByte); + TryTime ++; + } + // + // Exceed the max try times. The device may be error. + // + if (TryTime == KEYBOARD_MAX_TRY) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + } + // + // We should disable mouse interface during the initialization process + // since mouse device output could block keyboard device output in the + // 60H port of 8042 controller. + // + // So if we are not initializing 8042 controller for the + // first time, we have to remember the previous mouse interface + // enabling state + // + // Test the system flag in to determine whether this is the first + // time initialization + // + if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) { + if (!PcdGetBool (PcdFastPS2Detection)) { + // + // 8042 controller is already setup (by myself or by mouse driver): + // See whether mouse interface is already enabled + // which determines whether we should enable it later + // + // + // Read the command byte of 8042 controller + // + Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"\n\r"); + goto Done; + } + + Status = KeyboardRead (ConsoleIn, &CommandByte); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"\n\r"); + goto Done; + } + // + // Test the mouse enabling bit + // + if ((CommandByte & 0x20) != 0) { + mEnableMouseInterface = FALSE; + } else { + mEnableMouseInterface = TRUE; + } + } else { + mEnableMouseInterface = FALSE; + } + } else { + // + // 8042 controller is not setup yet: + // 8042 controller selftest; + // Don't enable mouse interface later. + // + // + // Disable keyboard and mouse interfaces + // + if (!PcdGetBool (PcdFastPS2Detection)) { + Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"\n\r"); + goto Done; + } + + Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"\n\r"); + goto Done; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST, + ConsoleIn->DevicePath + ); + // + // 8042 Controller Self Test + // + Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); + goto Done; + } + + Status = KeyboardWaitForValue (ConsoleIn, 0x55); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r"); + goto Done; + } + } + // + // Don't enable mouse interface later + // + mEnableMouseInterface = FALSE; + + } + + if (Ps2Policy != NULL) { + Ps2Policy->Ps2InitHardware (ConsoleIn->Handle); + } + // + // Write 8042 Command Byte, set System Flag + // While at the same time: + // 1. disable mouse interface, + // 2. enable kbd interface, + // 3. enable PC/XT kbd translation mode + // 4. enable mouse and kbd interrupts + // + // ( Command Byte bits: + // 7: Reserved + // 6: PC/XT translation mode + // 5: Disable Auxiliary device interface + // 4: Disable keyboard interface + // 3: Reserved + // 2: System Flag + // 1: Enable Auxiliary device interrupt + // 0: Enable Keyboard interrupt ) + // + Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); + goto Done; + } + + Status = KeyboardWrite (ConsoleIn, 0x67); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); + goto Done; + } + + // + // Clear Memory Scancode Buffer + // + ConsoleIn->ScancodeQueue.Head = 0; + ConsoleIn->ScancodeQueue.Tail = 0; + ConsoleIn->EfiKeyQueue.Head = 0; + ConsoleIn->EfiKeyQueue.Tail = 0; + + // + // Reset the status indicators + // + ConsoleIn->CapsLock = FALSE; + ConsoleIn->NumLock = FALSE; + ConsoleIn->ScrollLock = FALSE; + ConsoleIn->LeftCtrl = FALSE; + ConsoleIn->RightCtrl = FALSE; + ConsoleIn->LeftAlt = FALSE; + ConsoleIn->RightAlt = FALSE; + ConsoleIn->LeftShift = FALSE; + ConsoleIn->RightShift = FALSE; + ConsoleIn->LeftLogo = FALSE; + ConsoleIn->RightLogo = FALSE; + ConsoleIn->Menu = FALSE; + ConsoleIn->SysReq = FALSE; + + ConsoleIn->IsSupportPartialKey = FALSE; + // + // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow, + // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected + // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system, + // and normally during booting an OS, it's skipped. + // + if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) { + // + // Additional verifications for keyboard interface + // + // + // Keyboard Interface Test + // + Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); + goto Done; + } + + Status = KeyboardWaitForValue (ConsoleIn, 0x00); + if (EFI_ERROR (Status)) { + KeyboardError ( + ConsoleIn, + L"Some specific value not aquired from 8042 controller!\n\r" + ); + goto Done; + } + // + // Keyboard reset with a BAT(Basic Assurance Test) + // + Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); + goto Done; + } + + Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); + goto Done; + } + // + // wait for BAT completion code + // + mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT; + + Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r"); + goto Done; + } + + mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT; + + // + // Set Keyboard to use Scan Code Set 2 + // + Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); + goto Done; + } + + Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); + goto Done; + } + + Status = KeyboardWrite (ConsoleIn, 0x02); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r"); + goto Done; + } + + Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); + goto Done; + } + + // + // Clear Keyboard Scancode Buffer + // + Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); + goto Done; + } + + Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); + goto Done; + } + // + if (Ps2Policy != NULL) { + if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) { + ConsoleIn->CapsLock = TRUE; + } + + if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) { + ConsoleIn->NumLock = TRUE; + } + + if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) { + ConsoleIn->ScrollLock = TRUE; + } + } + // + // Update Keyboard Lights + // + Status = UpdateStatusLights (ConsoleIn); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r"); + goto Done; + } + } + // + // At last, we can now enable the mouse interface if appropriate + // +Done: + + if (mEnableMouseInterface) { + // + // Enable mouse interface + // + Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE); + if (EFI_ERROR (Status1)) { + KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); + return EFI_DEVICE_ERROR; + } + } + + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } + +} + +/** + Disable the keyboard interface of the 8042 controller. + + @param ConsoleIn The device instance + + @return status of issuing disable command + +**/ +EFI_STATUS +DisableKeyboard ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ) +{ + EFI_STATUS Status; + + // + // Disable keyboard interface + // + Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE); + if (EFI_ERROR (Status)) { + KeyboardError (ConsoleIn, L"\n\r"); + return EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command + If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device + should not be in system. + + @param[in] ConsoleIn Keyboard Private Data Structure + + @retval TRUE Keyboard in System. + @retval FALSE Keyboard not in System. +**/ +BOOLEAN +EFIAPI +CheckKeyboardConnect ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ) +{ + EFI_STATUS Status; + UINTN WaitForValueTimeOutBcakup; + + // + // enable keyboard itself and wait for its ack + // If can't receive ack, Keyboard should not be connected. + // + if (!PcdGetBool (PcdFastPS2Detection)) { + Status = KeyboardWrite ( + ConsoleIn, + KEYBOARD_KBEN + ); + + if (EFI_ERROR (Status)) { + return FALSE; + } + // + // wait for 1s + // + WaitForValueTimeOutBcakup = mWaitForValueTimeOut; + mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT; + Status = KeyboardWaitForValue ( + ConsoleIn, + KEYBOARD_CMDECHO_ACK + ); + mWaitForValueTimeOut = WaitForValueTimeOutBcakup; + + if (EFI_ERROR (Status)) { + return FALSE; + } + + return TRUE; + } else { + return TRUE; + } +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c new file mode 100644 index 0000000000..0efeb39e0d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c @@ -0,0 +1,683 @@ +/** @file + Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces + provided by Ps2KbdCtrller.c. + +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 "Ps2Keyboard.h" + +/** + Check whether the EFI key buffer is empty. + + @param Queue Pointer to instance of EFI_KEY_QUEUE. + + @retval TRUE The EFI key buffer is empty. + @retval FALSE The EFI key buffer isn't empty. +**/ +BOOLEAN +IsEfikeyBufEmpty ( + IN EFI_KEY_QUEUE *Queue + ) +{ + return (BOOLEAN) (Queue->Head == Queue->Tail); +} + +/** + Read & remove one key data from the EFI key buffer. + + @param Queue Pointer to instance of EFI_KEY_QUEUE. + @param KeyData Receive the key data. + + @retval EFI_SUCCESS The key data is popped successfully. + @retval EFI_NOT_READY There is no key data available. +**/ +EFI_STATUS +PopEfikeyBufHead ( + IN EFI_KEY_QUEUE *Queue, + OUT EFI_KEY_DATA *KeyData OPTIONAL + ) +{ + if (IsEfikeyBufEmpty (Queue)) { + return EFI_NOT_READY; + } + // + // Retrieve and remove the values + // + if (KeyData != NULL) { + CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA)); + } + Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT; + return EFI_SUCCESS; +} + +/** + Push one key data to the EFI key buffer. + + @param Queue Pointer to instance of EFI_KEY_QUEUE. + @param KeyData The key data to push. +**/ +VOID +PushEfikeyBufTail ( + IN EFI_KEY_QUEUE *Queue, + IN EFI_KEY_DATA *KeyData + ) +{ + if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) { + // + // If Queue is full, pop the one from head. + // + PopEfikeyBufHead (Queue, NULL); + } + CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA)); + Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT; +} + +/** + Judge whether is a registed key + + @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; + +} + +/** + 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 ConsoleInDev Ps2 Keyboard private structure + @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 +KeyboardReadKeyStrokeWorker ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev, + OUT EFI_KEY_DATA *KeyData + ) + +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + KeyboardTimerHandler (NULL, ConsoleInDev); + + if (ConsoleInDev->KeyboardErr) { + Status = EFI_DEVICE_ERROR; + } else { + Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData); + } + + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset() + + @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL + @param ExtendedVerification Indicate that the driver may perform a more + exhaustive verification operation of the device during + reset, now this par is ignored in this driver + +**/ +EFI_STATUS +EFIAPI +KeyboardEfiReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; + EFI_TPL OldTpl; + + ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); + if (ConsoleIn->KeyboardErr) { + return EFI_DEVICE_ERROR; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET, + ConsoleIn->DevicePath + ); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Call InitKeyboard to initialize the keyboard + // + Status = InitKeyboard (ConsoleIn, ExtendedVerification); + if (EFI_ERROR (Status)) { + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return EFI_DEVICE_ERROR; + } + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + // + // Report the status If a stuck key was detected + // + if (KeyReadStatusRegister (ConsoleIn) & 0x01) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY, + ConsoleIn->DevicePath + ); + } + // + // Report the status If keyboard is locked + // + if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED, + ConsoleIn->DevicePath + ); + } + + return EFI_SUCCESS; +} + +/** + Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke(). + + @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL + @param Key The output buffer for key value + + @retval EFI_SUCCESS success to read key stroke +**/ +EFI_STATUS +EFIAPI +KeyboardReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; + EFI_KEY_DATA KeyData; + + ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); + + // + // Considering if the partial keystroke is enabled, there maybe a partial + // keystroke in the queue, so here skip the partial keystroke and get the + // next key from the queue + // + while (1) { + // + // If there is no pending key, then return. + // + Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData); + if (EFI_ERROR (Status)) { + return Status; + } + // + // If it is partial keystroke, skip it. + // + if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { + continue; + } + // + // Translate the CTRL-Alpha characters to their corresponding control value + // (ctrl-a = 0x0001 through ctrl-Z = 0x001A) + // + if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { + if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); + } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); + } + } + + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + return EFI_SUCCESS; + } +} + +/** + Event notification function for SIMPLE_TEXT_IN.WaitForKey event + Signal the event if there is key available + + @param Event the event object + @param Context waitting context + +**/ +VOID +EFIAPI +KeyboardWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_TPL OldTpl; + KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; + EFI_KEY_DATA KeyData; + + ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context; + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + KeyboardTimerHandler (NULL, ConsoleIn); + + if (!ConsoleIn->KeyboardErr) { + // + // WaitforKey doesn't suppor the partial key. + // Considering if the partial keystroke is enabled, there maybe a partial + // keystroke in the queue, so here skip the partial keystroke and get the + // next key from the queue + // + while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) { + CopyMem ( + &KeyData, + &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]), + sizeof (EFI_KEY_DATA) + ); + if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { + PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData); + continue; + } + // + // if there is pending value key, signal the event. + // + gBS->SignalEvent (Event); + break; + } + } + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); +} + +/** + Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event + Signal the event if there is key available + + @param Event event object + @param Context waiting context + +**/ +VOID +EFIAPI +KeyboardWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ) + +{ + KeyboardWaitForKey (Event, Context); +} + +/** + 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 +KeyboardEfiResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) + +{ + KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; + + ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); + + return ConsoleInDev->ConIn.Reset ( + &ConsoleInDev->ConIn, + 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 +KeyboardReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ) + +{ + KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); + return KeyboardReadKeyStrokeWorker (ConsoleInDev, 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 +KeyboardSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ) + +{ + EFI_STATUS Status; + KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; + EFI_TPL OldTpl; + + if (KeyToggleState == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + if (ConsoleInDev->KeyboardErr) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + // + // Update the status light + // + ConsoleInDev->ScrollLock = FALSE; + ConsoleInDev->NumLock = FALSE; + ConsoleInDev->CapsLock = FALSE; + ConsoleInDev->IsSupportPartialKey = FALSE; + + if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { + ConsoleInDev->ScrollLock = TRUE; + } + if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) { + ConsoleInDev->NumLock = TRUE; + } + if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { + ConsoleInDev->CapsLock = TRUE; + } + if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) { + ConsoleInDev->IsSupportPartialKey = TRUE; + } + + Status = UpdateStatusLights (ConsoleInDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; + +} + +/** + 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 NotifyHandle or KeyNotificationFunction is NULL. + +**/ +EFI_STATUS +EFIAPI +KeyboardRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ) +{ + EFI_STATUS Status; + KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; + EFI_TPL OldTpl; + LIST_ENTRY *Link; + KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify; + + if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. + // + for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify; + Status = EFI_SUCCESS; + goto Exit; + } + } + } + + // + // Allocate resource to save the notification function + // + NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY)); + if (NewNotify == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); + InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry); + + *NotifyHandle = NewNotify; + Status = EFI_SUCCESS; + +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return Status; + +} + +/** + 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 +KeyboardUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ) +{ + EFI_STATUS Status; + KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; + EFI_TPL OldTpl; + LIST_ENTRY *Link; + KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + + if (NotificationHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (CurrentNotify == NotificationHandle) { + // + // Remove the notification function from NotifyList and free resources + // + RemoveEntryList (&CurrentNotify->NotifyEntry); + + gBS->FreePool (CurrentNotify); + Status = EFI_SUCCESS; + goto Exit; + } + } + + // + // Can not find the specified Notification Handle + // + Status = EFI_INVALID_PARAMETER; +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c new file mode 100644 index 0000000000..c020202349 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c @@ -0,0 +1,642 @@ +/** @file + + PS/2 Keyboard driver. Routines that interacts with callers, + conforming to EFI driver model + +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 "Ps2Keyboard.h" + +// +// Function prototypes +// +/** + Test controller is a keyboard Controller. + + @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL + @param Controller driver's controller + @param RemainingDevicePath children device path + + @retval EFI_UNSUPPORTED controller is not floppy disk + @retval EFI_SUCCESS controller is floppy disk +**/ +EFI_STATUS +EFIAPI +KbdControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Create KEYBOARD_CONSOLE_IN_DEV instance on controller. + + @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL + @param Controller driver controller handle + @param RemainingDevicePath Children's device path + + @retval whether success to create floppy control instance. +**/ +EFI_STATUS +EFIAPI +KbdControllerDriverStart ( + 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 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 +KbdControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + Free the waiting key notify list. + + @param ListHead Pointer to list head + + @retval EFI_INVALID_PARAMETER ListHead is NULL + @retval EFI_SUCCESS Sucess to free NotifyList +**/ +EFI_STATUS +KbdFreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ); + +// +// DriverBinding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = { + KbdControllerDriverSupported, + KbdControllerDriverStart, + KbdControllerDriverStop, + 0xa, + NULL, + NULL +}; + +/** + Test controller is a keyboard Controller. + + @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL + @param Controller driver's controller + @param RemainingDevicePath children device path + + @retval EFI_UNSUPPORTED controller is not floppy disk + @retval EFI_SUCCESS controller is floppy disk +**/ +EFI_STATUS +EFIAPI +KbdControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_ISA_IO_PROTOCOL *IsaIo; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Use the ISA I/O Protocol to see if Controller is the Keyboard controller + // + if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) { + Status = EFI_UNSUPPORTED; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Create KEYBOARD_CONSOLE_IN_DEV instance on controller. + + @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL + @param Controller driver controller handle + @param RemainingDevicePath Children's device path + + @retval whether success to create floppy control instance. +**/ +EFI_STATUS +EFIAPI +KbdControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + EFI_ISA_IO_PROTOCOL *IsaIo; + KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; + UINT8 Data; + EFI_STATUS_CODE_VALUE StatusCode; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + + StatusCode = 0; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Report that the keyboard is being enabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE, + ParentDevicePath + ); + + // + // Get the ISA I/O Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_INVALID_PARAMETER; + } + // + // Allocate private data + // + ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV)); + if (ConsoleIn == NULL) { + Status = EFI_OUT_OF_RESOURCES; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; + goto ErrorExit; + } + // + // Setup the device instance + // + ConsoleIn->Signature = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE; + ConsoleIn->Handle = Controller; + (ConsoleIn->ConIn).Reset = KeyboardEfiReset; + (ConsoleIn->ConIn).ReadKeyStroke = KeyboardReadKeyStroke; + ConsoleIn->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER; + ConsoleIn->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER; + ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER; + ConsoleIn->IsaIo = IsaIo; + ConsoleIn->DevicePath = ParentDevicePath; + + ConsoleIn->ConInEx.Reset = KeyboardEfiResetEx; + ConsoleIn->ConInEx.ReadKeyStrokeEx = KeyboardReadKeyStrokeEx; + ConsoleIn->ConInEx.SetState = KeyboardSetState; + ConsoleIn->ConInEx.RegisterKeyNotify = KeyboardRegisterKeyNotify; + ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify; + + InitializeListHead (&ConsoleIn->NotifyList); + + // + // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. + // When KBC decode (IO port 0x60/0x64 decode) is not enabled, + // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS. + // So instead we read status register to detect after read if KBC decode is enabled. + // + + // + // Return code is ignored on purpose. + // + if (!PcdGetBool (PcdFastPS2Detection)) { + KeyboardRead (ConsoleIn, &Data); + if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) { + // + // If nobody decodes KBC I/O port, it will read back as 0xFF. + // Check the Time-Out and Parity bit to see if it has an active KBC in system + // + Status = EFI_DEVICE_ERROR; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; + goto ErrorExit; + } + } + + // + // Setup the WaitForKey event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + KeyboardWaitForKey, + ConsoleIn, + &((ConsoleIn->ConIn).WaitForKey) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; + goto ErrorExit; + } + // + // Setup the WaitForKeyEx event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + KeyboardWaitForKeyEx, + ConsoleIn, + &(ConsoleIn->ConInEx.WaitForKeyEx) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; + goto ErrorExit; + } + // Setup a periodic timer, used for reading keystrokes at a fixed interval + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + KeyboardTimerHandler, + ConsoleIn, + &ConsoleIn->TimerEvent + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; + goto ErrorExit; + } + + Status = gBS->SetTimer ( + ConsoleIn->TimerEvent, + TimerPeriodic, + KEYBOARD_TIMER_INTERVAL + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; + goto ErrorExit; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT, + ParentDevicePath + ); + + // + // Reset the keyboard device + // + Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification)); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; + goto ErrorExit; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED, + ParentDevicePath + ); + + ConsoleIn->ControllerNameTable = NULL; + AddUnicodeString2 ( + "eng", + gPs2KeyboardComponentName.SupportedLanguages, + &ConsoleIn->ControllerNameTable, + L"PS/2 Keyboard Device", + TRUE + ); + AddUnicodeString2 ( + "en", + gPs2KeyboardComponentName2.SupportedLanguages, + &ConsoleIn->ControllerNameTable, + L"PS/2 Keyboard Device", + FALSE + ); + + + // + // Install protocol interfaces for the keyboard device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextInProtocolGuid, + &ConsoleIn->ConIn, + &gEfiSimpleTextInputExProtocolGuid, + &ConsoleIn->ConInEx, + NULL + ); + if (EFI_ERROR (Status)) { + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; + goto ErrorExit; + } + + return Status; + +ErrorExit: + // + // Report error code + // + if (StatusCode != 0) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + StatusCode, + ParentDevicePath + ); + } + + if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) { + gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey); + } + + if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) { + gBS->CloseEvent (ConsoleIn->TimerEvent); + } + if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) { + gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); + } + KbdFreeNotifyList (&ConsoleIn->NotifyList); + if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) { + FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); + } + // + // Since there will be no timer handler for keyboard input any more, + // exhaust input data just in case there is still keyboard data left + // + if (ConsoleIn != NULL) { + Status1 = EFI_SUCCESS; + while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) { + Status1 = KeyboardRead (ConsoleIn, &Data);; + } + } + + if (ConsoleIn != NULL) { + gBS->FreePool (ConsoleIn); + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param This Protocol instance pointer. + @param 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 +KbdControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; + UINT8 Data; + + // + // Disable Keyboard + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &ConIn, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextInputExProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn); + + // + // Report that the keyboard is being disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE, + ConsoleIn->DevicePath + ); + + if (ConsoleIn->TimerEvent != NULL) { + gBS->CloseEvent (ConsoleIn->TimerEvent); + ConsoleIn->TimerEvent = NULL; + } + + // + // Since there will be no timer handler for keyboard input any more, + // exhaust input data just in case there is still keyboard data left + // + Status = EFI_SUCCESS; + while (!EFI_ERROR (Status)) { + Status = KeyboardRead (ConsoleIn, &Data);; + } + // + // Uninstall the SimpleTextIn and SimpleTextInEx protocols + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleTextInProtocolGuid, + &ConsoleIn->ConIn, + &gEfiSimpleTextInputExProtocolGuid, + &ConsoleIn->ConInEx, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Free other resources + // + if ((ConsoleIn->ConIn).WaitForKey != NULL) { + gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey); + (ConsoleIn->ConIn).WaitForKey = NULL; + } + if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) { + gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); + ConsoleIn->ConInEx.WaitForKeyEx = NULL; + } + KbdFreeNotifyList (&ConsoleIn->NotifyList); + FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); + gBS->FreePool (ConsoleIn); + + return EFI_SUCCESS; +} + +/** + Free the waiting key notify list. + + @param ListHead Pointer to list head + + @retval EFI_INVALID_PARAMETER ListHead is NULL + @retval EFI_SUCCESS Sucess to free NotifyList +**/ +EFI_STATUS +KbdFreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ) +{ + KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode; + + if (ListHead == NULL) { + return EFI_INVALID_PARAMETER; + } + while (!IsListEmpty (ListHead)) { + NotifyNode = CR ( + ListHead->ForwardLink, + KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + RemoveEntryList (ListHead->ForwardLink); + gBS->FreePool (NotifyNode); + } + + return EFI_SUCCESS; +} + +/** + The module Entry Point for module Ps2Keyboard. + + @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 +InitializePs2Keyboard( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gKeyboardControllerDriver, + ImageHandle, + &gPs2KeyboardComponentName, + &gPs2KeyboardComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h new file mode 100644 index 0000000000..2023905538 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h @@ -0,0 +1,550 @@ +/** @file + PS/2 keyboard driver header file + +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 _PS2KEYBOARD_H_ +#define _PS2KEYBOARD_H_ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver; +extern EFI_COMPONENT_NAME_PROTOCOL gPs2KeyboardComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gPs2KeyboardComponentName2; + +// +// Driver Private Data +// +#define KEYBOARD_CONSOLE_IN_DEV_SIGNATURE SIGNATURE_32 ('k', 'k', 'e', 'y') +#define KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('k', 'c', 'e', 'n') + +typedef struct _KEYBOARD_CONSOLE_IN_EX_NOTIFY { + UINTN Signature; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + LIST_ENTRY NotifyEntry; +} KEYBOARD_CONSOLE_IN_EX_NOTIFY; + +#define KEYBOARD_SCAN_CODE_MAX_COUNT 32 +typedef struct { + UINT8 Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT]; + UINTN Head; + UINTN Tail; +} SCAN_CODE_QUEUE; + +#define KEYBOARD_EFI_KEY_MAX_COUNT 256 +typedef struct { + EFI_KEY_DATA Buffer[KEYBOARD_EFI_KEY_MAX_COUNT]; + UINTN Head; + UINTN Tail; +} EFI_KEY_QUEUE; + +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL ConIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL ConInEx; + EFI_ISA_IO_PROTOCOL *IsaIo; + + EFI_EVENT TimerEvent; + + UINT32 DataRegisterAddress; + UINT32 StatusRegisterAddress; + UINT32 CommandRegisterAddress; + + BOOLEAN LeftCtrl; + BOOLEAN RightCtrl; + BOOLEAN LeftAlt; + BOOLEAN RightAlt; + BOOLEAN LeftShift; + BOOLEAN RightShift; + BOOLEAN LeftLogo; + BOOLEAN RightLogo; + BOOLEAN Menu; + BOOLEAN SysReq; + + BOOLEAN CapsLock; + BOOLEAN NumLock; + BOOLEAN ScrollLock; + + BOOLEAN IsSupportPartialKey; + // + // Queue storing key scancodes + // + SCAN_CODE_QUEUE ScancodeQueue; + EFI_KEY_QUEUE EfiKeyQueue; + + // + // Error state + // + BOOLEAN KeyboardErr; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + // + // Notification Function List + // + LIST_ENTRY NotifyList; +} KEYBOARD_CONSOLE_IN_DEV; + +#define KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) CR (a, KEYBOARD_CONSOLE_IN_DEV, ConIn, KEYBOARD_CONSOLE_IN_DEV_SIGNATURE) +#define TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) \ + CR (a, \ + KEYBOARD_CONSOLE_IN_DEV, \ + ConInEx, \ + KEYBOARD_CONSOLE_IN_DEV_SIGNATURE \ + ) + +#define TABLE_END 0x0 + +// +// Driver entry point +// +/** + The user Entry Point for module Ps2Keyboard. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InstallPs2KeyboardDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#define KEYBOARD_8042_DATA_REGISTER 0x60 +#define KEYBOARD_8042_STATUS_REGISTER 0x64 +#define KEYBOARD_8042_COMMAND_REGISTER 0x64 + +#define KEYBOARD_KBEN 0xF4 +#define KEYBOARD_CMDECHO_ACK 0xFA + +#define KEYBOARD_MAX_TRY 256 // 256 +#define KEYBOARD_TIMEOUT 65536 // 0.07s +#define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s +#define KEYBOARD_BAT_TIMEOUT 4000000 // 4s +#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s +#define SCANCODE_EXTENDED0 0xE0 +#define SCANCODE_EXTENDED1 0xE1 +#define SCANCODE_CTRL_MAKE 0x1D +#define SCANCODE_CTRL_BREAK 0x9D +#define SCANCODE_ALT_MAKE 0x38 +#define SCANCODE_ALT_BREAK 0xB8 +#define SCANCODE_LEFT_SHIFT_MAKE 0x2A +#define SCANCODE_LEFT_SHIFT_BREAK 0xAA +#define SCANCODE_RIGHT_SHIFT_MAKE 0x36 +#define SCANCODE_RIGHT_SHIFT_BREAK 0xB6 +#define SCANCODE_CAPS_LOCK_MAKE 0x3A +#define SCANCODE_NUM_LOCK_MAKE 0x45 +#define SCANCODE_SCROLL_LOCK_MAKE 0x46 +#define SCANCODE_DELETE_MAKE 0x53 +#define SCANCODE_LEFT_LOGO_MAKE 0x5B //GUI key defined in Keyboard scan code +#define SCANCODE_LEFT_LOGO_BREAK 0xDB +#define SCANCODE_RIGHT_LOGO_MAKE 0x5C +#define SCANCODE_RIGHT_LOGO_BREAK 0xDC +#define SCANCODE_MENU_MAKE 0x5D //APPS key defined in Keyboard scan code +#define SCANCODE_MENU_BREAK 0xDD +#define SCANCODE_SYS_REQ_MAKE 0x37 +#define SCANCODE_SYS_REQ_BREAK 0xB7 +#define SCANCODE_SYS_REQ_MAKE_WITH_ALT 0x54 +#define SCANCODE_SYS_REQ_BREAK_WITH_ALT 0xD4 + +#define SCANCODE_MAX_MAKE 0x60 + + +#define KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA BIT0 ///< 0 - Output register has no data; 1 - Output register has data +#define KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA BIT1 ///< 0 - Input register has no data; 1 - Input register has data +#define KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG BIT2 ///< Set to 0 after power on reset +#define KEYBOARD_STATUS_REGISTER_INPUT_DATA_TYPE BIT3 ///< 0 - Data in input register is data; 1 - Data in input register is command +#define KEYBOARD_STATUS_REGISTER_ENABLE_FLAG BIT4 ///< 0 - Keyboard is disable; 1 - Keyboard is enable +#define KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT BIT5 ///< 0 - Transmit is complete without timeout; 1 - Transmit is timeout without complete +#define KEYBOARD_STATUS_REGISTER_RECEIVE_TIMEOUT BIT6 ///< 0 - Receive is complete without timeout; 1 - Receive is timeout without complete +#define KEYBOARD_STATUS_REGISTER_PARITY BIT7 ///< 0 - Odd parity; 1 - Even parity + +#define KEYBOARD_8042_COMMAND_READ 0x20 +#define KEYBOARD_8042_COMMAND_WRITE 0x60 +#define KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE 0xA7 +#define KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE 0xA8 +#define KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST 0xAA +#define KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST 0xAB +#define KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE 0xAD + +#define KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA 0xF4 +#define KEYBOARD_8048_COMMAND_RESET 0xFF +#define KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET 0xF0 + +#define KEYBOARD_8048_RETURN_8042_BAT_SUCCESS 0xAA +#define KEYBOARD_8048_RETURN_8042_BAT_ERROR 0xFC +#define KEYBOARD_8048_RETURN_8042_ACK 0xFA + + +// +// Keyboard Controller Status +// +#define KBC_PARE 0x80 // Parity Error +#define KBC_TIM 0x40 // General Time Out + +// +// Other functions that are used among .c files +// +/** + Show keyboard status lights according to + indicators in ConsoleIn. + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + + @return status + +**/ +EFI_STATUS +UpdateStatusLights ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ); + +/** + write key to keyboard. + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + @param Data value wanted to be written + + @retval EFI_TIMEOUT - GC_TODO: Add description for return value + @retval EFI_SUCCESS - GC_TODO: Add description for return value + +**/ +EFI_STATUS +KeyboardRead ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + OUT UINT8 *Data + ); + +/** + Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec. + + The function is always called in TPL_NOTIFY. + + @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer + +**/ +VOID +KeyGetchar ( + IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ); + +/** + Perform 8042 controller and keyboard Initialization. + If ExtendedVerification is TRUE, do additional test for + the keyboard interface + + @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer + @param ExtendedVerification - indicates a thorough initialization + + @retval EFI_DEVICE_ERROR Fail to init keyboard + @retval EFI_SUCCESS Success to init keyboard +**/ +EFI_STATUS +InitKeyboard ( + IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, + IN BOOLEAN ExtendedVerification + ); + +/** + Disable the keyboard interface of the 8042 controller. + + @param ConsoleIn - the device instance + + @return status of issuing disable command + +**/ +EFI_STATUS +DisableKeyboard ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ); + +/** + Timer event handler: read a series of scancodes from 8042 + and put them into memory scancode buffer. + it read as much scancodes to either fill + the memory buffer or empty the keyboard buffer. + It is registered as running under TPL_NOTIFY + + @param Event - The timer event + @param Context - A KEYBOARD_CONSOLE_IN_DEV pointer + +**/ +VOID +EFIAPI +KeyboardTimerHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + logic reset keyboard + Implement SIMPLE_TEXT_IN.Reset() + Perform 8042 controller and keyboard initialization + + @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL + @param ExtendedVerification Indicate that the driver may perform a more + exhaustive verification operation of the device during + reset, now this par is ignored in this driver + +**/ +EFI_STATUS +EFIAPI +KeyboardEfiReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Implement SIMPLE_TEXT_IN.ReadKeyStroke(). + Retrieve key values for driver user. + + @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL + @param Key The output buffer for key value + + @retval EFI_SUCCESS success to read key stroke +**/ +EFI_STATUS +EFIAPI +KeyboardReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +/** + Event notification function for SIMPLE_TEXT_IN.WaitForKey event + Signal the event if there is key available + + @param Event the event object + @param Context waitting context + +**/ +VOID +EFIAPI +KeyboardWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Read status register. + + @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + + @return value in status register + +**/ +UINT8 +KeyReadStatusRegister ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ); + +/** + Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command + If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device + should not be in system. + + @param[in] ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV + + @retval TRUE Keyboard in System. + @retval FALSE Keyboard not in System. +**/ +BOOLEAN +EFIAPI +CheckKeyboardConnect ( + IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn + ); + +/** + Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event + Signal the event if there is key available + + @param Event event object + @param Context waiting context + +**/ +VOID +EFIAPI +KeyboardWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// 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 +KeyboardEfiResetEx ( + 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 +KeyboardReadKeyStrokeEx ( + 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 +KeyboardSetState ( + 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 NotifyHandle is NULL. + +**/ +EFI_STATUS +EFIAPI +KeyboardRegisterKeyNotify ( + 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 +KeyboardUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ); + +/** + Push one key data to the EFI key buffer. + + @param Queue Pointer to instance of EFI_KEY_QUEUE. + @param KeyData The key data to push. +**/ +VOID +PushEfikeyBufTail ( + IN EFI_KEY_QUEUE *Queue, + IN EFI_KEY_DATA *KeyData + ); + +/** + Judge whether is a registed key + + @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 + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni new file mode 100644 index 0000000000..0410dd216a Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni new file mode 100644 index 0000000000..155d2515f8 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf new file mode 100644 index 0000000000..13c1ea9091 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf @@ -0,0 +1,85 @@ +## @file +# Ps2 Keyboard Driver. +# +# Ps2 Keyboard Driver for UEFI. The keyboard type implemented follows IBM +# compatible PS2 protocol using Scan Code Set 1. +# +# 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 +# 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 = Ps2KeyboardDxe + MODULE_UNI_FILE = Ps2KeyboardDxe.uni + FILE_GUID = 3DC82376-637B-40a6-A8FC-A565417F2C38 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializePs2Keyboard + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# DRIVER_BINDING = gKeyboardControllerDriver; +# COMPONENT_NAME = gPs2KeyboardComponentName; +# COMPONENT_NAME2 = gPs2KeyboardComponentName2; +# + +[Sources] + ComponentName.c + Ps2Keyboard.h + Ps2KbdCtrller.c + Ps2KbdTextIn.c + Ps2Keyboard.c + + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiRuntimeServicesTableLib + DebugLib + ReportStatusCodeLib + UefiBootServicesTableLib + UefiLib + UefiDriverEntryPoint + BaseLib + BaseMemoryLib + TimerLib + PcdLib + +[Protocols] + gEfiSimpleTextInProtocolGuid ## BY_START + gEfiSimpleTextInputExProtocolGuid ## BY_START + gEfiPs2PolicyProtocolGuid ## SOMETIMES_CONSUMES + gEfiIsaIoProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## TO_START + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification ## CONSUMES + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection ## SOMETIMES_CONSUMES + +# +# [Event] +# +# ## +# # Timer event used to read key strokes at a regular interval. +# # +# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES +# + +[UserExtensions.TianoCore."ExtraFiles"] + Ps2KeyboardDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c new file mode 100644 index 0000000000..fb4a75348c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c @@ -0,0 +1,923 @@ +/** @file + PS2 Mouse Communication Interface. + +Copyright (c) 2006 - 2007, Intel 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 "Ps2MouseAbsolutePointer.h" +#include "CommPs2.h" + +UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 }; + +UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 }; + +/** + Issue self test command via IsaIo interface. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return EFI_SUCCESS Success to do keyboard self testing. + @return others Fail to do keyboard self testing. +**/ +EFI_STATUS +KbcSelfTest ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Keyboard controller self test + // + Status = Out8042Command (IsaIo, SELF_TEST); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Read return code + // + Status = In8042Data (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Data != 0x55) { + return EFI_DEVICE_ERROR; + } + // + // Set system flag + // + Status = Out8042Command (IsaIo, READ_CMD_BYTE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = In8042Data (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Out8042Command (IsaIo, WRITE_CMD_BYTE); + if (EFI_ERROR (Status)) { + return Status; + } + + Data |= CMD_SYS_FLAG; + Status = Out8042Data (IsaIo, Data); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Issue command to enable keyboard AUX functionality. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcEnableAux ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send 8042 enable mouse command + // + return Out8042Command (IsaIo, ENABLE_AUX); +} + +/** + Issue command to disable keyboard AUX functionality. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcDisableAux ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send 8042 disable mouse command + // + return Out8042Command (IsaIo, DISABLE_AUX); +} + +/** + Issue command to enable keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcEnableKb ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send 8042 enable keyboard command + // + return Out8042Command (IsaIo, ENABLE_KB); +} + +/** + Issue command to disable keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcDisableKb ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send 8042 disable keyboard command + // + return Out8042Command (IsaIo, DISABLE_KB); +} + +/** + Issue command to check keyboard status. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param KeyboardEnable return whether keyboard is enable. + + @return Status of command issuing. +**/ +EFI_STATUS +CheckKbStatus ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + OUT BOOLEAN *KeyboardEnable + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Send command to read KBC command byte + // + Status = Out8042Command (IsaIo, READ_CMD_BYTE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = In8042Data (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check keyboard enable or not + // + if ((Data & CMD_KB_STS) == CMD_KB_DIS) { + *KeyboardEnable = FALSE; + } else { + *KeyboardEnable = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Issue command to reset keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseReset ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + EFI_STATUS Status; + UINT8 Data; + + Status = Out8042AuxCommand (IsaIo, RESET_CMD, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = In8042AuxData (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check BAT Complete Code + // + if (Data != PS2MOUSE_BAT1) { + return EFI_DEVICE_ERROR; + } + + Status = In8042AuxData (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check BAT Complete Code + // + if (Data != PS2MOUSE_BAT2) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Issue command to set mouse's sample rate + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param SampleRate value of sample rate + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetSampleRate ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_SR SampleRate + ) +{ + EFI_STATUS Status; + + // + // Send auxiliary command to set mouse sample rate + // + Status = Out8042AuxCommand (IsaIo, SETSR_CMD, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Out8042AuxData (IsaIo, SampleRateTbl[SampleRate]); + + return Status; +} + +/** + Issue command to set mouse's resolution. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Resolution value of resolution + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetResolution ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_RE Resolution + ) +{ + EFI_STATUS Status; + + // + // Send auxiliary command to set mouse resolution + // + Status = Out8042AuxCommand (IsaIo, SETRE_CMD, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Out8042AuxData (IsaIo, ResolutionTbl[Resolution]); + + return Status; +} + +/** + Issue command to set mouse's scaling. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Scaling value of scaling + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetScaling ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_SF Scaling + ) +{ + UINT8 Command; + + Command = (UINT8) (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD); + + // + // Send auxiliary command to set mouse scaling data + // + return Out8042AuxCommand (IsaIo, Command, FALSE); +} + +/** + Issue command to enable Ps2 mouse. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseEnable ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send auxiliary command to enable mouse + // + return Out8042AuxCommand (IsaIo, ENABLE_CMD, FALSE); +} + +/** + Get mouse packet . Only care first 3 bytes + + @param MouseAbsolutePointerDev Pointer to PS2 Absolute Pointer Simulation Device Private Data Structure + + @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet + @retval EFI_SUCCESS The data packet is gotten successfully. + +**/ +EFI_STATUS +PS2MouseGetPacket ( + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev + ) + +{ + EFI_STATUS Status; + BOOLEAN KeyboardEnable; + UINT8 Packet[PS2_PACKET_LENGTH]; + UINT8 Data; + UINTN Count; + UINTN State; + INT16 RelativeMovementX; + INT16 RelativeMovementY; + BOOLEAN LButton; + BOOLEAN RButton; + + KeyboardEnable = FALSE; + Count = 1; + State = PS2_READ_BYTE_ONE; + + // + // State machine to get mouse packet + // + while (1) { + + switch (State) { + case PS2_READ_BYTE_ONE: + // + // Read mouse first byte data, if failed, immediately return + // + KbcDisableAux (MouseAbsolutePointerDev->IsaIo); + Status = PS2MouseRead (MouseAbsolutePointerDev->IsaIo, &Data, &Count, State); + if (EFI_ERROR (Status)) { + KbcEnableAux (MouseAbsolutePointerDev->IsaIo); + return EFI_NOT_READY; + } + + if (Count != 1) { + KbcEnableAux (MouseAbsolutePointerDev->IsaIo); + return EFI_NOT_READY; + } + + if (IS_PS2_SYNC_BYTE (Data)) { + Packet[0] = Data; + State = PS2_READ_DATA_BYTE; + + CheckKbStatus (MouseAbsolutePointerDev->IsaIo, &KeyboardEnable); + KbcDisableKb (MouseAbsolutePointerDev->IsaIo); + KbcEnableAux (MouseAbsolutePointerDev->IsaIo); + } + break; + + case PS2_READ_DATA_BYTE: + Count = 2; + Status = PS2MouseRead (MouseAbsolutePointerDev->IsaIo, (Packet + 1), &Count, State); + if (EFI_ERROR (Status)) { + if (KeyboardEnable) { + KbcEnableKb (MouseAbsolutePointerDev->IsaIo); + } + + return EFI_NOT_READY; + } + + if (Count != 2) { + if (KeyboardEnable) { + KbcEnableKb (MouseAbsolutePointerDev->IsaIo); + } + + return EFI_NOT_READY; + } + + State = PS2_PROCESS_PACKET; + break; + + case PS2_PROCESS_PACKET: + if (KeyboardEnable) { + KbcEnableKb (MouseAbsolutePointerDev->IsaIo); + } + // + // Decode the packet + // + RelativeMovementX = Packet[1]; + RelativeMovementY = Packet[2]; + // + // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 + // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn + // Byte 1 | 8 bit X Movement + // Byte 2 | 8 bit Y Movement + // + // X sign bit + 8 bit X Movement : 9-bit signed twos complement integer that presents the relative displacement of the device in the X direction since the last data transmission. + // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement. + // + // + // First, Clear X and Y high 8 bits + // + RelativeMovementX = (INT16) (RelativeMovementX & 0xFF); + RelativeMovementY = (INT16) (RelativeMovementY & 0xFF); + // + // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff + // + if ((Packet[0] & 0x10) != 0) { + RelativeMovementX = (INT16) (RelativeMovementX | 0xFF00); + } + if ((Packet[0] & 0x20) != 0) { + RelativeMovementY = (INT16) (RelativeMovementY | 0xFF00); + } + + + RButton = (UINT8) (Packet[0] & 0x2); + LButton = (UINT8) (Packet[0] & 0x1); + + // + // Update mouse state + // + MouseAbsolutePointerDev->State.CurrentX += RelativeMovementX; + MouseAbsolutePointerDev->State.CurrentY -= RelativeMovementY; + MouseAbsolutePointerDev->State.CurrentZ = 0; + MouseAbsolutePointerDev->State.ActiveButtons = (UINT8) (LButton || RButton) & 0x3; + MouseAbsolutePointerDev->StateChanged = TRUE; + + return EFI_SUCCESS; + } + } +} + +/** + Read data via IsaIo protocol with given number. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Buffer Buffer receive data of mouse + @param BufSize The size of buffer + @param State Check input or read data + + @return status of reading mouse data. +**/ +EFI_STATUS +PS2MouseRead ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + OUT VOID *Buffer, + IN OUT UINTN *BufSize, + IN UINTN State + ) +{ + EFI_STATUS Status; + UINTN BytesRead; + + Status = EFI_SUCCESS; + BytesRead = 0; + + if (State == PS2_READ_BYTE_ONE) { + // + // Check input for mouse + // + Status = CheckForInput (IsaIo); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + while (BytesRead < *BufSize) { + + Status = WaitOutputFull (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + break; + } + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Buffer); + + BytesRead++; + Buffer = (UINT8 *) Buffer + 1; + } + // + // Verify the correct number of bytes read + // + if (BytesRead == 0 || BytesRead != *BufSize) { + Status = EFI_NOT_FOUND; + } + + *BufSize = BytesRead; + return Status; +} + +// +// 8042 I/O function +// +/** + I/O work flow of outing 8042 command. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Command I/O command. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042Command ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Command + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Wait keyboard controller input buffer empty + // + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Send command + // + Data = Command; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow of outing 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Data + ) +{ + EFI_STATUS Status; + UINT8 Temp; + // + // Wait keyboard controller input buffer empty + // + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + Temp = Data; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow of in 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ) +{ + UINTN Delay; + UINT8 Temp; + + Delay = TIMEOUT / 50; + + do { + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp); + + // + // Check keyboard controller status bit 0(output buffer status) + // + if ((Temp & KBC_OUTB) == KBC_OUTB) { + break; + } + + gBS->Stall (50); + Delay--; + } while (Delay != 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data); + + return EFI_SUCCESS; +} + +/** + I/O work flow of outing 8042 Aux command. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Command Aux I/O command + @param Resend Whether need resend the Aux command. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042AuxCommand ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Command, + IN BOOLEAN Resend + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Wait keyboard controller input buffer empty + // + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Send write to auxiliary device command + // + Data = WRITE_AUX_DEV; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Send auxiliary device command + // + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command); + + // + // Read return code + // + Status = In8042AuxData (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Data == PS2_ACK) { + // + // Receive mouse acknowledge, command send success + // + return EFI_SUCCESS; + + } else if (Resend) { + // + // Resend fail + // + return EFI_DEVICE_ERROR; + + } else if (Data == PS2_RESEND) { + // + // Resend command + // + Status = Out8042AuxCommand (IsaIo, Command, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + + } else { + // + // Invalid return code + // + return EFI_DEVICE_ERROR; + + } + + return EFI_SUCCESS; +} + +/** + I/O work flow of outing 8042 Aux data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Buffer holding return value + + @retval EFI_SUCCESS Success to excute I/O work flow. + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042AuxData ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Data + ) +{ + EFI_STATUS Status; + UINT8 Temp; + // + // Wait keyboard controller input buffer empty + // + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Send write to auxiliary device command + // + Temp = WRITE_AUX_DEV; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + Temp = Data; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow of in 8042 Aux data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Buffer holding return value. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042AuxData ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ) +{ + EFI_STATUS Status; + + // + // wait for output data + // + Status = WaitOutputFull (IsaIo, BAT_TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data); + + return EFI_SUCCESS; +} + + +/** + Check keyboard controller status, if it is output buffer full and for auxiliary device. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @retval EFI_SUCCESS Keyboard controller is ready + @retval EFI_NOT_READY Keyboard controller is not ready +**/ +EFI_STATUS +CheckForInput ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + UINT8 Data; + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + // + // Check keyboard controller status, if it is output buffer full and for auxiliary device + // + if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow to wait input buffer empty in given time. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Timeout Wating time. + + @retval EFI_TIMEOUT if input is still not empty in given time. + @retval EFI_SUCCESS input is empty. +**/ +EFI_STATUS +WaitInputEmpty ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINTN Timeout + ) +{ + UINTN Delay; + UINT8 Data; + + Delay = Timeout / 50; + + do { + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + // + // Check keyboard controller status bit 1(input buffer status) + // + if ((Data & KBC_INPB) == 0) { + break; + } + + gBS->Stall (50); + Delay--; + } while (Delay != 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow to wait output buffer full in given time. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Timeout given time + + @retval EFI_TIMEOUT output is not full in given time + @retval EFI_SUCCESS output is full in given time. +**/ +EFI_STATUS +WaitOutputFull ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINTN Timeout + ) +{ + UINTN Delay; + UINT8 Data; + + Delay = Timeout / 50; + + do { + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + // + // Check keyboard controller status bit 0(output buffer status) + // & bit5(output buffer for auxiliary device) + // + if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) { + break; + } + + gBS->Stall (50); + Delay--; + } while (Delay != 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h new file mode 100644 index 0000000000..59d7b51d44 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h @@ -0,0 +1,435 @@ +/** @file + Using PS2 Mouse to simulation Absolution Pointer Device. + +Copyright (c) 2006 - 2009, Intel 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 __COMMPS2_H__ +#define __COMMPS2_H__ + +#define PS2_PACKET_LENGTH 3 +#define PS2_SYNC_MASK 0xc +#define PS2_SYNC_BYTE 0x8 + +#define IS_PS2_SYNC_BYTE(byte) ((byte & PS2_SYNC_MASK) == PS2_SYNC_BYTE) + +#define PS2_READ_BYTE_ONE 0 +#define PS2_READ_DATA_BYTE 1 +#define PS2_PROCESS_PACKET 2 + +#define TIMEOUT 50000 +#define BAT_TIMEOUT 500000 + +// +// 8042 I/O Port +// +#define KBC_DATA_PORT 0x60 +#define KBC_CMD_STS_PORT 0x64 + +// +// 8042 Command +// +#define READ_CMD_BYTE 0x20 +#define WRITE_CMD_BYTE 0x60 +#define DISABLE_AUX 0xa7 +#define ENABLE_AUX 0xa8 +#define SELF_TEST 0xaa +#define DISABLE_KB 0xad +#define ENABLE_KB 0xae +#define WRITE_AUX_DEV 0xd4 + +#define CMD_SYS_FLAG 0x04 +#define CMD_KB_STS 0x10 +#define CMD_KB_DIS 0x10 +#define CMD_KB_EN 0x0 + +// +// 8042 Auxiliary Device Command +// +#define SETSF1_CMD 0xe6 +#define SETSF2_CMD 0xe7 +#define SETRE_CMD 0xe8 +#define READ_CMD 0xeb +#define SETRM_CMD 0xf0 +#define SETSR_CMD 0xf3 +#define ENABLE_CMD 0xf4 +#define DISABLE_CMD 0xf5 +#define RESET_CMD 0xff + +// +// return code +// +#define PS2_ACK 0xfa +#define PS2_RESEND 0xfe +#define PS2MOUSE_BAT1 0xaa +#define PS2MOUSE_BAT2 0x0 + +// +// Keyboard Controller Status +// +/// +/// Parity Error +/// +#define KBC_PARE 0x80 +/// +/// General Time Out +/// +#define KBC_TIM 0x40 +/// +/// Output buffer for auxiliary device (PS/2): +/// 0 - Holds keyboard data +/// 1 - Holds data for auxiliary device +/// +#define KBC_AUXB 0x20 +/// +/// Keyboard lock status: +/// 0 - keyboard locked +/// 1 - keyboard free +/// +#define KBC_KEYL 0x10 +/// +/// Command/Data: +/// 0 - data byte written via port 60h +/// 1 - command byte written via port 64h +/// +#define KBC_CD 0x08 +/// +/// System Flag: +/// 0 - power-on reset +/// 1 - self-test successful +/// +#define KBC_SYSF 0x04 +/// +/// Input Buffer Status : +/// 0 - input buffer empty +/// 1 - CPU data in input buffer +/// +#define KBC_INPB 0x02 +/// +/// Output Buffer Status : +/// 0 - output buffer empty +/// 1 - keyboard controller data in output buffer +/// +#define KBC_OUTB 0x01 + +/** + Issue self test command via IsaIo interface. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return EFI_SUCCESS Success to do keyboard self testing. + @return others Fail to do keyboard self testing. +**/ +EFI_STATUS +KbcSelfTest ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to enable keyboard AUX functionality. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcEnableAux ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to disable keyboard AUX functionality. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcDisableAux ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to enable keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcEnableKb ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to disable keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcDisableKb ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to check keyboard status. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param KeyboardEnable return whether keyboard is enable. + + @return Status of command issuing. +**/ +EFI_STATUS +CheckKbStatus ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + OUT BOOLEAN *KeyboardEnable + ); + +/** + Issue command to reset keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseReset ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to set mouse's sample rate + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param SampleRate value of sample rate + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetSampleRate ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_SR SampleRate + ); + +/** + Issue command to set mouse's resolution. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Resolution value of resolution + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetResolution ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_RE Resolution + ); + +/** + Issue command to set mouse's scaling. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Scaling value of scaling + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetScaling ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_SF Scaling + ); + +/** + Issue command to enable Ps2 mouse. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseEnable ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Get mouse packet . Only care first 3 bytes + + @param MouseAbsolutePointerDev Pointer to PS2 Absolute Pointer Simulation Device Private Data Structure + + @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet + @retval EFI_SUCCESS The data packet is gotten successfully. + +**/ +EFI_STATUS +PS2MouseGetPacket ( + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev + ); + +/** + Read data via IsaIo protocol with given number. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Buffer Buffer receive data of mouse + @param BufSize The size of buffer + @param State Check input or read data + + @return status of reading mouse data. +**/ +EFI_STATUS +PS2MouseRead ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + OUT VOID *Buffer, + IN OUT UINTN *BufSize, + IN UINTN State + ); + +// +// 8042 I/O function +// +/** + I/O work flow of outing 8042 command. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Command I/O command. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042Command ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Command + ); + +/** + I/O work flow of in 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ); + +/** + I/O work flow of outing 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Data + ); + +/** + I/O work flow of outing 8042 Aux command. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Command Aux I/O command + @param Resend Whether need resend the Aux command. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042AuxCommand ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Command, + IN BOOLEAN Resend + ); + +/** + I/O work flow of in 8042 Aux data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Buffer holding return value. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042AuxData ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ); + +/** + I/O work flow of outing 8042 Aux data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Buffer holding return value. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042AuxData ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Data + ); + +/** + Check keyboard controller status, if it is output buffer full and for auxiliary device. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @retval EFI_SUCCESS Keyboard controller is ready + @retval EFI_NOT_READY Keyboard controller is not ready +**/ +EFI_STATUS +CheckForInput ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + I/O work flow to wait input buffer empty in given time. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Timeout Wating time. + + @retval EFI_TIMEOUT if input is still not empty in given time. + @retval EFI_SUCCESS input is empty. +**/ +EFI_STATUS +WaitInputEmpty ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINTN Timeout + ); + +/** + I/O work flow to wait output buffer full in given time. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Timeout given time + + @retval EFI_TIMEOUT output is not full in given time + @retval EFI_SUCCESS output is full in given time. +**/ +EFI_STATUS +WaitOutputFull ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINTN Timeout + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c new file mode 100644 index 0000000000..8fbef28985 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c @@ -0,0 +1,241 @@ +/** @file + UEFI Component Name(2) protocol implementation for Ps2 Absolute Pointer Simulation Dxe 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 "Ps2MouseAbsolutePointer.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPs2MouseAbsolutePointerComponentName = { + Ps2MouseAbsolutePointerComponentNameGetDriverName, + Ps2MouseAbsolutePointerComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPs2MouseAbsolutePointerComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ps2MouseAbsolutePointerComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ps2MouseAbsolutePointerComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPs2MouseAbsolutePointerDriverNameTable[] = { + { + "eng;en", + L"faked PS/2 Touchpad Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +Ps2MouseAbsolutePointerComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mPs2MouseAbsolutePointerDriverNameTable, + DriverName, + (BOOLEAN)(This == &gPs2MouseAbsolutePointerComponentName) + ); +} + +/** + 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 +Ps2MouseAbsolutePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol; + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; + EFI_ISA_IO_PROTOCOL *IsaIoProtocol; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + // + // Check Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIoProtocol, + gPS2MouseAbsolutePointerDriver.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiIsaIoProtocolGuid, + gPS2MouseAbsolutePointerDriver.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiAbsolutePointerProtocolGuid, + (VOID **) &AbsolutePointerProtocol, + gPS2MouseAbsolutePointerDriver.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (AbsolutePointerProtocol); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + MouseAbsolutePointerDev->ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gPs2MouseAbsolutePointerComponentName) + ); +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.c new file mode 100644 index 0000000000..7af35bcd11 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.c @@ -0,0 +1,778 @@ +/** @file + A faked PS/2 Absolute Pointer driver. Routines that interacts with callers, + conforming to EFI driver model + +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 "Ps2MouseAbsolutePointer.h" +#include "CommPs2.h" + +// +// DriverBinding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gPS2MouseAbsolutePointerDriver = { + PS2MouseAbsolutePointerDriverSupported, + PS2MouseAbsolutePointerDriverStart, + PS2MouseAbsolutePointerDriverStop, + 0x1, + NULL, + NULL +}; + +/** + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a IsaIo protocol can be supported. + + @param This 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 EFI_ALREADY_STARTED This driver is already running on this device + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +PS2MouseAbsolutePointerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_ISA_IO_PROTOCOL *IsaIo; + + Status = EFI_SUCCESS; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Use the ISA I/O Protocol to see if Controller is the Mouse controller + // + switch (IsaIo->ResourceList->Device.HID) { + case EISA_PNP_ID (0xF03): + // + // Microsoft PS/2 style mouse + // + case EISA_PNP_ID (0xF13): + // + // PS/2 Port for PS/2-style Mice + // + break; + + case EISA_PNP_ID (0x303): + // + // IBM Enhanced (101/102-key, PS/2 mouse support) + // + if (IsaIo->ResourceList->Device.UID == 1) { + break; + } + + default: + Status = EFI_UNSUPPORTED; + break; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Start this driver on ControllerHandle by opening a IsaIo protocol, creating + PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid + finally. + + @param This 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 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 +PS2MouseAbsolutePointerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_STATUS EmptyStatus; + EFI_ISA_IO_PROTOCOL *IsaIo; + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; + UINT8 Data; + EFI_TPL OldTpl; + EFI_STATUS_CODE_VALUE StatusCode; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + + StatusCode = 0; + MouseAbsolutePointerDev = NULL; + IsaIo = NULL; + + // + // Open the device path protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Report that the keyboard is being enabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE, + ParentDevicePath + ); + + // + // Get the ISA I/O Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_INVALID_PARAMETER; + } + // + // Raise TPL to avoid keyboard operation impact + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Allocate private data + // + MouseAbsolutePointerDev = AllocateZeroPool (sizeof (PS2_MOUSE_ABSOLUTE_POINTER_DEV)); + if (MouseAbsolutePointerDev == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Setup the device instance + // + MouseAbsolutePointerDev->Signature = PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE; + MouseAbsolutePointerDev->Handle = Controller; + MouseAbsolutePointerDev->SampleRate = SampleRate20; + MouseAbsolutePointerDev->Resolution = MouseResolution4; + MouseAbsolutePointerDev->Scaling = Scaling1; + MouseAbsolutePointerDev->DataPackageSize = 3; + MouseAbsolutePointerDev->IsaIo = IsaIo; + MouseAbsolutePointerDev->DevicePath = ParentDevicePath; + + // + // Resolution = 4 counts/mm + // + MouseAbsolutePointerDev->Mode.AbsoluteMaxX = 1024; + MouseAbsolutePointerDev->Mode.AbsoluteMinX = 0; + MouseAbsolutePointerDev->Mode.AbsoluteMaxY = 798; + MouseAbsolutePointerDev->Mode.AbsoluteMinY = 0; + MouseAbsolutePointerDev->Mode.AbsoluteMaxZ = 0; + MouseAbsolutePointerDev->Mode.AbsoluteMinZ = 0; + MouseAbsolutePointerDev->Mode.Attributes = 0x03; + + MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset = MouseAbsolutePointerReset; + MouseAbsolutePointerDev->AbsolutePointerProtocol.GetState = MouseAbsolutePointerGetState; + MouseAbsolutePointerDev->AbsolutePointerProtocol.Mode = &(MouseAbsolutePointerDev->Mode); + + // + // Initialize keyboard controller if necessary + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST, + ParentDevicePath + ); + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + if ((Data & KBC_SYSF) != KBC_SYSF) { + Status = KbcSelfTest (IsaIo); + if (EFI_ERROR (Status)) { + StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR; + goto ErrorExit; + } + } + + KbcEnableAux (IsaIo); + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT, + ParentDevicePath + ); + + // + // Reset the mouse + // + Status = MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset ( + &MouseAbsolutePointerDev->AbsolutePointerProtocol, + FeaturePcdGet (PcdPs2MouseExtendedVerification) + ); + if (EFI_ERROR (Status)) { + // + // mouse not connected + // + Status = EFI_SUCCESS; + StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; + goto ErrorExit; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED, + ParentDevicePath + ); + + // + // Setup the WaitForKey event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + MouseAbsolutePointerWaitForInput, + MouseAbsolutePointerDev, + &((MouseAbsolutePointerDev->AbsolutePointerProtocol).WaitForInput) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Setup a periodic timer, used to poll mouse state + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + PollMouseAbsolutePointer, + MouseAbsolutePointerDev, + &MouseAbsolutePointerDev->TimerEvent + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Start timer to poll mouse (100 samples per second) + // + Status = gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerPeriodic, 100000); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + MouseAbsolutePointerDev->ControllerNameTable = NULL; + AddUnicodeString2 ( + "eng", + gPs2MouseAbsolutePointerComponentName.SupportedLanguages, + &MouseAbsolutePointerDev->ControllerNameTable, + L"Faked PS/2 Touchpad Device", + TRUE + ); + AddUnicodeString2 ( + "en", + gPs2MouseAbsolutePointerComponentName2.SupportedLanguages, + &MouseAbsolutePointerDev->ControllerNameTable, + L"Faked PS/2 Touchpad Device", + FALSE + ); + + + // + // Install protocol interfaces for the mouse device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiAbsolutePointerProtocolGuid, + &MouseAbsolutePointerDev->AbsolutePointerProtocol, + NULL + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + gBS->RestoreTPL (OldTpl); + + return Status; + +ErrorExit: + + KbcDisableAux (IsaIo); + + if (StatusCode != 0) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + StatusCode, + ParentDevicePath + ); + } + + if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput != NULL)) { + gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput); + } + + if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->TimerEvent != NULL)) { + gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent); + } + + if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->ControllerNameTable != NULL)) { + FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable); + } + // + // Since there will be no timer handler for mouse input any more, + // exhaust input data just in case there is still mouse data left + // + EmptyStatus = EFI_SUCCESS; + while (!EFI_ERROR (EmptyStatus)) { + EmptyStatus = In8042Data (IsaIo, &Data); + } + + if (MouseAbsolutePointerDev != NULL) { + FreePool (MouseAbsolutePointerDev); + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->RestoreTPL (OldTpl); + + return Status; +} + +/** + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param This 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 +PS2MouseAbsolutePointerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol; + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; + UINT8 Data; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiAbsolutePointerProtocolGuid, + (VOID **) &AbsolutePointerProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (AbsolutePointerProtocol); + + // + // Report that the keyboard is being disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE, + MouseAbsolutePointerDev->DevicePath + ); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiAbsolutePointerProtocolGuid, + &MouseAbsolutePointerDev->AbsolutePointerProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Cancel mouse data polling timer, close timer event + // + gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerCancel, 0); + gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent); + + // + // Since there will be no timer handler for mouse input any more, + // exhaust input data just in case there is still mouse data left + // + Status = EFI_SUCCESS; + while (!EFI_ERROR (Status)) { + Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data); + } + + gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput); + FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable); + FreePool (MouseAbsolutePointerDev); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +/** + Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system. + + @param This - Pointer of simple pointer Protocol. + @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. + + + @retval EFI_SUCCESS - The command byte is written successfully. + @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. + +**/ +EFI_STATUS +EFIAPI +MouseAbsolutePointerReset ( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; + EFI_TPL OldTpl; + BOOLEAN KeyboardEnable; + UINT8 Data; + + MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This); + + // + // Report reset progress code + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET, + MouseAbsolutePointerDev->DevicePath + ); + + KeyboardEnable = FALSE; + + // + // Raise TPL to avoid keyboard operation impact + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + ZeroMem (&MouseAbsolutePointerDev->State, sizeof (EFI_ABSOLUTE_POINTER_STATE)); + MouseAbsolutePointerDev->StateChanged = FALSE; + + // + // Exhaust input data + // + Status = EFI_SUCCESS; + while (!EFI_ERROR (Status)) { + Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data); + } + + CheckKbStatus (MouseAbsolutePointerDev->IsaIo, &KeyboardEnable); + + KbcDisableKb (MouseAbsolutePointerDev->IsaIo); + + MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + // + // if there's data block on KBC data port, read it out + // + if ((Data & KBC_OUTB) == KBC_OUTB) { + MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data); + } + + Status = EFI_SUCCESS; + // + // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system. + // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is + // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling + // + if (ExtendedVerification && CheckMouseAbsolutePointerConnect (MouseAbsolutePointerDev)) { + // + // Send mouse reset command and set mouse default configure + // + Status = PS2MouseReset (MouseAbsolutePointerDev->IsaIo); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = PS2MouseSetSampleRate (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->SampleRate); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = PS2MouseSetResolution (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Resolution); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = PS2MouseSetScaling (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Scaling); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + } +Exit: + gBS->RestoreTPL (OldTpl); + + if (KeyboardEnable) { + KbcEnableKb (MouseAbsolutePointerDev->IsaIo); + } + + return Status; +} + +/** + Check whether there is Ps/2 mouse device in system + + @param MouseAbsolutePointerDev - Absolute Pointer Device Private Data Structure + + @retval TRUE - Keyboard in System. + @retval FALSE - Keyboard not in System. + +**/ +BOOLEAN +CheckMouseAbsolutePointerConnect ( + IN PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev + ) + +{ + EFI_STATUS Status; + + Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo); + if (!EFI_ERROR (Status)) { + return TRUE; + } + + return FALSE; +} + +/** + Get and Clear mouse status. + + @param This - Pointer of simple pointer Protocol. + @param State - Output buffer holding status. + + @retval EFI_INVALID_PARAMETER Output buffer is invalid. + @retval EFI_NOT_READY Mouse is not changed status yet. + @retval EFI_SUCCESS Mouse status is changed and get successful. +**/ +EFI_STATUS +EFIAPI +MouseAbsolutePointerGetState ( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN OUT EFI_ABSOLUTE_POINTER_STATE *State + ) +{ + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; + EFI_TPL OldTpl; + + MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This); + + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!MouseAbsolutePointerDev->StateChanged) { + return EFI_NOT_READY; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + CopyMem (State, &(MouseAbsolutePointerDev->State), sizeof (EFI_ABSOLUTE_POINTER_STATE)); + + // + // clear mouse state + // + MouseAbsolutePointerDev->State.CurrentX = 0; + MouseAbsolutePointerDev->State.CurrentY = 0; + MouseAbsolutePointerDev->State.CurrentZ = 0; + MouseAbsolutePointerDev->State.ActiveButtons = 0x0; + MouseAbsolutePointerDev->StateChanged = FALSE; + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +/** + + Event notification function for SIMPLE_POINTER.WaitForInput event. + Signal the event if there is input from mouse. + + @param Event event object + @param Context event context + +**/ +VOID +EFIAPI +MouseAbsolutePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; + + MouseAbsolutePointerDev = (PS2_MOUSE_ABSOLUTE_POINTER_DEV *) Context; + + // + // Someone is waiting on the mouse event, if there's + // input from mouse, signal the event + // + if (MouseAbsolutePointerDev->StateChanged) { + gBS->SignalEvent (Event); + } + +} + +/** + Event notification function for TimerEvent event. + If mouse device is connected to system, try to get the mouse packet data. + + @param Event - TimerEvent in PS2_MOUSE_DEV + @param Context - Pointer to PS2_MOUSE_DEV structure + +**/ +VOID +EFIAPI +PollMouseAbsolutePointer( + IN EFI_EVENT Event, + IN VOID *Context + ) + +{ + PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; + + MouseAbsolutePointerDev = (PS2_MOUSE_ABSOLUTE_POINTER_DEV *) Context; + + // + // Polling mouse packet data + // + PS2MouseGetPacket (MouseAbsolutePointerDev); +} + +/** + The user Entry Point for module Ps2MouseAbsolutePointer. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializePs2MouseAbsolutePointer( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gPS2MouseAbsolutePointerDriver, + ImageHandle, + &gPs2MouseAbsolutePointerComponentName, + &gPs2MouseAbsolutePointerComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.h b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.h new file mode 100644 index 0000000000..a4e2174a4c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.h @@ -0,0 +1,400 @@ +/** @file + A Ps2MouseAbsolutePointer driver header file + +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 __PS2MOUSEABSOLUTEPOINTER_H__ +#define __PS2MOUSEABSOLUTEPOINTER_H__ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gPS2MouseAbsolutePointerDriver; +extern EFI_COMPONENT_NAME_PROTOCOL gPs2MouseAbsolutePointerComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gPs2MouseAbsolutePointerComponentName2; + +// +// PS/2 mouse sample rate +// +typedef enum { + SampleRate10, + SampleRate20, + SampleRate40, + SampleRate60, + SampleRate80, + SampleRate100, + SampleRate200, + MaxSampleRate +} MOUSE_SR; + +// +// PS/2 mouse resolution +// +typedef enum { + MouseResolution1, + MouseResolution2, + MouseResolution4, + MouseResolution8, + MaxResolution +} MOUSE_RE; + +// +// PS/2 mouse scaling +// +typedef enum { + Scaling1, + Scaling2 +} MOUSE_SF; + +// +// Driver Private Data +// +#define PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE SIGNATURE_32 ('p', '2', 's', 't') + +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_ABSOLUTE_POINTER_PROTOCOL AbsolutePointerProtocol; + EFI_ABSOLUTE_POINTER_STATE State; + EFI_ABSOLUTE_POINTER_MODE Mode; + BOOLEAN StateChanged; + + // + // PS2 Mouse device specific information + // + MOUSE_SR SampleRate; + MOUSE_RE Resolution; + MOUSE_SF Scaling; + UINT8 DataPackageSize; + + EFI_ISA_IO_PROTOCOL *IsaIo; + + EFI_EVENT TimerEvent; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} PS2_MOUSE_ABSOLUTE_POINTER_DEV; + +#define PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS(a) CR (a, PS2_MOUSE_ABSOLUTE_POINTER_DEV, AbsolutePointerProtocol, PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE) + +// +// Function prototypes +// +/** + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a IsaIo protocol can be supported. + + @param This 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 EFI_ALREADY_STARTED This driver is already running on this device + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +PS2MouseAbsolutePointerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start this driver on ControllerHandle by opening a IsaIo + protocol, creating PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid + finnally. + + @param This 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 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 +PS2MouseAbsolutePointerDriverStart ( + 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 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 +PS2MouseAbsolutePointerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +Ps2MouseAbsolutePointerComponentNameGetDriverName ( + 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 +Ps2MouseAbsolutePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/** + Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system. + + @param This - Pointer of simple pointer Protocol. + @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. + + + @retval EFI_SUCCESS - The command byte is written successfully. + @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. + +**/ +EFI_STATUS +EFIAPI +MouseAbsolutePointerReset ( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Get and Clear mouse status. + + @param This - Pointer of simple pointer Protocol. + @param State - Output buffer holding status. + + @retval EFI_INVALID_PARAMETER Output buffer is invalid. + @retval EFI_NOT_READY Mouse is not changed status yet. + @retval EFI_SUCCESS Mouse status is changed and get successful. +**/ +EFI_STATUS +EFIAPI +MouseAbsolutePointerGetState ( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN OUT EFI_ABSOLUTE_POINTER_STATE *State + ); + +/** + + Event notification function for SIMPLE_POINTER.WaitForInput event. + Signal the event if there is input from mouse. + + @param Event event object + @param Context event context + +**/ +VOID +EFIAPI +MouseAbsolutePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Event notification function for TimerEvent event. + If mouse device is connected to system, try to get the mouse packet data. + + @param Event - TimerEvent in PS2_MOUSE_DEV + @param Context - Pointer to PS2_MOUSE_DEV structure + +**/ +VOID +EFIAPI +PollMouseAbsolutePointer ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + I/O work flow of in 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ); + +/** + Check whether there is Ps/2 mouse device in system + + @param MouseAbsolutePointerDev - Absolute Pointer Device Private Data Structure + + @retval TRUE - Keyboard in System. + @retval FALSE - Keyboard not in System. + +**/ +BOOLEAN +CheckMouseAbsolutePointerConnect ( + IN PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf new file mode 100644 index 0000000000..be16671a2f --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf @@ -0,0 +1,77 @@ +## @file +# PS2 Mouse driver providing absolute (touch pad) pointer support. +# +# This driver simulates a touch pad absolute pointing device using a standard +# PS2 mouse as the input hardware. +# +# 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 +# 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 = Ps2MouseAbsolutePointerDxe + MODULE_UNI_FILE = Ps2MouseAbsolutePointerDxe.uni + FILE_GUID = 2899C94A-1FB6-4b1a-B96B-8364975303E0 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializePs2MouseAbsolutePointer + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# DRIVER_BINDING = gPS2MouseAbsolutePointerDriver; +# COMPONENT_NAME = gPs2MouseAbsolutePointerComponentName; +# COMPONENT_NAME2 = gPs2MouseAbsolutePointerComponentName2; +# + +[Sources] + ComponentName.c + CommPs2.h + CommPs2.c + Ps2MouseAbsolutePointer.h + Ps2MouseAbsolutePointer.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DebugLib + PcdLib + +[Protocols] + gEfiIsaIoProtocolGuid ## TO_START + gEfiAbsolutePointerProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## TO_START + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification ## CONSUMES + +# +# [Event] +# +# ## +# # Timer event used to check the mouse state at a regular interval. +# # +# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES +# + +[UserExtensions.TianoCore."ExtraFiles"] + Ps2MouseAbsolutePointerDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.uni new file mode 100644 index 0000000000..22f885d660 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxeExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxeExtra.uni new file mode 100644 index 0000000000..d5d7de237b Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c new file mode 100644 index 0000000000..1c763e97f3 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c @@ -0,0 +1,921 @@ +/** @file + PS2 Mouse Communication Interface. + +Copyright (c) 2006 - 2009, Intel 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 "Ps2Mouse.h" +#include "CommPs2.h" + +UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 }; + +UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 }; + +/** + Issue self test command via IsaIo interface. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return EFI_SUCCESS Success to do keyboard self testing. + @return others Fail to do keyboard self testing. +**/ +EFI_STATUS +KbcSelfTest ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Keyboard controller self test + // + Status = Out8042Command (IsaIo, SELF_TEST); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Read return code + // + Status = In8042Data (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Data != 0x55) { + return EFI_DEVICE_ERROR; + } + // + // Set system flag + // + Status = Out8042Command (IsaIo, READ_CMD_BYTE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = In8042Data (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Out8042Command (IsaIo, WRITE_CMD_BYTE); + if (EFI_ERROR (Status)) { + return Status; + } + + Data |= CMD_SYS_FLAG; + Status = Out8042Data (IsaIo, Data); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Issue command to enable keyboard AUX functionality. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcEnableAux ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send 8042 enable mouse command + // + return Out8042Command (IsaIo, ENABLE_AUX); +} + +/** + Issue command to disable keyboard AUX functionality. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcDisableAux ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send 8042 disable mouse command + // + return Out8042Command (IsaIo, DISABLE_AUX); +} + +/** + Issue command to enable keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcEnableKb ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send 8042 enable keyboard command + // + return Out8042Command (IsaIo, ENABLE_KB); +} + +/** + Issue command to disable keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcDisableKb ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send 8042 disable keyboard command + // + return Out8042Command (IsaIo, DISABLE_KB); +} + +/** + Issue command to check keyboard status. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param KeyboardEnable return whether keyboard is enable. + + @return Status of command issuing. +**/ +EFI_STATUS +CheckKbStatus ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + OUT BOOLEAN *KeyboardEnable + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Send command to read KBC command byte + // + Status = Out8042Command (IsaIo, READ_CMD_BYTE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = In8042Data (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check keyboard enable or not + // + if ((Data & CMD_KB_STS) == CMD_KB_DIS) { + *KeyboardEnable = FALSE; + } else { + *KeyboardEnable = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Issue command to reset keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseReset ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + EFI_STATUS Status; + UINT8 Data; + + Status = Out8042AuxCommand (IsaIo, RESET_CMD, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = In8042AuxData (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check BAT Complete Code + // + if (Data != PS2MOUSE_BAT1) { + return EFI_DEVICE_ERROR; + } + + Status = In8042AuxData (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check BAT Complete Code + // + if (Data != PS2MOUSE_BAT2) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Issue command to set mouse's sample rate + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param SampleRate value of sample rate + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetSampleRate ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_SR SampleRate + ) +{ + EFI_STATUS Status; + + // + // Send auxiliary command to set mouse sample rate + // + Status = Out8042AuxCommand (IsaIo, SETSR_CMD, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Out8042AuxData (IsaIo, SampleRateTbl[SampleRate]); + + return Status; +} + +/** + Issue command to set mouse's resolution. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Resolution value of resolution + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetResolution ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_RE Resolution + ) +{ + EFI_STATUS Status; + + // + // Send auxiliary command to set mouse resolution + // + Status = Out8042AuxCommand (IsaIo, SETRE_CMD, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Out8042AuxData (IsaIo, ResolutionTbl[Resolution]); + + return Status; +} + +/** + Issue command to set mouse's scaling. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Scaling value of scaling + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetScaling ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_SF Scaling + ) +{ + UINT8 Command; + + Command = (UINT8) (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD); + + // + // Send auxiliary command to set mouse scaling data + // + return Out8042AuxCommand (IsaIo, Command, FALSE); +} + +/** + Issue command to enable Ps2 mouse. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseEnable ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + // + // Send auxiliary command to enable mouse + // + return Out8042AuxCommand (IsaIo, ENABLE_CMD, FALSE); +} + +/** + Get mouse packet . Only care first 3 bytes + + @param MouseDev Pointer of PS2 Mouse Private Data Structure + + @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet + @retval EFI_SUCCESS The data packet is gotten successfully. + +**/ +EFI_STATUS +PS2MouseGetPacket ( + PS2_MOUSE_DEV *MouseDev + ) + +{ + EFI_STATUS Status; + BOOLEAN KeyboardEnable; + UINT8 Packet[PS2_PACKET_LENGTH]; + UINT8 Data; + UINTN Count; + UINTN State; + INT16 RelativeMovementX; + INT16 RelativeMovementY; + BOOLEAN LButton; + BOOLEAN RButton; + + KeyboardEnable = FALSE; + Count = 1; + State = PS2_READ_BYTE_ONE; + + // + // State machine to get mouse packet + // + while (1) { + + switch (State) { + case PS2_READ_BYTE_ONE: + // + // Read mouse first byte data, if failed, immediately return + // + KbcDisableAux (MouseDev->IsaIo); + Status = PS2MouseRead (MouseDev->IsaIo, &Data, &Count, State); + if (EFI_ERROR (Status)) { + KbcEnableAux (MouseDev->IsaIo); + return EFI_NOT_READY; + } + + if (Count != 1) { + KbcEnableAux (MouseDev->IsaIo); + return EFI_NOT_READY; + } + + if (IS_PS2_SYNC_BYTE (Data)) { + Packet[0] = Data; + State = PS2_READ_DATA_BYTE; + + CheckKbStatus (MouseDev->IsaIo, &KeyboardEnable); + KbcDisableKb (MouseDev->IsaIo); + KbcEnableAux (MouseDev->IsaIo); + } + break; + + case PS2_READ_DATA_BYTE: + Count = 2; + Status = PS2MouseRead (MouseDev->IsaIo, (Packet + 1), &Count, State); + if (EFI_ERROR (Status)) { + if (KeyboardEnable) { + KbcEnableKb (MouseDev->IsaIo); + } + + return EFI_NOT_READY; + } + + if (Count != 2) { + if (KeyboardEnable) { + KbcEnableKb (MouseDev->IsaIo); + } + + return EFI_NOT_READY; + } + + State = PS2_PROCESS_PACKET; + break; + + case PS2_PROCESS_PACKET: + if (KeyboardEnable) { + KbcEnableKb (MouseDev->IsaIo); + } + // + // Decode the packet + // + RelativeMovementX = Packet[1]; + RelativeMovementY = Packet[2]; + // + // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 + // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn + // Byte 1 | 8 bit X Movement + // Byte 2 | 8 bit Y Movement + // + // X sign bit + 8 bit X Movement : 9-bit signed twos complement integer that presents the relative displacement of the device in the X direction since the last data transmission. + // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement. + // + // + // First, Clear X and Y high 8 bits + // + RelativeMovementX = (INT16) (RelativeMovementX & 0xFF); + RelativeMovementY = (INT16) (RelativeMovementY & 0xFF); + // + // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff + // + if ((Packet[0] & 0x10) != 0) { + RelativeMovementX = (INT16) (RelativeMovementX | 0xFF00); + } + if ((Packet[0] & 0x20) != 0) { + RelativeMovementY = (INT16) (RelativeMovementY | 0xFF00); + } + + + RButton = (UINT8) (Packet[0] & 0x2); + LButton = (UINT8) (Packet[0] & 0x1); + + // + // Update mouse state + // + MouseDev->State.RelativeMovementX += RelativeMovementX; + MouseDev->State.RelativeMovementY -= RelativeMovementY; + MouseDev->State.RightButton = (UINT8) (RButton ? TRUE : FALSE); + MouseDev->State.LeftButton = (UINT8) (LButton ? TRUE : FALSE); + MouseDev->StateChanged = TRUE; + + return EFI_SUCCESS; + } + } +} + +/** + Read data via IsaIo protocol with given number. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Buffer Buffer receive data of mouse + @param BufSize The size of buffer + @param State Check input or read data + + @return status of reading mouse data. +**/ +EFI_STATUS +PS2MouseRead ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + OUT VOID *Buffer, + IN OUT UINTN *BufSize, + IN UINTN State + ) +{ + EFI_STATUS Status; + UINTN BytesRead; + + Status = EFI_SUCCESS; + BytesRead = 0; + + if (State == PS2_READ_BYTE_ONE) { + // + // Check input for mouse + // + Status = CheckForInput (IsaIo); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + while (BytesRead < *BufSize) { + + Status = WaitOutputFull (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + break; + } + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Buffer); + + BytesRead++; + Buffer = (UINT8 *) Buffer + 1; + } + // + // Verify the correct number of bytes read + // + if (BytesRead == 0 || BytesRead != *BufSize) { + Status = EFI_NOT_FOUND; + } + + *BufSize = BytesRead; + return Status; +} +// +// 8042 I/O function +// +/** + I/O work flow of outing 8042 command. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Command I/O command. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042Command ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Command + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Wait keyboard controller input buffer empty + // + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Send command + // + Data = Command; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow of outing 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Data + ) +{ + EFI_STATUS Status; + UINT8 Temp; + // + // Wait keyboard controller input buffer empty + // + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + Temp = Data; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow of in 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ) +{ + UINTN Delay; + UINT8 Temp; + + Delay = TIMEOUT / 50; + + do { + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp); + + // + // Check keyboard controller status bit 0(output buffer status) + // + if ((Temp & KBC_OUTB) == KBC_OUTB) { + break; + } + + gBS->Stall (50); + Delay--; + } while (Delay != 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data); + + return EFI_SUCCESS; +} + +/** + I/O work flow of outing 8042 Aux command. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Command Aux I/O command + @param Resend Whether need resend the Aux command. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042AuxCommand ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Command, + IN BOOLEAN Resend + ) +{ + EFI_STATUS Status; + UINT8 Data; + + // + // Wait keyboard controller input buffer empty + // + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Send write to auxiliary device command + // + Data = WRITE_AUX_DEV; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Send auxiliary device command + // + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command); + + // + // Read return code + // + Status = In8042AuxData (IsaIo, &Data); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Data == PS2_ACK) { + // + // Receive mouse acknowledge, command send success + // + return EFI_SUCCESS; + + } else if (Resend) { + // + // Resend fail + // + return EFI_DEVICE_ERROR; + + } else if (Data == PS2_RESEND) { + // + // Resend command + // + Status = Out8042AuxCommand (IsaIo, Command, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + + } else { + // + // Invalid return code + // + return EFI_DEVICE_ERROR; + + } + + return EFI_SUCCESS; +} + +/** + I/O work flow of outing 8042 Aux data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Buffer holding return value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042AuxData ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Data + ) +{ + EFI_STATUS Status; + UINT8 Temp; + // + // Wait keyboard controller input buffer empty + // + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Send write to auxiliary device command + // + Temp = WRITE_AUX_DEV; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + Temp = Data; + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp); + + Status = WaitInputEmpty (IsaIo, TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow of in 8042 Aux data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Buffer holding return value. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042AuxData ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ) +{ + EFI_STATUS Status; + + // + // wait for output data + // + Status = WaitOutputFull (IsaIo, BAT_TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data); + + return EFI_SUCCESS; +} + + +/** + Check keyboard controller status, if it is output buffer full and for auxiliary device. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @retval EFI_SUCCESS Keyboard controller is ready + @retval EFI_NOT_READY Keyboard controller is not ready +**/ +EFI_STATUS +CheckForInput ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ) +{ + UINT8 Data; + + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + // + // Check keyboard controller status, if it is output buffer full and for auxiliary device + // + if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow to wait input buffer empty in given time. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Timeout Wating time. + + @retval EFI_TIMEOUT if input is still not empty in given time. + @retval EFI_SUCCESS input is empty. +**/ +EFI_STATUS +WaitInputEmpty ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINTN Timeout + ) +{ + UINTN Delay; + UINT8 Data; + + Delay = Timeout / 50; + + do { + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + // + // Check keyboard controller status bit 1(input buffer status) + // + if ((Data & KBC_INPB) == 0) { + break; + } + + gBS->Stall (50); + Delay--; + } while (Delay != 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + I/O work flow to wait output buffer full in given time. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Timeout given time + + @retval EFI_TIMEOUT output is not full in given time + @retval EFI_SUCCESS output is full in given time. +**/ +EFI_STATUS +WaitOutputFull ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINTN Timeout + ) +{ + UINTN Delay; + UINT8 Data; + + Delay = Timeout / 50; + + do { + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + // + // Check keyboard controller status bit 0(output buffer status) + // & bit5(output buffer for auxiliary device) + // + if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) { + break; + } + + gBS->Stall (50); + Delay--; + } while (Delay != 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.h b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.h new file mode 100644 index 0000000000..a48ee8cb09 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.h @@ -0,0 +1,435 @@ +/** @file + PS2 Mouse Communication Interface + +Copyright (c) 2006 - 2007, Intel 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 _COMMPS2_H_ +#define _COMMPS2_H_ + +#define PS2_PACKET_LENGTH 3 +#define PS2_SYNC_MASK 0xc +#define PS2_SYNC_BYTE 0x8 + +#define IS_PS2_SYNC_BYTE(byte) ((byte & PS2_SYNC_MASK) == PS2_SYNC_BYTE) + +#define PS2_READ_BYTE_ONE 0 +#define PS2_READ_DATA_BYTE 1 +#define PS2_PROCESS_PACKET 2 + +#define TIMEOUT 50000 +#define BAT_TIMEOUT 500000 + +// +// 8042 I/O Port +// +#define KBC_DATA_PORT 0x60 +#define KBC_CMD_STS_PORT 0x64 + +// +// 8042 Command +// +#define READ_CMD_BYTE 0x20 +#define WRITE_CMD_BYTE 0x60 +#define DISABLE_AUX 0xa7 +#define ENABLE_AUX 0xa8 +#define SELF_TEST 0xaa +#define DISABLE_KB 0xad +#define ENABLE_KB 0xae +#define WRITE_AUX_DEV 0xd4 + +#define CMD_SYS_FLAG 0x04 +#define CMD_KB_STS 0x10 +#define CMD_KB_DIS 0x10 +#define CMD_KB_EN 0x0 + +// +// 8042 Auxiliary Device Command +// +#define SETSF1_CMD 0xe6 +#define SETSF2_CMD 0xe7 +#define SETRE_CMD 0xe8 +#define READ_CMD 0xeb +#define SETRM_CMD 0xf0 +#define SETSR_CMD 0xf3 +#define ENABLE_CMD 0xf4 +#define DISABLE_CMD 0xf5 +#define RESET_CMD 0xff + +// +// return code +// +#define PS2_ACK 0xfa +#define PS2_RESEND 0xfe +#define PS2MOUSE_BAT1 0xaa +#define PS2MOUSE_BAT2 0x0 + +// +// Keyboard Controller Status +// +/// +/// Parity Error +/// +#define KBC_PARE 0x80 +/// +/// General Time Out +/// +#define KBC_TIM 0x40 +/// +/// Output buffer for auxiliary device (PS/2): +/// 0 - Holds keyboard data +/// 1 - Holds data for auxiliary device +/// +#define KBC_AUXB 0x20 +/// +/// Keyboard lock status: +/// 0 - keyboard locked +/// 1 - keyboard free +/// +#define KBC_KEYL 0x10 +/// +/// Command/Data: +/// 0 - data byte written via port 60h +/// 1 - command byte written via port 64h +/// +#define KBC_CD 0x08 +/// +/// System Flag: +/// 0 - power-on reset +/// 1 - self-test successful +/// +#define KBC_SYSF 0x04 +/// +/// Input Buffer Status : +/// 0 - input buffer empty +/// 1 - CPU data in input buffer +/// +#define KBC_INPB 0x02 +/// +/// Output Buffer Status : +/// 0 - output buffer empty +/// 1 - keyboard controller data in output buffer +/// +#define KBC_OUTB 0x01 + +/** + Issue self test command via IsaIo interface. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return EFI_SUCCESS Success to do keyboard self testing. + @return others Fail to do keyboard self testing. +**/ +EFI_STATUS +KbcSelfTest ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to enable keyboard AUX functionality. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcEnableAux ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to disable keyboard AUX functionality. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcDisableAux ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to enable keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcEnableKb ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to disable keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +KbcDisableKb ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to check keyboard status. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param KeyboardEnable return whether keyboard is enable. + + @return Status of command issuing. +**/ +EFI_STATUS +CheckKbStatus ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + OUT BOOLEAN *KeyboardEnable + ); + +/** + Issue command to reset keyboard. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseReset ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Issue command to set mouse's sample rate + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param SampleRate value of sample rate + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetSampleRate ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_SR SampleRate + ); + +/** + Issue command to set mouse's resolution. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Resolution value of resolution + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetResolution ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_RE Resolution + ); + +/** + Issue command to set mouse's scaling. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Scaling value of scaling + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseSetScaling ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN MOUSE_SF Scaling + ); + +/** + Issue command to enable Ps2 mouse. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @return Status of command issuing. +**/ +EFI_STATUS +PS2MouseEnable ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + Get mouse packet . Only care first 3 bytes + + @param MouseDev Pointer of PS2 Mouse Private Data Structure + + @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet + @retval EFI_SUCCESS The data packet is gotten successfully. + +**/ +EFI_STATUS +PS2MouseGetPacket ( + PS2_MOUSE_DEV *MouseDev + ); + +/** + Read data via IsaIo protocol with given number. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Buffer Buffer receive data of mouse + @param BufSize The size of buffer + @param State Check input or read data + + @return status of reading mouse data. +**/ +EFI_STATUS +PS2MouseRead ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + OUT VOID *Buffer, + IN OUT UINTN *BufSize, + IN UINTN State + ); + +// +// 8042 I/O function +// +/** + I/O work flow of outing 8042 command. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Command I/O command. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042Command ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Command + ); + +/** + I/O work flow of in 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ); + +/** + I/O work flow of outing 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Data + ); + +/** + I/O work flow of outing 8042 Aux command. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Command Aux I/O command + @param Resend Whether need resend the Aux command. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042AuxCommand ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Command, + IN BOOLEAN Resend + ); + +/** + I/O work flow of in 8042 Aux data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Buffer holding return value. + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042AuxData ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ); + +/** + I/O work flow of outing 8042 Aux data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Buffer holding return value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +Out8042AuxData ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINT8 Data + ); + +/** + Check keyboard controller status, if it is output buffer full and for auxiliary device. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + + @retval EFI_SUCCESS Keyboard controller is ready + @retval EFI_NOT_READY Keyboard controller is not ready +**/ +EFI_STATUS +CheckForInput ( + IN EFI_ISA_IO_PROTOCOL *IsaIo + ); + +/** + I/O work flow to wait input buffer empty in given time. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Timeout Wating time. + + @retval EFI_TIMEOUT if input is still not empty in given time. + @retval EFI_SUCCESS input is empty. +**/ +EFI_STATUS +WaitInputEmpty ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINTN Timeout + ); + +/** + I/O work flow to wait output buffer full in given time. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Timeout given time + + @retval EFI_TIMEOUT output is not full in given time + @retval EFI_SUCCESS output is full in given time. +**/ +EFI_STATUS +WaitOutputFull ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN UINTN Timeout + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/ComponentName.c new file mode 100644 index 0000000000..1c3e84ec6d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/ComponentName.c @@ -0,0 +1,241 @@ +/** @file + UEFI Component Name(2) protocol implementation for Ps2MouseDxe 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 "Ps2Mouse.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPs2MouseComponentName = { + Ps2MouseComponentNameGetDriverName, + Ps2MouseComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPs2MouseComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ps2MouseComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ps2MouseComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPs2MouseDriverNameTable[] = { + { + "eng;en", + L"PS/2 Mouse Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +Ps2MouseComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mPs2MouseDriverNameTable, + DriverName, + (BOOLEAN)(This == &gPs2MouseComponentName) + ); +} + +/** + 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 +Ps2MouseComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol; + PS2_MOUSE_DEV *MouseDev; + EFI_ISA_IO_PROTOCOL *IsaIoProtocol; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + // + // Check Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIoProtocol, + gPS2MouseDriver.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiIsaIoProtocolGuid, + gPS2MouseDriver.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointerProtocol, + gPS2MouseDriver.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + MouseDev = PS2_MOUSE_DEV_FROM_THIS (SimplePointerProtocol); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + MouseDev->ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gPs2MouseComponentName) + ); +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c new file mode 100644 index 0000000000..1623201876 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c @@ -0,0 +1,792 @@ +/** @file + PS/2 Mouse driver. Routines that interacts with callers, + conforming to EFI driver model. + +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 "Ps2Mouse.h" +#include "CommPs2.h" + +/// +/// DriverBinding Protocol Instance +/// +EFI_DRIVER_BINDING_PROTOCOL gPS2MouseDriver = { + PS2MouseDriverSupported, + PS2MouseDriverStart, + PS2MouseDriverStop, + 0xa, + NULL, + NULL +}; + +/** + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a IsaIo protocol can be supported. + + @param This 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 EFI_ALREADY_STARTED This driver is already running on this device + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +PS2MouseDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_ISA_IO_PROTOCOL *IsaIo; + + Status = EFI_SUCCESS; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Use the ISA I/O Protocol to see if Controller is the Keyboard controller + // + switch (IsaIo->ResourceList->Device.HID) { + case EISA_PNP_ID (0xF03): + // + // Microsoft PS/2 style mouse + // + case EISA_PNP_ID (0xF13): + // + // PS/2 Port for PS/2-style Mice + // + break; + + case EISA_PNP_ID (0x303): + // + // IBM Enhanced (101/102-key, PS/2 mouse support) + // + if (IsaIo->ResourceList->Device.UID == 1) { + break; + } + + default: + Status = EFI_UNSUPPORTED; + break; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Start this driver on ControllerHandle by opening a IsaIo protocol, creating + PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid + finally. + + @param This 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 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 +PS2MouseDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_STATUS EmptyStatus; + EFI_ISA_IO_PROTOCOL *IsaIo; + PS2_MOUSE_DEV *MouseDev; + UINT8 Data; + EFI_TPL OldTpl; + EFI_STATUS_CODE_VALUE StatusCode; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + + StatusCode = 0; + MouseDev = NULL; + IsaIo = NULL; + + // + // Open the device path protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Report that the keyboard is being enabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE, + ParentDevicePath + ); + + // + // Get the ISA I/O Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_INVALID_PARAMETER; + } + // + // Raise TPL to avoid keyboard operation impact + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Allocate private data + // + MouseDev = AllocateZeroPool (sizeof (PS2_MOUSE_DEV)); + if (MouseDev == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Setup the device instance + // + MouseDev->Signature = PS2_MOUSE_DEV_SIGNATURE; + MouseDev->Handle = Controller; + MouseDev->SampleRate = SampleRate20; + MouseDev->Resolution = MouseResolution4; + MouseDev->Scaling = Scaling1; + MouseDev->DataPackageSize = 3; + MouseDev->IsaIo = IsaIo; + MouseDev->DevicePath = ParentDevicePath; + + // + // Resolution = 4 counts/mm + // + MouseDev->Mode.ResolutionX = 4; + MouseDev->Mode.ResolutionY = 4; + MouseDev->Mode.LeftButton = TRUE; + MouseDev->Mode.RightButton = TRUE; + + MouseDev->SimplePointerProtocol.Reset = MouseReset; + MouseDev->SimplePointerProtocol.GetState = MouseGetState; + MouseDev->SimplePointerProtocol.Mode = &(MouseDev->Mode); + + // + // Initialize keyboard controller if necessary + // + IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + // + // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. + // + if ((Data & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) { + // + // If nobody decodes KBC I/O port, it will read back as 0xFF. + // Check the Time-Out and Parity bit to see if it has an active KBC in system + // + Status = EFI_DEVICE_ERROR; + StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; + goto ErrorExit; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST, + ParentDevicePath + ); + + if ((Data & KBC_SYSF) != KBC_SYSF) { + Status = KbcSelfTest (IsaIo); + if (EFI_ERROR (Status)) { + StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR; + goto ErrorExit; + } + } + + KbcEnableAux (IsaIo); + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT, + ParentDevicePath + ); + + // + // Reset the mouse + // + Status = MouseDev->SimplePointerProtocol.Reset ( + &MouseDev->SimplePointerProtocol, + FeaturePcdGet (PcdPs2MouseExtendedVerification) + ); + if (EFI_ERROR (Status)) { + // + // mouse not connected + // + Status = EFI_SUCCESS; + StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; + goto ErrorExit; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED, + ParentDevicePath + ); + + // + // Setup the WaitForKey event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + MouseWaitForInput, + MouseDev, + &((MouseDev->SimplePointerProtocol).WaitForInput) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Setup a periodic timer, used to poll mouse state + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + PollMouse, + MouseDev, + &MouseDev->TimerEvent + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Start timer to poll mouse (100 samples per second) + // + Status = gBS->SetTimer (MouseDev->TimerEvent, TimerPeriodic, 100000); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + MouseDev->ControllerNameTable = NULL; + AddUnicodeString2 ( + "eng", + gPs2MouseComponentName.SupportedLanguages, + &MouseDev->ControllerNameTable, + L"PS/2 Mouse Device", + TRUE + ); + AddUnicodeString2 ( + "en", + gPs2MouseComponentName2.SupportedLanguages, + &MouseDev->ControllerNameTable, + L"PS/2 Mouse Device", + FALSE + ); + + + // + // Install protocol interfaces for the mouse device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimplePointerProtocolGuid, + &MouseDev->SimplePointerProtocol, + NULL + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + gBS->RestoreTPL (OldTpl); + + return Status; + +ErrorExit: + + if (Status != EFI_DEVICE_ERROR) { + KbcDisableAux (IsaIo); + } + + if (StatusCode != 0) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + StatusCode, + ParentDevicePath + ); + } + + if ((MouseDev != NULL) && (MouseDev->SimplePointerProtocol.WaitForInput != NULL)) { + gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput); + } + + if ((MouseDev != NULL) && (MouseDev->TimerEvent != NULL)) { + gBS->CloseEvent (MouseDev->TimerEvent); + } + + if ((MouseDev != NULL) && (MouseDev->ControllerNameTable != NULL)) { + FreeUnicodeStringTable (MouseDev->ControllerNameTable); + } + + if (Status != EFI_DEVICE_ERROR) { + // + // Since there will be no timer handler for mouse input any more, + // exhaust input data just in case there is still mouse data left + // + EmptyStatus = EFI_SUCCESS; + while (!EFI_ERROR (EmptyStatus)) { + EmptyStatus = In8042Data (IsaIo, &Data); + } + } + + if (MouseDev != NULL) { + FreePool (MouseDev); + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->RestoreTPL (OldTpl); + + return Status; +} + +/** + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + @param This 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 +PS2MouseDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol; + PS2_MOUSE_DEV *MouseDev; + UINT8 Data; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointerProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + MouseDev = PS2_MOUSE_DEV_FROM_THIS (SimplePointerProtocol); + + // + // Report that the keyboard is being disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE, + MouseDev->DevicePath + ); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSimplePointerProtocolGuid, + &MouseDev->SimplePointerProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Cancel mouse data polling timer, close timer event + // + gBS->SetTimer (MouseDev->TimerEvent, TimerCancel, 0); + gBS->CloseEvent (MouseDev->TimerEvent); + + // + // Since there will be no timer handler for mouse input any more, + // exhaust input data just in case there is still mouse data left + // + Status = EFI_SUCCESS; + while (!EFI_ERROR (Status)) { + Status = In8042Data (MouseDev->IsaIo, &Data); + } + + gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput); + FreeUnicodeStringTable (MouseDev->ControllerNameTable); + FreePool (MouseDev); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +/** + Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system + + @param This - Pointer of simple pointer Protocol. + @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. + + + @retval EFI_SUCCESS - The command byte is written successfully. + @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. + +**/ +EFI_STATUS +EFIAPI +MouseReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + PS2_MOUSE_DEV *MouseDev; + EFI_TPL OldTpl; + BOOLEAN KeyboardEnable; + UINT8 Data; + + MouseDev = PS2_MOUSE_DEV_FROM_THIS (This); + + // + // Report reset progress code + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET, + MouseDev->DevicePath + ); + + KeyboardEnable = FALSE; + + // + // Raise TPL to avoid keyboard operation impact + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + ZeroMem (&MouseDev->State, sizeof (EFI_SIMPLE_POINTER_STATE)); + MouseDev->StateChanged = FALSE; + + // + // Exhaust input data + // + Status = EFI_SUCCESS; + while (!EFI_ERROR (Status)) { + Status = In8042Data (MouseDev->IsaIo, &Data); + } + + CheckKbStatus (MouseDev->IsaIo, &KeyboardEnable); + + KbcDisableKb (MouseDev->IsaIo); + + MouseDev->IsaIo->Io.Read (MouseDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); + + // + // if there's data block on KBC data port, read it out + // + if ((Data & KBC_OUTB) == KBC_OUTB) { + MouseDev->IsaIo->Io.Read (MouseDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data); + } + + Status = EFI_SUCCESS; + // + // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system. + // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is + // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling + // + if (ExtendedVerification && CheckMouseConnect (MouseDev)) { + // + // Send mouse reset command and set mouse default configure + // + Status = PS2MouseReset (MouseDev->IsaIo); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = PS2MouseSetSampleRate (MouseDev->IsaIo, MouseDev->SampleRate); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = PS2MouseSetResolution (MouseDev->IsaIo, MouseDev->Resolution); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = PS2MouseSetScaling (MouseDev->IsaIo, MouseDev->Scaling); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = PS2MouseEnable (MouseDev->IsaIo); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + } +Exit: + gBS->RestoreTPL (OldTpl); + + if (KeyboardEnable) { + KbcEnableKb (MouseDev->IsaIo); + } + + return Status; +} + +/** + Check whether there is Ps/2 mouse device in system + + @param MouseDev - Mouse Private Data Structure + + @retval TRUE - Keyboard in System. + @retval FALSE - Keyboard not in System. + +**/ +BOOLEAN +CheckMouseConnect ( + IN PS2_MOUSE_DEV *MouseDev + ) + +{ + EFI_STATUS Status; + + Status = PS2MouseEnable (MouseDev->IsaIo); + if (!EFI_ERROR (Status)) { + return TRUE; + } + + return FALSE; +} + +/** + Get and Clear mouse status. + + @param This - Pointer of simple pointer Protocol. + @param State - Output buffer holding status. + + @retval EFI_INVALID_PARAMETER Output buffer is invalid. + @retval EFI_NOT_READY Mouse is not changed status yet. + @retval EFI_SUCCESS Mouse status is changed and get successful. +**/ +EFI_STATUS +EFIAPI +MouseGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +{ + PS2_MOUSE_DEV *MouseDev; + EFI_TPL OldTpl; + + MouseDev = PS2_MOUSE_DEV_FROM_THIS (This); + + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!MouseDev->StateChanged) { + return EFI_NOT_READY; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + CopyMem (State, &(MouseDev->State), sizeof (EFI_SIMPLE_POINTER_STATE)); + + // + // clear mouse state + // + MouseDev->State.RelativeMovementX = 0; + MouseDev->State.RelativeMovementY = 0; + MouseDev->State.RelativeMovementZ = 0; + MouseDev->StateChanged = FALSE; + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +/** + + Event notification function for SIMPLE_POINTER.WaitForInput event. + Signal the event if there is input from mouse. + + @param Event event object + @param Context event context + +**/ +VOID +EFIAPI +MouseWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + PS2_MOUSE_DEV *MouseDev; + + MouseDev = (PS2_MOUSE_DEV *) Context; + + // + // Someone is waiting on the mouse event, if there's + // input from mouse, signal the event + // + if (MouseDev->StateChanged) { + gBS->SignalEvent (Event); + } + +} + +/** + Event notification function for TimerEvent event. + If mouse device is connected to system, try to get the mouse packet data. + + @param Event - TimerEvent in PS2_MOUSE_DEV + @param Context - Pointer to PS2_MOUSE_DEV structure + +**/ +VOID +EFIAPI +PollMouse ( + IN EFI_EVENT Event, + IN VOID *Context + ) + +{ + PS2_MOUSE_DEV *MouseDev; + + MouseDev = (PS2_MOUSE_DEV *) Context; + + // + // Polling mouse packet data + // + PS2MouseGetPacket (MouseDev); +} + +/** + The user Entry Point for module Ps2Mouse. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializePs2Mouse( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gPS2MouseDriver, + ImageHandle, + &gPs2MouseComponentName, + &gPs2MouseComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.h b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.h new file mode 100644 index 0000000000..604fb47e47 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.h @@ -0,0 +1,400 @@ +/** @file + PS/2 Mouse driver header file. + +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 _PS2MOUSE_H_ +#define _PS2MOUSE_H_ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gPS2MouseDriver; +extern EFI_COMPONENT_NAME_PROTOCOL gPs2MouseComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gPs2MouseComponentName2; + +// +// PS/2 mouse sample rate +// +typedef enum { + SampleRate10, + SampleRate20, + SampleRate40, + SampleRate60, + SampleRate80, + SampleRate100, + SampleRate200, + MaxSampleRate +} MOUSE_SR; + +// +// PS/2 mouse resolution +// +typedef enum { + MouseResolution1, + MouseResolution2, + MouseResolution4, + MouseResolution8, + MaxResolution +} MOUSE_RE; + +// +// PS/2 mouse scaling +// +typedef enum { + Scaling1, + Scaling2 +} MOUSE_SF; + +// +// Driver Private Data +// +#define PS2_MOUSE_DEV_SIGNATURE SIGNATURE_32 ('p', 's', '2', 'm') + +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_SIMPLE_POINTER_PROTOCOL SimplePointerProtocol; + EFI_SIMPLE_POINTER_STATE State; + EFI_SIMPLE_POINTER_MODE Mode; + BOOLEAN StateChanged; + + // + // PS2 Mouse device specific information + // + MOUSE_SR SampleRate; + MOUSE_RE Resolution; + MOUSE_SF Scaling; + UINT8 DataPackageSize; + + EFI_ISA_IO_PROTOCOL *IsaIo; + + EFI_EVENT TimerEvent; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} PS2_MOUSE_DEV; + +#define PS2_MOUSE_DEV_FROM_THIS(a) CR (a, PS2_MOUSE_DEV, SimplePointerProtocol, PS2_MOUSE_DEV_SIGNATURE) + +// +// Function prototypes +// +/** + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a IsaIo protocol can be supported. + + @param This 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 EFI_ALREADY_STARTED This driver is already running on this device + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +PS2MouseDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start this driver on ControllerHandle by opening a IsaIo + protocol, creating PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid + finnally. + + @param This 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 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 +PS2MouseDriverStart ( + 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 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 +PS2MouseDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +Ps2MouseComponentNameGetDriverName ( + 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 +Ps2MouseComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/** + Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system + + @param This - Pointer of simple pointer Protocol. + @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. + + + @retval EFI_SUCCESS - The command byte is written successfully. + @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. + +**/ +EFI_STATUS +EFIAPI +MouseReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Get and Clear mouse status. + + @param This - Pointer of simple pointer Protocol. + @param State - Output buffer holding status. + + @retval EFI_INVALID_PARAMETER Output buffer is invalid. + @retval EFI_NOT_READY Mouse is not changed status yet. + @retval EFI_SUCCESS Mouse status is changed and get successful. +**/ +EFI_STATUS +EFIAPI +MouseGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ); + +/** + + Event notification function for SIMPLE_POINTER.WaitForInput event. + Signal the event if there is input from mouse. + + @param Event event object + @param Context event context + +**/ +VOID +EFIAPI +MouseWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Event notification function for TimerEvent event. + If mouse device is connected to system, try to get the mouse packet data. + + @param Event - TimerEvent in PS2_MOUSE_DEV + @param Context - Pointer to PS2_MOUSE_DEV structure + +**/ +VOID +EFIAPI +PollMouse ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + I/O work flow of in 8042 data. + + @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL + @param Data Data value + + @retval EFI_SUCCESS Success to excute I/O work flow + @retval EFI_TIMEOUT Keyboard controller time out. +**/ +EFI_STATUS +In8042Data ( + IN EFI_ISA_IO_PROTOCOL *IsaIo, + IN OUT UINT8 *Data + ); + +/** + Check whether there is Ps/2 mouse device in system + + @param MouseDev - Mouse Private Data Structure + + @retval TRUE - Keyboard in System. + @retval FALSE - Keyboard not in System. + +**/ +BOOLEAN +CheckMouseConnect ( + IN PS2_MOUSE_DEV *MouseDev + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf new file mode 100644 index 0000000000..ea7af5b10b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf @@ -0,0 +1,76 @@ +## @file +# PS2 Mouse Driver. +# +# This dirver provides support for PS2 based mice. +# +# 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 +# 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 = Ps2MouseDxe + MODULE_UNI_FILE = Ps2MouseDxe.uni + FILE_GUID = 202A2B0E-9A31-4812-B291-8747DF152439 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializePs2Mouse + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# DRIVER_BINDING = gPS2MouseDriver; +# COMPONENT_NAME = gPs2MouseComponentName; +# COMPONENT_NAME2 = gPs2MouseComponentName2; +# + +[Sources] + ComponentName.c + CommPs2.h + CommPs2.c + Ps2Mouse.h + Ps2Mouse.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DebugLib + PcdLib + +[Protocols] + gEfiIsaIoProtocolGuid ## TO_START + gEfiSimplePointerProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## TO_START + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification ## CONSUMES + +# +# [Event] +# +# ## +# # Timer event used to check the mouse state at a regular interval. +# # +# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES +# + +[UserExtensions.TianoCore."ExtraFiles"] + Ps2MouseDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni new file mode 100644 index 0000000000..c22c440d85 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni new file mode 100644 index 0000000000..750a15a849 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c new file mode 100644 index 0000000000..c541eb8991 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c @@ -0,0 +1,2799 @@ +/** @file + This file contains all helper functions on the ATA command + + Copyright (c) 2006 - 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. + + @par Revision Reference: + 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including + update - ATAIdentity() func + update - AtaBlockIoReadBlocks() func + update - AtaBlockIoWriteBlocks() func + add - AtaAtapi6Identify() func + add - AtaReadSectorsExt() func + add - AtaWriteSectorsExt() func + add - AtaPioDataInExt() func + add - AtaPioDataOutExt() func + +**/ + +#include "IdeBus.h" +/** + This function is called by ATAIdentify() to identity whether this disk + supports ATA/ATAPI6 48bit addressing, ie support >120G capacity + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + + @retval EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one and + 48-bit addressing must be used + @retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but the + capacity is below 120G, 48bit addressing is not needed + @retval EFI_DEVICE_ERROR The identify data in IdeDev is incorrect + @retval EFI_INVALID_PARAMETER The identify data in IdeDev is NULL. + + @note This function must be called after DEVICE_IDENTITY command has been + successfully returned + +**/ +EFI_STATUS +AtaAtapi6Identify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + UINT8 Index; + EFI_LBA TmpLba; + EFI_LBA Capacity; + EFI_IDENTIFY_DATA *Atapi6IdentifyStruct; + + if (IdeDev->IdData == NULL) { + return EFI_INVALID_PARAMETER; + } + + Atapi6IdentifyStruct = IdeDev->IdData; + + if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & (BIT15 | BIT14)) != 0x4000) { + // + // Per ATA-6 spec, word83: bit15 is zero and bit14 is one + // + return EFI_DEVICE_ERROR; + } + + if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & BIT10) == 0) { + // + // The device dosn't support 48 bit addressing + // + return EFI_UNSUPPORTED; + } + + // + // 48 bit address feature set is supported, get maximum capacity + // + Capacity = Atapi6IdentifyStruct->AtaData.maximum_lba_for_48bit_addressing[0]; + for (Index = 1; Index < 4; Index++) { + // + // Lower byte goes first: word[100] is the lowest word, word[103] is highest + // + TmpLba = Atapi6IdentifyStruct->AtaData.maximum_lba_for_48bit_addressing[Index]; + Capacity |= LShiftU64 (TmpLba, 16 * Index); + } + + if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) { + // + // Capacity exceeds 120GB. 48-bit addressing is really needed + // + IdeDev->Type = Ide48bitAddressingHardDisk; + + // + // Fill block media information:Media->LogicalPartition , + // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function. + // + IdeDev->BlkIo.Media->IoAlign = 4; + IdeDev->BlkIo.Media->MediaId = 1; + IdeDev->BlkIo.Media->RemovableMedia = FALSE; + IdeDev->BlkIo.Media->MediaPresent = TRUE; + IdeDev->BlkIo.Media->ReadOnly = FALSE; + IdeDev->BlkIo.Media->BlockSize = 0x200; + IdeDev->BlkIo.Media->LastBlock = Capacity - 1; + + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} +/** + Enable SMART of the disk if supported + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record + all the information of the IDE device. +**/ +VOID +AtaSMARTSupport ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_STATUS Status; + BOOLEAN SMARTSupported; + UINT8 Device; + EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer; + UINT8 DeviceSelect; + UINT8 LBAMid; + UINT8 LBAHigh; + + // + // Detect if the device supports S.M.A.R.T. + // + if ((IdeDev->IdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) { + // + // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one) + // + return ; + } else { + if ((IdeDev->IdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) { + // + // S.M.A.R.T is not supported by the device + // + SMARTSupported = FALSE; + } else { + SMARTSupported = TRUE; + } + } + + if (!SMARTSupported) { + // + // Report nonsupport status code + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED) + ); + } else { + // + // Enable this feature + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE) + ); + + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + Status = AtaNonDataCommandIn ( + IdeDev, + ATA_CMD_SMART, + Device, + ATA_SMART_ENABLE_OPERATION, + 0, + 0, + ATA_CONSTANT_4F, + ATA_CONSTANT_C2 + ); + // + // Detect if this feature is enabled + // + TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA)); + if (TmpAtaIdentifyPointer == NULL) { + return; + } + + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + Status = AtaPioDataIn ( + IdeDev, + (VOID *) TmpAtaIdentifyPointer, + sizeof (EFI_IDENTIFY_DATA), + ATA_CMD_IDENTIFY_DRIVE, + DeviceSelect, + 0, + 0, + 0, + 0 + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (TmpAtaIdentifyPointer); + return ; + } + + // + // Check if the feature is enabled + // + if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) { + // + // Read status data + // + AtaNonDataCommandIn ( + IdeDev, + ATA_CMD_SMART, + Device, + ATA_SMART_RETURN_STATUS, + 0, + 0, + ATA_CONSTANT_4F, + ATA_CONSTANT_C2 + ); + LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); + LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb); + + if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) { + // + // The threshold exceeded condition is not detected by the device + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD) + ); + + } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) { + // + // The threshold exceeded condition is detected by the device + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD) + ); + } + + } else { + // + // Report disabled status code + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED) + ); + } + + gBS->FreePool (TmpAtaIdentifyPointer); + } + + return ; +} +/** + Sends out an ATA Identify Command to the specified device. + + This function is called by DiscoverIdeDevice() during its device + identification. It sends out the ATA Identify Command to the + specified device. Only ATA device responses to this command. If + the command succeeds, it returns the Identify data structure which + contains information about the device. This function extracts the + information it needs to fill the IDE_BLK_IO_DEV data structure, + including device type, media block size, media capacity, and etc. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record + all the information of the IDE device. + + @retval EFI_SUCCESS Identify ATA device successfully. + @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device. + @note parameter IdeDev will be updated in this function. + +**/ +EFI_STATUS +ATAIdentify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_STATUS Status; + EFI_IDENTIFY_DATA *AtaIdentifyPointer; + UINT32 Capacity; + UINT8 DeviceSelect; + UINTN Retry; + + // + // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of + // the ATA Identify command + // + AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA)); + if (AtaIdentifyPointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // use ATA PIO Data In protocol to send ATA Identify command + // and receive data from device + // + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + + + Retry = 3; + while (Retry > 0) { + Status = AtaPioDataIn ( + IdeDev, + (VOID *) AtaIdentifyPointer, + sizeof (EFI_IDENTIFY_DATA), + ATA_CMD_IDENTIFY_DRIVE, + DeviceSelect, + 0, + 0, + 0, + 0 + ); + // + // If ATA Identify command succeeds, then according to the received + // IDENTIFY data, + // identify the device type ( ATA or not ). + // If ATA device, fill the information in IdeDev. + // If not ATA device, return IDE_DEVICE_ERROR + // + if (!EFI_ERROR (Status)) { + + IdeDev->IdData = AtaIdentifyPointer; + + // + // Print ATA Module Name + // + PrintAtaModuleName (IdeDev); + + // + // bit 15 of pAtaIdentify->config is used to identify whether device is + // ATA device or ATAPI device. + // if 0, means ATA device; if 1, means ATAPI device. + // + if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) { + // + // Detect if support S.M.A.R.T. If yes, enable it as default + // + AtaSMARTSupport (IdeDev); + + // + // Check whether this device needs 48-bit addressing (ATAPI-6 ata device) + // + Status = AtaAtapi6Identify (IdeDev); + if (!EFI_ERROR (Status)) { + // + // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify() + // + return EFI_SUCCESS; + } else if (Status == EFI_DEVICE_ERROR) { + // + // Some disk with big capacity (>200GB) is slow when being identified + // and will return all zero for word83. + // We try twice at first. If it fails, we do a SoftRest and try again. + // + Retry--; + if (Retry == 1) { + // + // Do a SoftRest before the third attempt. + // + AtaSoftReset (IdeDev); + } + continue; + } + // + // This is a hard disk <= 120GB capacity, treat it as normal hard disk + // + IdeDev->Type = IdeHardDisk; + + // + // Block Media Information: + // Media->LogicalPartition , Media->WriteCaching will be filled + // in the DiscoverIdeDevcie() function. + // + IdeDev->BlkIo.Media->IoAlign = 4; + IdeDev->BlkIo.Media->MediaId = 1; + IdeDev->BlkIo.Media->RemovableMedia = FALSE; + IdeDev->BlkIo.Media->MediaPresent = TRUE; + IdeDev->BlkIo.Media->ReadOnly = FALSE; + IdeDev->BlkIo.Media->BlockSize = 0x200; + + // + // Calculate device capacity + // + Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) | + AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ; + IdeDev->BlkIo.Media->LastBlock = Capacity - 1; + + return EFI_SUCCESS; + } + + } + break; + } + + gBS->FreePool (AtaIdentifyPointer); + // + // Make sure the pIdData will not be freed again. + // + IdeDev->IdData = NULL; + + return EFI_DEVICE_ERROR; +} + +/** + This function is a helper function used to change the char order in a string. It + is designed specially for the PrintAtaModuleName() function. After the IDE device + is detected, the IDE driver gets the device module name by sending ATA command + called ATA Identify Command or ATAPI Identify Command to the specified IDE device. + The module name returned is a string of ASCII characters: the first character is bit8--bit15 + of the first word, the second character is BIT0--bit7 of the first word and so on. Thus + the string can not be print directly before it is preprocessed by this func to change + the order of characters in each word in the string. + + @param Destination Indicates the destination string. + @param Source Indicates the source string. + @param Size the length of the string +**/ +VOID +SwapStringChars ( + IN CHAR8 *Destination, + IN CHAR8 *Source, + IN UINT32 Size + ) +{ + UINT32 Index; + CHAR8 Temp; + + for (Index = 0; Index < Size; Index += 2) { + + Temp = Source[Index + 1]; + Destination[Index + 1] = Source[Index]; + Destination[Index] = Temp; + } +} +/** + This function is called by ATAIdentify() or ATAPIIdentify() to print device's module name. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. +**/ +VOID +PrintAtaModuleName ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + if (IdeDev->IdData == NULL) { + return ; + } + + SwapStringChars (IdeDev->ModelName, IdeDev->IdData->AtaData.ModelName, 40); + IdeDev->ModelName[40] = 0x00; +} + +/** + This function is used to send out ATA commands conforms to the PIO Data In Protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param Buffer buffer contained data transferred from device to host. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param Head value of the Head/Device Register + @param SectorCount value of the Sector Count Register + @param SectorNumber value of the Sector Number Register + @param CylinderLsb value of the low byte of the Cylinder Register + @param CylinderMsb value of the high byte of the Cylinder Register + + @retval EFI_SUCCESS send out the ATA command and device send required data successfully. + @retval EFI_DEVICE_ERROR command sent failed. + +**/ +EFI_STATUS +AtaPioDataIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN UINT8 Head, + IN UINT8 SectorCount, + IN UINT8 SectorNumber, + IN UINT8 CylinderLsb, + IN UINT8 CylinderMsb + ) +{ + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // e0:1110,0000-- bit7 and bit5 are reserved bits. + // bit6 set means LBA mode + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head) + ); + + // + // All ATAPI device's ATA commands can be issued regardless of the + // state of the DRDY + // + if (IdeDev->Type == IdeHardDisk) { + + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + // + // set all the command parameters + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (AtaCommand == ATA_CMD_SET_FEATURES) { + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); + } + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb); + + // + // send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + Buffer16 = (UINT16 *) Buffer; + + // + // According to PIO data in protocol, host can perform a series of reads to + // the data register after each time device set DRQ ready; + // The data size of "a series of read" is command specific. + // For most ATA command, data size received from device will not exceed + // 1 sector, hence the data size for "a series of read" can be the whole data + // size of one command request. + // For ATA command such as Read Sector command, the data size of one ATA + // command request is often larger than 1 sector, according to the + // Read Sector command, the data size of "a series of read" is exactly 1 + // sector. + // Here for simplification reason, we specify the data size for + // "a series of read" to 1 sector (256 words) if data size of one ATA command + // request is larger than 256 words. + // + Increment = 256; + + // + // used to record bytes of currently transfered data + // + WordCount = 0; + + while (WordCount < ByteCount / 2) { + // + // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Get the byte count for one series of read + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } + + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); + + WordCount += Increment; + Buffer16 += Increment; + + } + + DRQClear (IdeDev, ATATIMEOUT); + + return CheckErrorStatus (IdeDev); +} + +/** + This function is used to send out ATA commands conforms to the + PIO Data Out Protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param *Buffer buffer contained data transferred from host to device. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param Head value of the Head/Device Register + @param SectorCount value of the Sector Count Register + @param SectorNumber value of the Sector Number Register + @param CylinderLsb value of the low byte of the Cylinder Register + @param CylinderMsb value of the high byte of the Cylinder Register + + @retval EFI_SUCCESS send out the ATA command and device received required + data successfully. + @retval EFI_DEVICE_ERROR command sent failed. + +**/ +EFI_STATUS +AtaPioDataOut ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN UINT8 Head, + IN UINT8 SectorCount, + IN UINT8 SectorNumber, + IN UINT8 CylinderLsb, + IN UINT8 CylinderMsb + ) +{ + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // select device via Head/Device register. + // Before write Head/Device register, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // e0:1110,0000-- bit7 and bit5 are reserved bits. + // bit6 set means LBA mode + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head) + ); + + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // set all the command parameters + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb); + + // + // send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + Buffer16 = (UINT16 *) Buffer; + + // + // According to PIO data out protocol, host can perform a series of + // writes to the data register after each time device set DRQ ready; + // The data size of "a series of read" is command specific. + // For most ATA command, data size written to device will not exceed 1 sector, + // hence the data size for "a series of write" can be the data size of one + // command request. + // For ATA command such as Write Sector command, the data size of one + // ATA command request is often larger than 1 sector, according to the + // Write Sector command, the data size of "a series of read" is exactly + // 1 sector. + // Here for simplification reason, we specify the data size for + // "a series of write" to 1 sector (256 words) if data size of one ATA command + // request is larger than 256 words. + // + Increment = 256; + WordCount = 0; + + while (WordCount < ByteCount / 2) { + + // + // DRQReady2-- read Alternate Status Register to determine the DRQ bit + // data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Check the remaining byte count is less than 512 bytes + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } + // + // perform a series of write without check DRQ ready + // + + IDEWritePortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); + WordCount += Increment; + Buffer16 += Increment; + + } + + DRQClear (IdeDev, ATATIMEOUT); + + return CheckErrorStatus (IdeDev); +} + +/** + This function is used to analyze the Status Register and print out + some debug information and if there is ERR bit set in the Status + Register, the Error Register's value is also be parsed and print out. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to + record all the information of the IDE device. + + @retval EFI_SUCCESS No err information in the Status Register. + @retval EFI_DEVICE_ERROR Any err information in the Status Register. + +**/ +EFI_STATUS +CheckErrorStatus ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + UINT8 StatusRegister; + UINT8 ErrorRegister; + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + DEBUG_CODE_BEGIN (); + + if ((StatusRegister & ATA_STSREG_DWF) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Write Fault\n", + StatusRegister) + ); + } + + if ((StatusRegister & ATA_STSREG_CORR) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Corrected Data\n", + StatusRegister) + ); + } + + if ((StatusRegister & ATA_STSREG_ERR) != 0) { + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + + if ((ErrorRegister & ATA_ERRREG_BBK) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n", + ErrorRegister) + ); + } + + if ((ErrorRegister & ATA_ERRREG_UNC) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n", + ErrorRegister) + ); + } + + if ((ErrorRegister & ATA_ERRREG_MC) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Media Change\n", + ErrorRegister) + ); + } + + if ((ErrorRegister & ATA_ERRREG_ABRT) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Abort\n", + ErrorRegister) + ); + } + + if ((ErrorRegister & ATA_ERRREG_TK0NF) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n", + ErrorRegister) + ); + } + + if ((ErrorRegister & ATA_ERRREG_AMNF) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n", + ErrorRegister) + ); + } + } + + DEBUG_CODE_END (); + + if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) { + return EFI_SUCCESS; + } + + return EFI_DEVICE_ERROR; + +} + +/** + This function is called by the AtaBlkIoReadBlocks() to perform reading from + media in block unit. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param DataBuffer A pointer to the destination buffer for the data. + @param Lba The starting logical block address to read from on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtaPioDataIn() function. + +**/ +EFI_STATUS +AtaReadSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +{ + EFI_STATUS Status; + UINTN BlocksRemaining; + UINT32 Lba32; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + UINT8 AtaCommand; + UINT8 SectorCount8; + UINT16 SectorCount; + UINTN ByteCount; + VOID *Buffer; + + Buffer = DataBuffer; + + // + // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol + // + AtaCommand = ATA_CMD_READ_SECTORS; + + + BlocksRemaining = NumberOfBlocks; + + Lba32 = (UINT32) Lba; + + Status = EFI_SUCCESS; + + while (BlocksRemaining > 0) { + + // + // in ATA-3 spec, LBA is in 28 bit width + // + Lba0 = (UINT8) Lba32; + Lba1 = (UINT8) (Lba32 >> 8); + Lba2 = (UINT8) (Lba32 >> 16); + // + // low 4 bit of Lba3 stands for LBA bit24~bit27. + // + Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f); + + if (BlocksRemaining >= 0x100) { + + // + // SectorCount8 is sent to Sector Count register, 0x00 means 256 + // sectors to be read + // + SectorCount8 = 0x00; + // + // SectorCount is used to record the number of sectors to be read + // + SectorCount = 256; + } else { + + SectorCount8 = (UINT8) BlocksRemaining; + SectorCount = (UINT16) BlocksRemaining; + } + + // + // ByteCount is the number of bytes that will be read + // + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + + // + // call AtaPioDataIn() to send Read Sector Command and receive data read + // + Status = AtaPioDataIn ( + IdeDev, + Buffer, + (UINT32) ByteCount, + AtaCommand, + Lba3, + SectorCount8, + Lba0, + Lba1, + Lba2 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba32 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } + + return Status; +} + +/** + This function is called by the AtaBlkIoWriteBlocks() to perform writing onto + media in block unit. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record + all the information of the IDE device. + @param BufferData A pointer to the source buffer for the data. + @param Lba The starting logical block address to write onto the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtaPioDataIn() function. + +**/ +EFI_STATUS +AtaWriteSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *BufferData, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +{ + EFI_STATUS Status; + UINTN BlocksRemaining; + UINT32 Lba32; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + UINT8 AtaCommand; + UINT8 SectorCount8; + UINT16 SectorCount; + UINTN ByteCount; + VOID *Buffer; + + Buffer = BufferData; + + // + // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol + // + AtaCommand = ATA_CMD_WRITE_SECTORS; + + BlocksRemaining = NumberOfBlocks; + + Lba32 = (UINT32) Lba; + + Status = EFI_SUCCESS; + + while (BlocksRemaining > 0) { + + Lba0 = (UINT8) Lba32; + Lba1 = (UINT8) (Lba32 >> 8); + Lba2 = (UINT8) (Lba32 >> 16); + Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f); + + if (BlocksRemaining >= 0x100) { + + // + // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors + // to be written + // + SectorCount8 = 0x00; + // + // SectorCount is used to record the number of sectors to be written + // + SectorCount = 256; + } else { + + SectorCount8 = (UINT8) BlocksRemaining; + SectorCount = (UINT16) BlocksRemaining; + } + + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + + Status = AtaPioDataOut ( + IdeDev, + Buffer, + (UINT32) ByteCount, + AtaCommand, + Lba3, + SectorCount8, + Lba0, + Lba1, + Lba2 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba32 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } + + return Status; +} +/** + This function is used to implement the Soft Reset on the specified device. But, + the ATA Soft Reset mechanism is so strong a reset method that it will force + resetting on both devices connected to the same cable. + + It is called by IdeBlkIoReset(), a interface function of Block + I/O protocol. + + This function can also be used by the ATAPI device to perform reset when + ATAPI Reset command is failed. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @retval EFI_SUCCESS Soft reset completes successfully. + @retval EFI_DEVICE_ERROR Any step during the reset process is failed. + + @note The registers initial values after ATA soft reset are different + to the ATA device and ATAPI device. +**/ +EFI_STATUS +AtaSoftReset ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + + UINT8 DeviceControl; + + DeviceControl = 0; + // + // set SRST bit to initiate soft reset + // + DeviceControl |= ATA_CTLREG_SRST; + + // + // disable Interrupt + // + DeviceControl |= BIT1; + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + // + // SRST should assert for at least 5 us, we use 10 us for + // better compatibility + // + gBS->Stall (10); + + // + // Enable interrupt to support UDMA, and clear SRST bit + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + // + // Wait for at least 2 ms to check BSY status, we use 10 ms + // for better compatibility + // + gBS->Stall(10000); + // + // slave device needs at most 31s to clear BSY + // + if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} +/** + This function is used to send out ATA commands conforms to the PIO Data In + Protocol, supporting ATA/ATAPI-6 standard + + Comparing with ATA-3 data in protocol, we have two differents here: + 1. Do NOT wait for DRQ clear before sending command into IDE device.(the + wait will frequently fail... cause writing function return error) + + 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly + slow down writing performance by 100 times!) + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Buffer buffer contained data transferred from device to host. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param StartLba the start LBA of this transaction + @param SectorCount the count of sectors to be transfered + + @retval EFI_SUCCESS send out the ATA command and device send required data successfully. + @retval EFI_DEVICE_ERROR command sent failed. + +**/ +EFI_STATUS +AtaPioDataInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN OUT VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount + ) +{ + UINT8 DevSel; + UINT8 SectorCount8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device, set bit6 as 1 to indicate LBA mode is used + // + DevSel = (UINT8) (IdeDev->Device << 4); + DevSel |= 0x40; + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + DevSel + ); + + // + // Wait for DRDY singnal asserting. ATAPI device needn't wait + // + if ( (IdeDev->Type == IdeHardDisk) || + (IdeDev->Type == Ide48bitAddressingHardDisk)) { + + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + + // + // Fill feature register if needed + // + if (AtaCommand == ATA_CMD_SET_FEATURES) { + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); + } + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (StartLba, 24); + LbaMid = (UINT8) RShiftU64 (StartLba, 32); + LbaHigh = (UINT8) RShiftU64 (StartLba, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + LbaLow = (UINT8) StartLba; + LbaMid = (UINT8) RShiftU64 (StartLba, 8); + LbaHigh = (UINT8) RShiftU64 (StartLba, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register, invoking the processing of this command + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + Buffer16 = (UINT16 *) Buffer; + + // + // According to PIO data in protocol, host can perform a series of reads to + // the data register after each time device set DRQ ready; + // + + // + // 256 words + // + Increment = 256; + + // + // used to record bytes of currently transfered data + // + WordCount = 0; + + while (WordCount < ByteCount / 2) { + // + // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Get the byte count for one series of read + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } + + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); + + WordCount += Increment; + Buffer16 += Increment; + + } + + return CheckErrorStatus (IdeDev); +} +/** + Send ATA Ext command into device with NON_DATA protocol. + + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaAddress The LBA address in 48-bit mode + + @retval EFI_SUCCESS Reading succeed + @retval EFI_DEVICE_ERROR Error executing commands on this device. + +**/ +EFI_STATUS +AtaCommandIssueExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +{ + EFI_STATUS Status; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + // + // Fill the feature register, which is a two-byte FIFO. Need write twice. + // + Feature8 = (UINT8) (Feature >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + LbaLow = (UINT8) LbaAddress; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + + LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Work around for Segate 160G disk writing + // + gBS->Stall (1800); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Stall at least 400ns + // + gBS->Stall (100); + + return EFI_SUCCESS; +} +/** + Send ATA Ext command into device with NON_DATA protocol + + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaAddress The LBA address in 48-bit mode + + @retval EFI_SUCCESS Reading succeed + @retval EFI_DEVICE_ERROR Error executing commands on this device. + +**/ +EFI_STATUS +AtaCommandIssue ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +{ + EFI_STATUS Status; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Lba0 = (UINT8) LbaAddress; + Lba1 = (UINT8) RShiftU64 (LbaAddress, 8); + Lba2 = (UINT8) RShiftU64 (LbaAddress, 16); + Lba3 = (UINT8) RShiftU64 (LbaAddress, 24); + Device = (UINT8) (Device | Lba3); + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + // + // Fill the feature register, which is a two-byte FIFO. Need write twice. + // + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Stall at least 400ns + // + gBS->Stall (100); + + return EFI_SUCCESS; +} +/** + Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt). + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DataBuffer A pointer to the source buffer for the data. + @param StartLba The starting logical block address to write to + on the device media. + @param NumberOfBlocks The number of transfer data blocks. + @param UdmaOp The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp, + AtaUdmaWriteOp, AtaUdmaWriteExOp + + @retval EFI_SUCCESS the operation is successful. + @retval EFI_OUT_OF_RESOURCES Build PRD table failed + @retval EFI_UNSUPPORTED Unknown channel or operations command + @retval EFI_DEVICE_ERROR Ata command execute failed + +**/ +EFI_STATUS +DoAtaUdma ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks, + IN ATA_UDMA_OPERATION UdmaOp + ) +{ + IDE_DMA_PRD *PrdAddr; + IDE_DMA_PRD *UsedPrdAddr; + IDE_DMA_PRD *TempPrdAddr; + UINT8 RegisterValue; + UINT8 Device; + UINT64 IoPortForBmic; + UINT64 IoPortForBmis; + UINT64 IoPortForBmid; + EFI_STATUS Status; + UINTN PrdTableNum; + UINTN ByteCount; + UINTN ByteAvailable; + UINT8 *PrdBuffer; + UINTN RemainBlockNum; + UINT8 DeviceControl; + UINT32 Count; + UINTN PageCount; + VOID *Map; + VOID *MemPage; + EFI_PHYSICAL_ADDRESS DeviceAddress; + UINTN MaxDmaCommandSectors; + EFI_PCI_IO_PROTOCOL_OPERATION PciIoProtocolOp; + UINT8 AtaCommand; + + switch (UdmaOp) { + case AtaUdmaReadOp: + MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS; + PciIoProtocolOp = EfiPciIoOperationBusMasterWrite; + AtaCommand = ATA_CMD_READ_DMA; + break; + case AtaUdmaReadExtOp: + MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS; + PciIoProtocolOp = EfiPciIoOperationBusMasterWrite; + AtaCommand = ATA_CMD_READ_DMA_EXT; + break; + case AtaUdmaWriteOp: + MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS; + PciIoProtocolOp = EfiPciIoOperationBusMasterRead; + AtaCommand = ATA_CMD_WRITE_DMA; + break; + case AtaUdmaWriteExtOp: + MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS; + PciIoProtocolOp = EfiPciIoOperationBusMasterRead; + AtaCommand = ATA_CMD_WRITE_DMA_EXT; + break; + default: + return EFI_UNSUPPORTED; + break; + } + + // + // Select device + // + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + // + // Enable interrupt to support UDMA + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + if (IdePrimary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET; + } else { + if (IdeSecondary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET; + } else { + return EFI_UNSUPPORTED; + } + } + + // + // Read BMIS register and clear ERROR and INTR bit + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + Status = EFI_SUCCESS; + + RemainBlockNum = NumberOfBlocks; + while (RemainBlockNum > 0) { + + if (RemainBlockNum >= MaxDmaCommandSectors) { + // + // SectorCount is used to record the number of sectors to be read + // Max 65536 sectors can be transfered at a time. + // + NumberOfBlocks = MaxDmaCommandSectors; + RemainBlockNum -= MaxDmaCommandSectors; + } else { + NumberOfBlocks = (UINT16) RemainBlockNum; + RemainBlockNum = 0; + } + + // + // Calculate the number of PRD table to make sure the memory region + // not cross 64K boundary + // + ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + PrdTableNum = ((ByteCount >> 16) + 1) + 1; + + // + // Build PRD table + // + PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD)); + Status = IdeDev->PciIo->AllocateBuffer ( + IdeDev->PciIo, + AllocateAnyPages, + EfiBootServicesData, + PageCount, + &MemPage, + 0 + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount)); + + PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage); + // + // To make sure PRD is allocated in one 64K page + // + if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000); + } else { + if ((UINTN) PrdAddr & 0x03) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC); + } else { + UsedPrdAddr = PrdAddr; + } + } + + // + // Build the PRD table + // + Status = IdeDev->PciIo->Map ( + IdeDev->PciIo, + PciIoProtocolOp, + DataBuffer, + &ByteCount, + &DeviceAddress, + &Map + ); + if (EFI_ERROR (Status)) { + IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); + return EFI_OUT_OF_RESOURCES; + } + PrdBuffer = (VOID *) ((UINTN) DeviceAddress); + TempPrdAddr = UsedPrdAddr; + while (TRUE) { + + ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF); + + if (ByteCount <= ByteAvailable) { + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteCount; + TempPrdAddr->EndOfTable = 0x8000; + break; + } + + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteAvailable; + + ByteCount -= ByteAvailable; + PrdBuffer += ByteAvailable; + TempPrdAddr++; + } + + // + // Set the base address to BMID register + // + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmid, + 1, + &UsedPrdAddr + ); + + // + // Set BMIC register to identify the operation direction + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) { + RegisterValue |= BMIC_NREAD; + } else { + RegisterValue &= ~((UINT8) BMIC_NREAD); + } + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) { + Status = AtaCommandIssueExt ( + IdeDev, + AtaCommand, + Device, + 0, + (UINT16) NumberOfBlocks, + StartLba + ); + } else { + Status = AtaCommandIssue ( + IdeDev, + AtaCommand, + Device, + 0, + (UINT16) NumberOfBlocks, + StartLba + ); + } + + if (EFI_ERROR (Status)) { + IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); + IdeDev->PciIo->Unmap (IdeDev->PciIo, Map); + return EFI_DEVICE_ERROR; + } + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue |= BMIC_START; + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Check the INTERRUPT and ERROR bit of BMIS + // Max transfer number of sectors for one command is 65536(32Mbyte), + // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps). + // So set the variable Count to 2000, for about 2 second timeout time. + // + Status = EFI_SUCCESS; + Count = 2000; + while (TRUE) { + + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + if (((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) != 0) || (Count == 0)) { + if (((RegisterValue & BMIS_ERROR) != 0) || (Count == 0)) { + Status = EFI_DEVICE_ERROR; + break; + } + break; + } + + gBS->Stall (1000); + Count --; + } + + IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); + IdeDev->PciIo->Unmap (IdeDev->PciIo, Map); + // + // Read BMIS register and clear ERROR and INTR bit + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + // + // Read Status Register of IDE device to clear interrupt + // + RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status); + // + // Clear START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue &= ~((UINT8) BMIC_START); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + if ((RegisterValue & BMIS_ERROR) != 0) { + return EFI_DEVICE_ERROR; + } + + if (EFI_ERROR (Status)) { + break; + } + DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + StartLba += NumberOfBlocks; + } + + // + // Disable interrupt of Select device + // + IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl); + DeviceControl |= ATA_CTLREG_IEN_L; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + return Status; +} + + +/** + This function is called by the AtaBlkIoReadBlocks() to perform reading from + media in block unit. The function has been enhanced to support >120GB access + and transfer at most 65536 blocks per command + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param DataBuffer A pointer to the destination buffer for the data. + @param StartLba The starting logical block address to read from on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status depends on the function DoAtaUdma() returns. +**/ +EFI_STATUS +AtaUdmaReadExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp); +} +/** + This function is called by the AtaBlkIoReadBlocks() to perform + reading from media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param DataBuffer A pointer to the destination buffer for the data. + @param StartLba The starting logical block address to read from + on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status depends on the function DoAtaUdma() returns. +**/ +EFI_STATUS +AtaUdmaRead ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp); +} + +/** + This function is called by the AtaBlkIoReadBlocks() to perform + reading from media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param DataBuffer A pointer to the destination buffer for the data. + @param StartLba The starting logical block address to read from on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtaPioDataInExt() function. +**/ +EFI_STATUS +AtaReadSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + EFI_STATUS Status; + UINTN BlocksRemaining; + EFI_LBA Lba64; + UINT8 AtaCommand; + UINT16 SectorCount; + UINT32 ByteCount; + VOID *Buffer; + + // + // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol + // + AtaCommand = ATA_CMD_READ_SECTORS_EXT; + Buffer = DataBuffer; + BlocksRemaining = NumberOfBlocks; + Lba64 = StartLba; + Status = EFI_SUCCESS; + + while (BlocksRemaining > 0) { + + if (BlocksRemaining >= 0x10000) { + // + // SectorCount is used to record the number of sectors to be read + // Max 65536 sectors can be transfered at a time. + // + SectorCount = 0xffff; + } else { + SectorCount = (UINT16) BlocksRemaining; + } + + // + // ByteCount is the number of bytes that will be read + // + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + + // + // call AtaPioDataInExt() to send Read Sector Command and receive data read + // + Status = AtaPioDataInExt ( + IdeDev, + Buffer, + ByteCount, + AtaCommand, + Lba64, + SectorCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba64 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } + + return Status; +} +/** + This function is the ATA implementation for ReadBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the read request is for. + @param Lba The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + + @param Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the memory that data is read into. + + @retval EFI_SUCCESS Read Blocks successfully. + @retval EFI_DEVICE_ERROR Read Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the data buffer is not valid. + + @note If Read Block error because of device error, this function will call + AtaSoftReset() function to reset device. + +**/ +EFI_STATUS +AtaBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + Status = EFI_SUCCESS; + + // + // Get the intrinsic block size + // + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (!(Media->MediaPresent)) { + return EFI_NO_MEDIA; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + // + // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism + // + if (IdeBlkIoDevice->UdmaMode.Valid) { + Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + } else { + Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + } + } else { + // + // For ATA-3 compatible device, use ATA-3 read block mechanism + // + if (IdeBlkIoDevice->UdmaMode.Valid) { + Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + } else { + Status = AtaReadSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + } + } + + if (EFI_ERROR (Status)) { + AtaSoftReset (IdeBlkIoDevice); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + +} +/** + This function is used to send out ATA commands conforms to the + PIO Data Out Protocol, supporting ATA/ATAPI-6 standard + + Comparing with ATA-3 data out protocol, we have two differents here:
+ 1. Do NOT wait for DRQ clear before sending command into IDE device.(the + wait will frequently fail... cause writing function return error) + + 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly + slow down writing performance by 100 times!) + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Buffer buffer contained data transferred from host to device. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param StartLba the start LBA of this transaction + @param SectorCount the count of sectors to be transfered + + @retval EFI_SUCCESS send out the ATA command and device receive required + data successfully. + @retval EFI_DEVICE_ERROR command sent failed. + +**/ +EFI_STATUS +AtaPioDataOutExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount + ) +{ + UINT8 DevSel; + UINT8 SectorCount8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device. Set bit6 as 1 to indicate LBA mode is used + // + DevSel = (UINT8) (IdeDev->Device << 4); + DevSel |= 0x40; + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + DevSel + ); + + // + // Wait for DRDY singnal asserting. + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Fill feature register if needed + // + if (AtaCommand == ATA_CMD_SET_FEATURES) { + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); + } + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (StartLba, 24); + LbaMid = (UINT8) RShiftU64 (StartLba, 32); + LbaHigh = (UINT8) RShiftU64 (StartLba, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + LbaLow = (UINT8) StartLba; + LbaMid = (UINT8) RShiftU64 (StartLba, 8); + LbaHigh = (UINT8) RShiftU64 (StartLba, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register, invoking the processing of this command + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + Buffer16 = (UINT16 *) Buffer; + + // + // According to PIO Data Out protocol, host can perform a series of writes to + // the data register after each time device set DRQ ready; + // + Increment = 256; + + // + // used to record bytes of currently transfered data + // + WordCount = 0; + + while (WordCount < ByteCount / 2) { + // + // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Write data into device by one series of writing to data register + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } + + IDEWritePortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); + + WordCount += Increment; + Buffer16 += Increment; + + } + return CheckErrorStatus (IdeDev); +} +/** + This function is called by the AtaBlkIoWriteBlocks() to perform + writing to media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DataBuffer A pointer to the source buffer for the data. + @param StartLba The starting logical block address to write to + on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status depends on the function DoAtaUdma() returns. +**/ +EFI_STATUS +AtaUdmaWriteExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp); +} + +/** + This function is called by the AtaBlkIoWriteBlocks() to perform + writing to media in block unit. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DataBuffer A pointer to the source buffer for the data. + @param StartLba The starting logical block address to write to + on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status depends on the function DoAtaUdma() returns. +**/ +EFI_STATUS +AtaUdmaWrite ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp); +} +/** + This function is called by the AtaBlkIoWriteBlocks() to perform + writing onto media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used + to record all the information of the IDE device. + @param DataBuffer A pointer to the source buffer for the data. + @param StartLba The starting logical block address to write onto the device + media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtaPioDataOutExt() function. +**/ +EFI_STATUS +AtaWriteSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + EFI_STATUS Status; + EFI_LBA Lba64; + UINTN BlocksRemaining; + UINT8 AtaCommand; + UINT16 SectorCount; + UINT32 ByteCount; + VOID *Buffer; + + // + // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol + // + AtaCommand = ATA_CMD_WRITE_SECTORS_EXT; + Lba64 = StartLba; + Buffer = DataBuffer; + BlocksRemaining = NumberOfBlocks; + + Status = EFI_SUCCESS; + + while (BlocksRemaining > 0) { + + if (BlocksRemaining >= 0x10000) { + // + // SectorCount is used to record the number of sectors to be written. + // Max 65536 sectors can be transfered at a time. + // + SectorCount = 0xffff; + } else { + SectorCount = (UINT16) BlocksRemaining; + } + + // + // ByteCount is the number of bytes that will be written + // + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + + // + // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command + // + Status = AtaPioDataOutExt ( + IdeDev, + Buffer, + ByteCount, + AtaCommand, + Lba64, + SectorCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba64 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } + + return Status; +} +/** + This function is the ATA implementation for WriteBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the write request is for. + @param Lba The starting logical block address to write onto the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the source buffer for the data.The caller + is responsible for either having implicit or explicit + ownership of the memory that data is written from. + + @retval EFI_SUCCESS Write Blocks successfully. + @retval EFI_DEVICE_ERROR Write Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the data buffer is not valid. + + @note If Write Block error because of device error, this function will call + AtaSoftReset() function to reset device. +**/ +EFI_STATUS +AtaBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + Status = EFI_SUCCESS; + + // + // Get the intrinsic block size + // + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + NumberOfBlocks = BufferSize / BlockSize; + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + // + // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism + // + if (IdeBlkIoDevice->UdmaMode.Valid) { + Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + } else { + Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + } + } else { + // + // For ATA-3 compatible device, use ATA-3 write block mechanism + // + if (IdeBlkIoDevice->UdmaMode.Valid) { + Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + } else { + Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + } + } + + if (EFI_ERROR (Status)) { + AtaSoftReset (IdeBlkIoDevice); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} +/** + Enable Long Physical Sector Feature for ATA device. + + @param IdeDev The IDE device data + + @retval EFI_SUCCESS The ATA device supports Long Physical Sector feature + and corresponding fields in BlockIo structure is updated. + @retval EFI_UNSUPPORTED The device is not ATA device or Long Physical Sector + feature is not supported. +**/ +EFI_STATUS +AtaEnableLongPhysicalSector ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_ATA_IDENTIFY_DATA *AtaIdentifyData; + UINT16 PhyLogicSectorSupport; + + ASSERT (IdeDev->IdData != NULL); + // + // Only valid for ATA device + // + AtaIdentifyData = (EFI_ATA_IDENTIFY_DATA *) &IdeDev->IdData->AtaData; + if ((AtaIdentifyData->config & 0x8000) != 0) { + return EFI_UNSUPPORTED; + } + PhyLogicSectorSupport = AtaIdentifyData->phy_logic_sector_support; + // + // Check whether Long Physical Sector Feature is supported + // + if ((PhyLogicSectorSupport & 0xc000) == 0x4000) { + IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = 1; + IdeDev->BlkIo.Media->LowestAlignedLba = 0; + // + // Check whether one physical block contains multiple physical blocks + // + if ((PhyLogicSectorSupport & 0x2000) != 0) { + IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = + (UINT32) (1 << (PhyLogicSectorSupport & 0x000f)); + // + // Check lowest alignment of logical blocks within physical block + // + if ((AtaIdentifyData->alignment_logic_in_phy_blocks & 0xc000) == 0x4000) { + IdeDev->BlkIo.Media->LowestAlignedLba = + (EFI_LBA) ((IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock - ((UINT32)AtaIdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) % + IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock); + } + } + // + // Check logical block size + // + IdeDev->BlkIo.Media->BlockSize = 0x200; + if ((PhyLogicSectorSupport & 0x1000) != 0) { + IdeDev->BlkIo.Media->BlockSize = (UINT32) ( + ((AtaIdentifyData->logic_sector_size_hi << 16) | + AtaIdentifyData->logic_sector_size_lo) * sizeof (UINT16) + ); + } + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +} +/** + Send ATA command into device with NON_DATA protocol + + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaLow The value in LBA_LOW register + @param LbaMiddle The value in LBA_MIDDLE register + @param LbaHigh The value in LBA_HIGH register + + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. + +**/ +EFI_STATUS +AtaNonDataCommandIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT8 Feature, + IN UINT8 SectorCount, + IN UINT8 LbaLow, + IN UINT8 LbaMiddle, + IN UINT8 LbaHigh + ) +{ + EFI_STATUS Status; + UINT8 StatusRegister; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device (bit4), set Lba mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Wait for command completion + // For ATAPI_SMART_CMD, we may need more timeout to let device + // adjust internal states. + // + if (AtaCommand == ATA_CMD_SMART) { + Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT); + } else { + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + } + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { + // + // Failed to execute command, abort operation + // + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +/** + Send ATA Ext command into device with NON_DATA protocol + + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaAddress The LBA address in 48-bit mode + + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. + +**/ +EFI_STATUS +AtaNonDataCommandInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +{ + EFI_STATUS Status; + UINT8 StatusRegister; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + // + // Fill the feature register, which is a two-byte FIFO. Need write twice. + // + Feature8 = (UINT8) (Feature >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); + LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + LbaLow = (UINT8) LbaAddress; + LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Wait for command completion + // + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { + // + // Failed to execute command, abort operation + // + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + + + diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c new file mode 100644 index 0000000000..1a3cb2e0a0 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c @@ -0,0 +1,1952 @@ +/** @file + This file contains all helper functions on the ATAPI command + + Copyright (c) 2006 - 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 "IdeBus.h" + +/** + This function is used to get the current status of the media residing + in the LS-120 drive or ZIP drive. The media status is returned in the + Error Status. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @retval EFI_SUCCESS The media status is achieved successfully and the media + can be read/written. + @retval EFI_DEVICE_ERROR Get Media Status Command is failed. + @retval EFI_NO_MEDIA There is no media in the drive. + @retval EFI_WRITE_PROTECTED The media is writing protected. + + @note This function must be called after the LS120EnableMediaStatus() + with second parameter set to TRUE + (means enable media status notification) is called. +**/ +EFI_STATUS +LS120GetMediaStatus ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + UINT8 DeviceSelect; + UINT8 StatusValue; + EFI_STATUS EfiStatus; + // + // Poll Alternate Register for BSY clear within timeout. + // + EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (EfiStatus)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device via Device/Head Register. + // + DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); + + // + // Poll Alternate Register for DRDY set within timeout. + // After device is selected, DRDY set indicates the device is ready to + // accept command. + // + EfiStatus = DRDYReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (EfiStatus)) { + return EFI_DEVICE_ERROR; + } + + // + // Get Media Status Command is sent + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xDA); + + // + // BSY bit will clear after command is complete. + // + EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (EfiStatus)) { + return EFI_DEVICE_ERROR; + } + + // + // the media status is returned by the command in the ERROR register + // + StatusValue = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + + if ((StatusValue & BIT1) != 0) { + return EFI_NO_MEDIA; + } + + if ((StatusValue & BIT6) != 0) { + return EFI_WRITE_PROTECTED; + } else { + return EFI_SUCCESS; + } +} +/** + This function is used to send Enable Media Status Notification Command + or Disable Media Status Notification Command. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @param Enable a flag that indicates whether enable or disable media + status notification. + @retval EFI_SUCCESS If command completes successfully. + @retval EFI_DEVICE_ERROR If command failed. +**/ +EFI_STATUS +LS120EnableMediaStatus ( + IN IDE_BLK_IO_DEV *IdeDev, + IN BOOLEAN Enable + ) +{ + UINT8 DeviceSelect; + EFI_STATUS Status; + + // + // Poll Alternate Register for BSY clear within timeout. + // + Status = WaitForBSYClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device via Device/Head Register. + // + DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); + + // + // Poll Alternate Register for DRDY set within timeout. + // After device is selected, DRDY set indicates the device is ready to + // accept command. + // + Status = DRDYReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (Enable) { + // + // 0x95: Enable media status notification + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x95); + } else { + // + // 0x31: Disable media status notification + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x31); + } + // + // Set Feature Command is sent + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xEF); + + // + // BSY bit will clear after command is complete. + // + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} +/** + This function reads the pending data in the device. + + @param IdeDev Indicates the calling context. + + @retval EFI_SUCCESS Successfully read. + @retval EFI_NOT_READY The BSY is set avoiding reading. + +**/ +EFI_STATUS +AtapiReadPendingData ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + UINT8 AltRegister; + UINT16 TempWordBuffer; + + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + if ((AltRegister & ATA_STSREG_BSY) == ATA_STSREG_BSY) { + return EFI_NOT_READY; + } + if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { + TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus); + while ((TempWordBuffer & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + 1, + &TempWordBuffer + ); + TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus); + } + } + return EFI_SUCCESS; +} + +/** + This function is called by either AtapiPacketCommandIn() or AtapiPacketCommandOut(). + It is used to transfer data between host and device. The data direction is specified + by the fourth parameter. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param Buffer buffer contained data transferred between host and device. + @param ByteCount data size in byte unit of the buffer. + @param Read flag used to determine the data transfer direction. + Read equals 1, means data transferred from device to host; + Read equals 0, means data transferred from host to device. + @param TimeOut timeout value for wait DRQ ready before each data stream's transfer. + + @retval EFI_SUCCESS data is transferred successfully. + @retval EFI_DEVICE_ERROR the device failed to transfer data. +**/ +EFI_STATUS +PioReadWriteData ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN BOOLEAN Read, + IN UINTN TimeOut + ) +{ + // + // required transfer data in word unit. + // + UINT32 RequiredWordCount; + + // + // actual transfer data in word unit. + // + UINT32 ActualWordCount; + UINT32 WordCount; + EFI_STATUS Status; + UINT16 *PtrBuffer; + + // + // No data transfer is premitted. + // + if (ByteCount == 0) { + return EFI_SUCCESS; + } + // + // for performance, we assert the ByteCount is an even number + // which is actually a resonable assumption + ASSERT((ByteCount%2) == 0); + + PtrBuffer = Buffer; + RequiredWordCount = ByteCount / 2; + // + // ActuralWordCount means the word count of data really transferred. + // + ActualWordCount = 0; + + while (ActualWordCount < RequiredWordCount) { + + // + // before each data transfer stream, the host should poll DRQ bit ready, + // to see whether indicates device is ready to transfer data. + // + Status = DRQReady2 (IdeDev, TimeOut); + if (EFI_ERROR (Status)) { + return CheckErrorStatus (IdeDev); + } + + // + // read Status Register will clear interrupt + // + IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // get current data transfer size from Cylinder Registers. + // + WordCount = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8; + WordCount = WordCount | IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); + WordCount = WordCount & 0xffff; + WordCount /= 2; + + WordCount = MIN (WordCount, (RequiredWordCount - ActualWordCount)); + + if (Read) { + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + WordCount, + PtrBuffer + ); + } else { + IDEWritePortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + WordCount, + PtrBuffer + ); + } + + PtrBuffer += WordCount; + ActualWordCount += WordCount; + } + + if (Read) { + // + // In the case where the drive wants to send more data than we need to read, + // the DRQ bit will be set and cause delays from DRQClear2(). + // We need to read data from the drive until it clears DRQ so we can move on. + // + AtapiReadPendingData (IdeDev); + } + + // + // After data transfer is completed, normally, DRQ bit should clear. + // + Status = DRQClear2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // read status register to check whether error happens. + // + return CheckErrorStatus (IdeDev); +} + +/** + This function is used to send out ATAPI commands conforms to the Packet Command + with PIO Data In Protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure + which contains the contents of the command. + @param Buffer buffer contained data transferred from device to host. + @param ByteCount data size in byte unit of the buffer. + @param TimeOut this parameter is used to specify the timeout value for the + PioReadWriteData() function. + + @retval EFI_SUCCESS send out the ATAPI packet command successfully + and device sends data successfully. + @retval EFI_DEVICE_ERROR the device failed to send data. + +**/ +EFI_STATUS +AtapiPacketCommandIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATAPI_PACKET_COMMAND *Packet, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN UINTN TimeOut + ) +{ + UINT16 *CommandIndex; + EFI_STATUS Status; + UINT32 Count; + + // + // Set all the command parameters by fill related registers. + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select device via Device/Head Register. + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | ATA_DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000) + ); + + // + // No OVL; No DMA + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00); + + // + // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device + // determine how many data should be transferred. + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderLsb, + (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff) + ); + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderMsb, + (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8) + ); + + // + // ATA_DEFAULT_CTL:0x0a (0000,1010) + // Disable interrupt + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, ATA_DEFAULT_CTL); + + // + // Send Packet command to inform device + // that the following data bytes are command packet. + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, ATA_CMD_PACKET); + + Status = DRQReady (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Send out command packet + // + CommandIndex = Packet->Data16; + for (Count = 0; Count < 6; Count++, CommandIndex++) { + + IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex); + gBS->Stall (10); + } + + // + // call PioReadWriteData() function to get + // requested transfer data form device. + // + return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut); +} +/** + This function is used to send out ATAPI commands conforms to the Packet Command + with PIO Data Out Protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure + which contains the contents of the command. + @param Buffer buffer contained data transferred from host to device. + @param ByteCount data size in byte unit of the buffer. + @param TimeOut this parameter is used to specify the timeout value + for the PioReadWriteData() function. + @retval EFI_SUCCESS send out the ATAPI packet command successfully + and device received data successfully. + @retval EFI_DEVICE_ERROR the device failed to send data. + +**/ +EFI_STATUS +AtapiPacketCommandOut ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATAPI_PACKET_COMMAND *Packet, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN UINTN TimeOut + ) +{ + UINT16 *CommandIndex; + EFI_STATUS Status; + UINT32 Count; + + // + // set all the command parameters + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select device via Device/Head Register. + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | ATA_DEFAULT_CMD) // ATA_DEFAULT_CMD: 0xa0 (1010,0000) + ); + + // + // No OVL; No DMA + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00); + + // + // set the transfersize to ATAPI_MAX_BYTE_COUNT to + // let the device determine how many data should be transferred. + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderLsb, + (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff) + ); + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderMsb, + (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8) + ); + + // + // DEFAULT_CTL:0x0a (0000,1010) + // Disable interrupt + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, ATA_DEFAULT_CTL); + + // + // Send Packet command to inform device + // that the following data bytes are command packet. + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, ATA_CMD_PACKET); + + Status = DRQReady2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Send out command packet + // + CommandIndex = Packet->Data16; + for (Count = 0; Count < 6; Count++, CommandIndex++) { + IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex); + gBS->Stall (10); + } + + // + // call PioReadWriteData() function to send requested transfer data to device. + // + return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut); +} +/** + Sends out ATAPI Inquiry Packet Command to the specified device. This command will + return INQUIRY data of the device. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @retval EFI_SUCCESS Inquiry command completes successfully. + @retval EFI_DEVICE_ERROR Inquiry command failed. + + @note Parameter "IdeDev" will be updated in this function. + +**/ +EFI_STATUS +AtapiInquiry ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + ATAPI_PACKET_COMMAND Packet; + EFI_STATUS Status; + ATAPI_INQUIRY_DATA *InquiryData; + + // + // prepare command packet for the ATAPI Inquiry Packet Command. + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.Inquiry.opcode = ATA_CMD_INQUIRY; + Packet.Inquiry.page_code = 0; + Packet.Inquiry.allocation_length = (UINT8) sizeof (ATAPI_INQUIRY_DATA); + + InquiryData = AllocatePool (sizeof (ATAPI_INQUIRY_DATA)); + if (InquiryData == NULL) { + return EFI_DEVICE_ERROR; + } + + // + // Send command packet and get requested Inquiry data. + // + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) InquiryData, + sizeof (ATAPI_INQUIRY_DATA), + ATAPITIMEOUT + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (InquiryData); + return EFI_DEVICE_ERROR; + } + + IdeDev->InquiryData = InquiryData; + + return EFI_SUCCESS; +} +/** + This function is called by DiscoverIdeDevice() during its device + identification. + Its main purpose is to get enough information for the device media + to fill in the Media data structure of the Block I/O Protocol interface. + + There are 5 steps to reach such objective: + 1. Sends out the ATAPI Identify Command to the specified device. + Only ATAPI device responses to this command. If the command succeeds, + it returns the Identify data structure which filled with information + about the device. Since the ATAPI device contains removable media, + the only meaningful information is the device module name. + 2. Sends out ATAPI Inquiry Packet Command to the specified device. + This command will return inquiry data of the device, which contains + the device type information. + 3. Allocate sense data space for future use. We don't detect the media + presence here to improvement boot performance, especially when CD + media is present. The media detection will be performed just before + each BLK_IO read/write + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @retval EFI_SUCCESS Identify ATAPI device successfully. + @retval EFI_DEVICE_ERROR ATAPI Identify Device Command failed or device type + is not supported by this IDE driver. + @retval EFI_OUT_OF_RESOURCES Allocate memory for sense data failed + + @note Parameter "IdeDev" will be updated in this function. +**/ +EFI_STATUS +ATAPIIdentify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_IDENTIFY_DATA *AtapiIdentifyPointer; + UINT8 DeviceSelect; + EFI_STATUS Status; + + // + // device select bit + // + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + + AtapiIdentifyPointer = AllocatePool (sizeof (EFI_IDENTIFY_DATA)); + if (AtapiIdentifyPointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Send ATAPI Identify Command to get IDENTIFY data. + // + Status = AtaPioDataIn ( + IdeDev, + (VOID *) AtapiIdentifyPointer, + sizeof (EFI_IDENTIFY_DATA), + ATA_CMD_IDENTIFY_DEVICE, + DeviceSelect, + 0, + 0, + 0, + 0 + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (AtapiIdentifyPointer); + return EFI_DEVICE_ERROR; + } + + IdeDev->IdData = AtapiIdentifyPointer; + PrintAtaModuleName (IdeDev); + + // + // Send ATAPI Inquiry Packet Command to get INQUIRY data. + // + Status = AtapiInquiry (IdeDev); + if (EFI_ERROR (Status)) { + gBS->FreePool (IdeDev->IdData); + // + // Make sure the pIdData will not be freed again. + // + IdeDev->IdData = NULL; + return EFI_DEVICE_ERROR; + } + // + // Get media removable info from INQUIRY data. + // + IdeDev->BlkIo.Media->RemovableMedia = (UINT8) ((IdeDev->InquiryData->RMB & 0x80) == 0x80); + + // + // Identify device type via INQUIRY data. + // + switch (IdeDev->InquiryData->peripheral_type & 0x1f) { + + // + // Magnetic Disk + // + case 0x00: + + // + // device is LS120 or ZIP drive. + // + IdeDev->Type = IdeMagnetic; + + IdeDev->BlkIo.Media->MediaId = 0; + // + // Give initial value + // + IdeDev->BlkIo.Media->MediaPresent = FALSE; + + IdeDev->BlkIo.Media->LastBlock = 0; + IdeDev->BlkIo.Media->BlockSize = 0x200; + break; + + // + // CD-ROM + // + case 0x05: + + IdeDev->Type = IdeCdRom; + IdeDev->BlkIo.Media->MediaId = 0; + // + // Give initial value + // + IdeDev->BlkIo.Media->MediaPresent = FALSE; + + IdeDev->BlkIo.Media->LastBlock = 0; + IdeDev->BlkIo.Media->BlockSize = 0x800; + IdeDev->BlkIo.Media->ReadOnly = TRUE; + break; + + // + // Tape + // + case 0x01: + + // + // WORM + // + case 0x04: + + // + // Optical + // + case 0x07: + + default: + IdeDev->Type = IdeUnknown; + gBS->FreePool (IdeDev->IdData); + gBS->FreePool (IdeDev->InquiryData); + // + // Make sure the pIdData and pInquiryData will not be freed again. + // + IdeDev->IdData = NULL; + IdeDev->InquiryData = NULL; + return EFI_DEVICE_ERROR; + } + + // + // original sense data numbers + // + IdeDev->SenseDataNumber = 20; + + IdeDev->SenseData = AllocatePool (IdeDev->SenseDataNumber * sizeof (ATAPI_REQUEST_SENSE_DATA)); + if (IdeDev->SenseData == NULL) { + gBS->FreePool (IdeDev->IdData); + gBS->FreePool (IdeDev->InquiryData); + // + // Make sure the pIdData and pInquiryData will not be freed again. + // + IdeDev->IdData = NULL; + IdeDev->InquiryData = NULL; + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} +/** + Sends out ATAPI Request Sense Packet Command to the specified device. This command + will return all the current Sense data in the device. This function will pack + all the Sense data in one single buffer. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param SenseCounts allocated in this function, and freed by the calling function. + This buffer is used to accommodate all the sense data returned + by the device. + + @retval EFI_SUCCESS Request Sense command completes successfully. + @retval EFI_DEVICE_ERROR Request Sense command failed. +**/ +EFI_STATUS +AtapiRequestSense ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT UINTN *SenseCounts + ) +{ + EFI_STATUS Status; + ATAPI_REQUEST_SENSE_DATA *Sense; + UINT16 *Ptr; + BOOLEAN FetchSenseData; + ATAPI_PACKET_COMMAND Packet; + + *SenseCounts = 0; + + ZeroMem (IdeDev->SenseData, sizeof (ATAPI_REQUEST_SENSE_DATA) * (IdeDev->SenseDataNumber)); + // + // fill command packet for Request Sense Packet Command + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.RequestSence.opcode = ATA_CMD_REQUEST_SENSE; + Packet.RequestSence.allocation_length = (UINT8) sizeof (ATAPI_REQUEST_SENSE_DATA); + + // + // initialize pointer + // + Ptr = (UINT16 *) IdeDev->SenseData; + // + // request sense data from device continuously until no sense data + // exists in the device. + // + for (FetchSenseData = TRUE; FetchSenseData;) { + + Sense = (ATAPI_REQUEST_SENSE_DATA *) Ptr; + + // + // send out Request Sense Packet Command and get one Sense data form device + // + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + Ptr, + sizeof (ATAPI_REQUEST_SENSE_DATA), + ATAPITIMEOUT + ); + // + // failed to get Sense data + // + if (EFI_ERROR (Status)) { + if (*SenseCounts == 0) { + return EFI_DEVICE_ERROR; + } else { + return EFI_SUCCESS; + } + } + + (*SenseCounts)++; + // + // We limit MAX sense data count to 20 in order to avoid dead loop. Some + // incompatible ATAPI devices don't retrive NO_SENSE when there is no media. + // In this case, dead loop occurs if we don't have a gatekeeper. 20 is + // supposed to be large enough for any ATAPI device. + // + if ((Sense->sense_key != ATA_SK_NO_SENSE) && ((*SenseCounts) < 20)) { + // + // Ptr is word-based pointer + // + Ptr += (sizeof (ATAPI_REQUEST_SENSE_DATA) + 1) >> 1; + + } else { + // + // when no sense key, skip out the loop + // + FetchSenseData = FALSE; + } + } + + return EFI_SUCCESS; +} +/** + This function is used to parse sense data. Only the first sense data is honoured + + @param IdeDev Indicates the calling context. + @param SenseCount Count of sense data. + @param Result The parsed result. + + @retval EFI_SUCCESS Successfully parsed. + @retval EFI_INVALID_PARAMETER Count of sense data is zero. + +**/ +EFI_STATUS +ParseSenseData ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN SenseCount, + OUT SENSE_RESULT *Result + ) +{ + ATAPI_REQUEST_SENSE_DATA *SenseData; + + if (SenseCount == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Only use the first sense data + // + SenseData = IdeDev->SenseData; + *Result = SenseOtherSense; + + switch (SenseData->sense_key) { + case ATA_SK_NO_SENSE: + *Result = SenseNoSenseKey; + break; + case ATA_SK_NOT_READY: + switch (SenseData->addnl_sense_code) { + case ATA_ASC_NO_MEDIA: + *Result = SenseNoMedia; + break; + case ATA_ASC_MEDIA_UPSIDE_DOWN: + *Result = SenseMediaError; + break; + case ATA_ASC_NOT_READY: + if (SenseData->addnl_sense_code_qualifier == ATA_ASCQ_IN_PROGRESS) { + *Result = SenseDeviceNotReadyNeedRetry; + } else { + *Result = SenseDeviceNotReadyNoRetry; + } + break; + } + break; + case ATA_SK_UNIT_ATTENTION: + if (SenseData->addnl_sense_code == ATA_ASC_MEDIA_CHANGE) { + *Result = SenseMediaChange; + } + break; + case ATA_SK_MEDIUM_ERROR: + switch (SenseData->addnl_sense_code) { + case ATA_ASC_MEDIA_ERR1: + case ATA_ASC_MEDIA_ERR2: + case ATA_ASC_MEDIA_ERR3: + case ATA_ASC_MEDIA_ERR4: + *Result = SenseMediaError; + break; + } + break; + default: + break; + } + + return EFI_SUCCESS; +} + +/** + Sends out ATAPI Test Unit Ready Packet Command to the specified device + to find out whether device is accessible. + + @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param SResult Sense result for this packet command. + + @retval EFI_SUCCESS Device is accessible. + @retval EFI_DEVICE_ERROR Device is not accessible. + +**/ +EFI_STATUS +AtapiTestUnitReady ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT SENSE_RESULT *SResult + ) +{ + ATAPI_PACKET_COMMAND Packet; + EFI_STATUS Status; + UINTN SenseCount; + + // + // fill command packet + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY; + + // + // send command packet + // + Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = AtapiRequestSense (IdeDev, &SenseCount); + if (EFI_ERROR (Status)) { + return Status; + } + + ParseSenseData (IdeDev, SenseCount, SResult); + return EFI_SUCCESS; +} + + +/** + Sends out ATAPI Read Capacity Packet Command to the specified device. + This command will return the information regarding the capacity of the + media in the device. + + Current device status will impact device's response to the Read Capacity + Command. For example, if the device once reset, the Read Capacity + Command will fail. The Sense data record the current device status, so + if the Read Capacity Command failed, the Sense data must be requested + and be analyzed to determine if the Read Capacity Command should retry. + + @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param SResult Sense result for this packet command + + @retval EFI_SUCCESS Read Capacity Command finally completes successfully. + @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error. + @retval EFI_NOT_READY Operation succeeds but returned capacity is 0 + + @note Parameter "IdeDev" will be updated in this function. + + +**/ +EFI_STATUS +AtapiReadCapacity ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT SENSE_RESULT *SResult + ) +{ + // + // status returned by Read Capacity Packet Command + // + EFI_STATUS Status; + EFI_STATUS SenseStatus; + ATAPI_PACKET_COMMAND Packet; + UINTN SenseCount; + + // + // used for capacity data returned from ATAPI device + // + ATAPI_READ_CAPACITY_DATA Data; + ATAPI_READ_FORMAT_CAPACITY_DATA FormatData; + + ZeroMem (&Data, sizeof (Data)); + ZeroMem (&FormatData, sizeof (FormatData)); + + if (IdeDev->Type == IdeCdRom) { + + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.Inquiry.opcode = ATA_CMD_READ_CAPACITY; + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) &Data, + sizeof (ATAPI_READ_CAPACITY_DATA), + ATAPITIMEOUT + ); + + } else { + // + // Type == IdeMagnetic + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.ReadFormatCapacity.opcode = ATA_CMD_READ_FORMAT_CAPACITY; + Packet.ReadFormatCapacity.allocation_length_lo = 12; + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) &FormatData, + sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA), + ATAPITIMEOUT + ); + } + + if (Status == EFI_TIMEOUT) { + return Status; + } + + SenseStatus = AtapiRequestSense (IdeDev, &SenseCount); + + if (!EFI_ERROR (SenseStatus)) { + ParseSenseData (IdeDev, SenseCount, SResult); + + if (!EFI_ERROR (Status) && *SResult == SenseNoSenseKey) { + if (IdeDev->Type == IdeCdRom) { + + IdeDev->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) | + (Data.LastLba2 << 16) | + (Data.LastLba1 << 8) | + Data.LastLba0; + + IdeDev->BlkIo.Media->MediaPresent = TRUE; + + IdeDev->BlkIo.Media->ReadOnly = TRUE; + + // + // Because the user data portion in the sector of the Data CD supported + // is always 0x800 + // + IdeDev->BlkIo.Media->BlockSize = 0x800; + } + + if (IdeDev->Type == IdeMagnetic) { + + if (FormatData.DesCode == 3) { + IdeDev->BlkIo.Media->MediaPresent = FALSE; + IdeDev->BlkIo.Media->LastBlock = 0; + } else { + + IdeDev->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) | + (FormatData.LastLba2 << 16) | + (FormatData.LastLba1 << 8) | + FormatData.LastLba0; + if (IdeDev->BlkIo.Media->LastBlock != 0) { + IdeDev->BlkIo.Media->LastBlock--; + + IdeDev->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) | + (FormatData.BlockSize1 << 8) | + FormatData.BlockSize0; + + IdeDev->BlkIo.Media->MediaPresent = TRUE; + } else { + IdeDev->BlkIo.Media->MediaPresent = FALSE; + // + // Return EFI_NOT_READY operation succeeds but returned capacity is 0 + // + return EFI_NOT_READY; + } + + IdeDev->BlkIo.Media->BlockSize = 0x200; + + } + } + } + + return EFI_SUCCESS; + + } else { + return EFI_DEVICE_ERROR; + } +} +/** + This function is used to test the current media write-protected or not residing + in the LS-120 drive or ZIP drive. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param WriteProtected if True, current media is write protected. + if FALSE, current media is writable + + @retval EFI_SUCCESS The media write-protected status is achieved successfully + @retval EFI_DEVICE_ERROR Get Media Status Command is failed. +**/ +EFI_STATUS +IsLS120orZipWriteProtected ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT BOOLEAN *WriteProtected + ) +{ + EFI_STATUS Status; + + *WriteProtected = FALSE; + + Status = LS120EnableMediaStatus (IdeDev, TRUE); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // the Get Media Status Command is only valid + // if a Set Features/Enable Media Status Command has been priviously issued. + // + if (LS120GetMediaStatus (IdeDev) == EFI_WRITE_PROTECTED) { + + *WriteProtected = TRUE; + } else { + + *WriteProtected = FALSE; + } + + // + // After Get Media Status Command completes, + // Set Features/Disable Media Command should be sent. + // + Status = LS120EnableMediaStatus (IdeDev, FALSE); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Used before read/write blocks from/to ATAPI device media. Since ATAPI device + media is removable, it is necessary to detect whether media is present and + get current present media's information, and if media has been changed, Block + I/O Protocol need to be reinstalled. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param MediaChange return value that indicates if the media of the device has been + changed. + + @retval EFI_SUCCESS media found successfully. + @retval EFI_DEVICE_ERROR any error encounters during media detection. + @retval EFI_NO_MEDIA media not found. + + @note + parameter IdeDev may be updated in this function. + +**/ +EFI_STATUS +AtapiDetectMedia ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT BOOLEAN *MediaChange + ) +{ + EFI_STATUS Status; + EFI_STATUS CleanStateStatus; + EFI_BLOCK_IO_MEDIA OldMediaInfo; + UINTN RetryTimes; + UINTN RetryNotReady; + SENSE_RESULT SResult; + BOOLEAN WriteProtected; + + CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (EFI_BLOCK_IO_MEDIA)); + *MediaChange = FALSE; + // + // Retry for SenseDeviceNotReadyNeedRetry. + // Each retry takes 1s and we limit the upper boundary to + // 120 times about 2 min. + // + RetryNotReady = 120; + + // + // Do Test Unit Ready + // + DoTUR: + // + // Retry 5 times + // + RetryTimes = 5; + while (RetryTimes != 0) { + + Status = AtapiTestUnitReady (IdeDev, &SResult); + + if (EFI_ERROR (Status)) { + // + // Test Unit Ready error without sense data. + // For some devices, this means there's extra data + // that has not been read, so we read these extra + // data out before going on. + // + CleanStateStatus = AtapiReadPendingData (IdeDev); + if (EFI_ERROR (CleanStateStatus)) { + // + // Busy wait failed, try again + // + RetryTimes--; + } + // + // Try again without counting down RetryTimes + // + continue; + } else { + switch (SResult) { + case SenseNoSenseKey: + if (IdeDev->BlkIo.Media->MediaPresent) { + goto Done; + } else { + // + // Media present but the internal structure need refreshed. + // Try Read Capacity + // + goto DoRC; + } + break; + + case SenseDeviceNotReadyNeedRetry: + if (--RetryNotReady == 0) { + return EFI_DEVICE_ERROR; + } + gBS->Stall (1000 * STALL_1_MILLI_SECOND); + continue; + break; + + case SenseNoMedia: + IdeDev->BlkIo.Media->MediaPresent = FALSE; + IdeDev->BlkIo.Media->LastBlock = 0; + goto Done; + break; + + case SenseDeviceNotReadyNoRetry: + case SenseMediaError: + return EFI_DEVICE_ERROR; + + case SenseMediaChange: + IdeDev->BlkIo.Media->MediaId++; + goto DoRC; + break; + + default: + RetryTimes--; + break; + } + } + } + + return EFI_DEVICE_ERROR; + + // + // Do Read Capacity + // + DoRC: + RetryTimes = 5; + + while (RetryTimes != 0) { + + Status = AtapiReadCapacity (IdeDev, &SResult); + + if (EFI_ERROR (Status)) { + RetryTimes--; + continue; + } else { + switch (SResult) { + case SenseNoSenseKey: + goto Done; + break; + + case SenseDeviceNotReadyNeedRetry: + // + // We use Test Unit Ready to retry which + // is faster. + // + goto DoTUR; + break; + + case SenseNoMedia: + IdeDev->BlkIo.Media->MediaPresent = FALSE; + IdeDev->BlkIo.Media->LastBlock = 0; + goto Done; + break; + + case SenseDeviceNotReadyNoRetry: + case SenseMediaError: + return EFI_DEVICE_ERROR; + + case SenseMediaChange: + IdeDev->BlkIo.Media->MediaId++; + continue; + break; + + default: + RetryTimes--; + break; + } + } + } + + return EFI_DEVICE_ERROR; + + Done: + // + // the following code is to check the write-protected for LS120 media + // + if ((IdeDev->BlkIo.Media->MediaPresent) && (IdeDev->Type == IdeMagnetic)) { + + Status = IsLS120orZipWriteProtected (IdeDev, &WriteProtected); + if (!EFI_ERROR (Status)) { + + if (WriteProtected) { + + IdeDev->BlkIo.Media->ReadOnly = TRUE; + } else { + + IdeDev->BlkIo.Media->ReadOnly = FALSE; + } + + } + } + + if (IdeDev->BlkIo.Media->MediaId != OldMediaInfo.MediaId) { + // + // Media change information got from the device + // + *MediaChange = TRUE; + } + + if (IdeDev->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) { + *MediaChange = TRUE; + IdeDev->BlkIo.Media->MediaId += 1; + } + + if (IdeDev->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) { + *MediaChange = TRUE; + IdeDev->BlkIo.Media->MediaId += 1; + } + + if (IdeDev->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) { + *MediaChange = TRUE; + IdeDev->BlkIo.Media->MediaId += 1; + } + + if (IdeDev->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) { + if (IdeDev->BlkIo.Media->MediaPresent) { + // + // when change from no media to media present, reset the MediaId to 1. + // + IdeDev->BlkIo.Media->MediaId = 1; + } else { + // + // when no media, reset the MediaId to zero. + // + IdeDev->BlkIo.Media->MediaId = 0; + } + + *MediaChange = TRUE; + } + + // + // if any change on current existing media, + // the Block I/O protocol need to be reinstalled. + // + if (*MediaChange) { + gBS->ReinstallProtocolInterface ( + IdeDev->Handle, + &gEfiBlockIoProtocolGuid, + &IdeDev->BlkIo, + &IdeDev->BlkIo + ); + } + + if (IdeDev->BlkIo.Media->MediaPresent) { + return EFI_SUCCESS; + } else { + return EFI_NO_MEDIA; + } +} + +/** + This function is called by the AtapiBlkIoReadBlocks() to perform + read from media in block unit. + + The main command used to access media here is READ(10) Command. + READ(10) Command requests that the ATAPI device media transfer + specified data to the host. Data is transferred in block(sector) + unit. The maximum number of blocks that can be transferred once is + 65536. This is the main difference between READ(10) and READ(12) + Command. The maximum number of blocks in READ(12) is 2 power 32. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Buffer A pointer to the destination buffer for the data. + @param Lba The starting logical block address to read from on the + device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtapiPacketCommandIn() function. + +**/ +EFI_STATUS +AtapiReadSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +{ + + ATAPI_PACKET_COMMAND Packet; + ATAPI_READ10_CMD *Read10Packet; + EFI_STATUS Status; + UINTN BlocksRemaining; + UINT32 Lba32; + UINT32 BlockSize; + UINT32 ByteCount; + UINT16 SectorCount; + VOID *PtrBuffer; + UINT16 MaxBlock; + UINTN TimeOut; + + // + // fill command packet for Read(10) command + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Read10Packet = &Packet.Read10; + Lba32 = (UINT32) Lba; + PtrBuffer = Buffer; + + BlockSize = IdeDev->BlkIo.Media->BlockSize; + + // + // limit the data bytes that can be transferred by one Read(10) Command + // + MaxBlock = 65535; + + BlocksRemaining = NumberOfBlocks; + + Status = EFI_SUCCESS; + while (BlocksRemaining > 0) { + + if (BlocksRemaining <= MaxBlock) { + + SectorCount = (UINT16) BlocksRemaining; + } else { + + SectorCount = MaxBlock; + } + + // + // fill the Packet data structure + // + + Read10Packet->opcode = ATA_CMD_READ_10; + + // + // Lba0 ~ Lba3 specify the start logical block address of the data transfer. + // Lba0 is MSB, Lba3 is LSB + // + Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff); + Read10Packet->Lba2 = (UINT8) (Lba32 >> 8); + Read10Packet->Lba1 = (UINT8) (Lba32 >> 16); + Read10Packet->Lba0 = (UINT8) (Lba32 >> 24); + + // + // TranLen0 ~ TranLen1 specify the transfer length in block unit. + // TranLen0 is MSB, TranLen is LSB + // + Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff); + Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8); + + ByteCount = SectorCount * BlockSize; + + if (IdeDev->Type == IdeCdRom) { + TimeOut = CDROMLONGTIMEOUT; + } else { + TimeOut = ATAPILONGTIMEOUT; + } + + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) PtrBuffer, + ByteCount, + TimeOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba32 += SectorCount; + PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize; + BlocksRemaining -= SectorCount; + } + + return Status; +} + +/** + This function is called by the AtapiBlkIoWriteBlocks() to perform + write onto media in block unit. + The main command used to access media here is Write(10) Command. + Write(10) Command requests that the ATAPI device media transfer + specified data to the host. Data is transferred in block (sector) + unit. The maximum number of blocks that can be transferred once is + 65536. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Buffer A pointer to the source buffer for the data. + @param Lba The starting logical block address to write onto + the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtapiPacketCommandOut() function. + +**/ +EFI_STATUS +AtapiWriteSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +{ + + ATAPI_PACKET_COMMAND Packet; + ATAPI_READ10_CMD *Read10Packet; + + EFI_STATUS Status; + UINTN BlocksRemaining; + UINT32 Lba32; + UINT32 BlockSize; + UINT32 ByteCount; + UINT16 SectorCount; + VOID *PtrBuffer; + UINT16 MaxBlock; + + // + // fill command packet for Write(10) command + // Write(10) command packet has the same data structure as + // Read(10) command packet, + // so here use the Read10Packet data structure + // for the Write(10) command packet. + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Read10Packet = &Packet.Read10; + + Lba32 = (UINT32) Lba; + PtrBuffer = Buffer; + + BlockSize = IdeDev->BlkIo.Media->BlockSize; + + // + // limit the data bytes that can be transferred by one Read(10) Command + // + MaxBlock = (UINT16) (65536 / BlockSize); + + BlocksRemaining = NumberOfBlocks; + + Status = EFI_SUCCESS; + while (BlocksRemaining > 0) { + + if (BlocksRemaining >= MaxBlock) { + SectorCount = MaxBlock; + } else { + SectorCount = (UINT16) BlocksRemaining; + } + + // + // Command code is WRITE_10. + // + Read10Packet->opcode = ATA_CMD_WRITE_10; + + // + // Lba0 ~ Lba3 specify the start logical block address of the data transfer. + // Lba0 is MSB, Lba3 is LSB + // + Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff); + Read10Packet->Lba2 = (UINT8) (Lba32 >> 8); + Read10Packet->Lba1 = (UINT8) (Lba32 >> 16); + Read10Packet->Lba0 = (UINT8) (Lba32 >> 24); + + // + // TranLen0 ~ TranLen1 specify the transfer length in block unit. + // TranLen0 is MSB, TranLen is LSB + // + Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff); + Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8); + + ByteCount = SectorCount * BlockSize; + + Status = AtapiPacketCommandOut ( + IdeDev, + &Packet, + (UINT16 *) PtrBuffer, + ByteCount, + ATAPILONGTIMEOUT + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba32 += SectorCount; + PtrBuffer = ((UINT8 *) PtrBuffer + SectorCount * BlockSize); + BlocksRemaining -= SectorCount; + } + + return Status; +} +/** + This function is used to implement the Soft Reset on the specified + ATAPI device. Different from the AtaSoftReset(), here reset is a ATA + Soft Reset Command special for ATAPI device, and it only take effects + on the specified ATAPI device, not on the whole IDE bus. + Since the ATAPI soft reset is needed when device is in exceptional + condition (such as BSY bit is always set ), I think the Soft Reset + command should be sent without waiting for the BSY clear and DRDY + set. + This function is called by IdeBlkIoReset(), + a interface function of Block I/O protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @retval EFI_SUCCESS Soft reset completes successfully. + @retval EFI_DEVICE_ERROR Any step during the reset process is failed. + +**/ +EFI_STATUS +AtapiSoftReset ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + UINT8 Command; + UINT8 DeviceSelect; + EFI_STATUS Status; + + // + // for ATAPI device, no need to wait DRDY ready after device selecting. + // (bit7 and bit5 are both set to 1 for backward compatibility) + // + DeviceSelect = (UINT8) (((BIT7 | BIT5) | (IdeDev->Device << 4))); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); + + Command = ATA_CMD_SOFT_RESET; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, Command); + + // + // BSY cleared is the only status return to the host by the device + // when reset is completed. + // slave device needs at most 31s to clear BSY + // + Status = WaitForBSYClear (IdeDev, 31000); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // stall 5 seconds to make the device status stable + // + gBS->Stall (5000000); + + return EFI_SUCCESS; +} + +/** + This function is the ATAPI implementation for ReadBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the read request is for. + @param Lba The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit + ownership of the memory that data is read into. + + @retval EFI_SUCCESS Read Blocks successfully. + @retval EFI_DEVICE_ERROR Read Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the data buffer is not valid. +**/ +EFI_STATUS +AtapiBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + + BOOLEAN MediaChange; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + // + // ATAPI device media is removable, so it is a must + // to detect media first before read operation + // + MediaChange = FALSE; + Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange); + if (EFI_ERROR (Status)) { + + if (IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + + return Status; + } + // + // Get the intrinsic block size + // + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + + if (IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return EFI_NO_MEDIA; + + } + + if ((MediaId != Media->MediaId) || MediaChange) { + + if (IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return EFI_MEDIA_CHANGED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // if all the parameters are valid, then perform read sectors command + // to transfer data from device to host. + // + Status = AtapiReadSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Read blocks succeeded + // + + // + // save the first block to the cache for performance + // + if (Lba == 0 && (IdeBlkIoDevice->Cache == NULL)) { + IdeBlkIoDevice->Cache = AllocatePool (BlockSize); + if (IdeBlkIoDevice->Cache!= NULL) { + CopyMem ((UINT8 *) IdeBlkIoDevice->Cache, (UINT8 *) Buffer, BlockSize); + } + } + + return EFI_SUCCESS; + +} +/** + This function is the ATAPI implementation for WriteBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the write request is for. + @param Lba The starting logical block address to write onto the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the source buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the memory that data is written from. + + @retval EFI_SUCCESS Write Blocks successfully. + @retval EFI_DEVICE_ERROR Write Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the data buffer is not valid. + + @retval EFI_WRITE_PROTECTED The write protected is enabled or the media does not support write +**/ +EFI_STATUS +AtapiBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + BOOLEAN MediaChange; + + if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + // + // ATAPI device media is removable, + // so it is a must to detect media first before write operation + // + MediaChange = FALSE; + Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange); + if (EFI_ERROR (Status)) { + + if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return Status; + } + + // + // Get the intrinsic block size + // + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + + if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return EFI_NO_MEDIA; + } + + if ((MediaId != Media->MediaId) || MediaChange) { + + if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return EFI_MEDIA_CHANGED; + } + + if (Media->ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // if all the parameters are valid, + // then perform write sectors command to transfer data from host to device. + // + Status = AtapiWriteSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + +} + + + diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c new file mode 100644 index 0000000000..5e376d72d7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c @@ -0,0 +1,278 @@ +/** @file + UEFI Component Name(2) protocol implementation for ConPlatform 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 "IdeBus.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName = { + IDEBusComponentNameGetDriverName, + IDEBusComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIDEBusComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IDEBusComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IDEBusComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIDEBusDriverNameTable[] = { + { "eng;en", (CHAR16 *) L"PCI IDE/ATAPI Bus Driver" }, + { NULL , NULL } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIDEBusControllerNameTable[] = { + { "eng;en", (CHAR16 *) L"PCI IDE/ATAPI Controller" }, + { 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 +IDEBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mIDEBusDriverNameTable, + DriverName, + (BOOLEAN)(This == &gIDEBusComponentName) + ); +} + +/** + 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 +IDEBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + // + // Make sure this driver is currently managing ControllHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gIDEBusDriverBinding.DriverBindingHandle, + &gEfiIdeControllerInitProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (ChildHandle == NULL) { + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mIDEBusControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gIDEBusComponentName) + ); + } + + Status = EfiTestChildHandle ( + ControllerHandle, + ChildHandle, + &gEfiPciIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the child context + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gIDEBusDriverBinding.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlockIo); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + IdeBlkIoDevice->ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gIDEBusComponentName) + ); +} + +/** + Add the component name for the IDE/ATAPI device + + @param IdeBlkIoDevicePtr A pointer to the IDE_BLK_IO_DEV instance. + +**/ +VOID +AddName ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr + ) +{ + UINTN StringIndex; + CHAR16 ModelName[41]; + + // + // Add Component Name for the IDE/ATAPI device that was discovered. + // + IdeBlkIoDevicePtr->ControllerNameTable = NULL; + for (StringIndex = 0; StringIndex < 41; StringIndex++) { + ModelName[StringIndex] = IdeBlkIoDevicePtr->ModelName[StringIndex]; + } + + AddUnicodeString2 ( + "eng", + gIDEBusComponentName.SupportedLanguages, + &IdeBlkIoDevicePtr->ControllerNameTable, + ModelName, + TRUE + ); + AddUnicodeString2 ( + "en", + gIDEBusComponentName2.SupportedLanguages, + &IdeBlkIoDevicePtr->ControllerNameTable, + ModelName, + FALSE + ); + +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h new file mode 100644 index 0000000000..9a911a5ec9 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h @@ -0,0 +1,166 @@ +/** @file + + UEFI Component Name(2) protocol implementation header file for IDE Bus 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. + +**/ + +#ifndef _IDE_BUS_COMPONENT_NAME_H_ +#define _IDE_BUS_COMPONENT_NAME_H_ + +#define ADD_IDE_ATAPI_NAME(x) AddName ((x)); + +extern EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gIDEBusComponentName2; + + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +IDEBusComponentNameGetDriverName ( + 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 +IDEBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +/** + Add the component name for the IDE/ATAPI device + + @param IdeBlkIoDevicePtr A pointer to the IDE_BLK_IO_DEV instance. + +**/ +VOID +AddName ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c new file mode 100644 index 0000000000..999e20e016 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c @@ -0,0 +1,292 @@ +/** @file + Implementation of UEFI Driver Configuration Protocol for IDE bus driver which + provides ability to set IDE bus controller specific options. + + Copyright (c) 2006 - 2008, Intel 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 "IdeBus.h" + +CHAR16 *OptionString[4] = { + L"Enable Primary Master (Y/N)? -->", + L"Enable Primary Slave (Y/N)? -->", + L"Enable Secondary Master (Y/N)? -->", + L"Enable Secondary Slave (Y/N)? -->" +}; + +// +// EFI Driver Configuration Protocol +// +EFI_DRIVER_CONFIGURATION_PROTOCOL gIDEBusDriverConfiguration = { + IDEBusDriverConfigurationSetOptions, + IDEBusDriverConfigurationOptionsValid, + IDEBusDriverConfigurationForceDefaults, + "eng" +}; + +/** + Interprete keyboard input. + + @retval EFI_ABORTED Get an 'ESC' key inputed. + @retval EFI_SUCCESS Get an 'Y' or 'y' inputed. + @retval EFI_NOT_FOUND Get an 'N' or 'n' inputed.. + +**/ +EFI_STATUS +GetResponse ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + + while (TRUE) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (!EFI_ERROR (Status)) { + if (Key.ScanCode == SCAN_ESC) { + return EFI_ABORTED; + } + + switch (Key.UnicodeChar) { + + // + // fall through + // + case L'y': + case L'Y': + gST->ConOut->OutputString (gST->ConOut, L"Y\n"); + return EFI_SUCCESS; + + // + // fall through + // + case L'n': + case L'N': + gST->ConOut->OutputString (gST->ConOut, L"N\n"); + return EFI_NOT_FOUND; + } + + } + } +} + +/** + Allows the user to set controller specific options for a controller that a + driver is currently managing. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to set options on. + @param ChildHandle The handle of the child controller to set options on. + This is an optional parameter that may be NULL. + It will be NULL for device drivers, and for a bus drivers + that wish to set options for the bus controller. + It will not be NULL for a bus driver that wishes to set + options for one of its child controllers. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the user interface that should be presented + to the user, 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 ActionRequired A pointer to the action that the calling agent is required + to perform when this function returns. + + + @retval EFI_SUCCESS The driver specified by This successfully set the configuration + options for the controller specified by ControllerHandle.. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support setting configuration options for + the controller specified by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the language specified by Language. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the configuration options for the + controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to set the configuration options for the + controller specified by ControllerHandle and ChildHandle +**/ +EFI_STATUS +EFIAPI +IDEBusDriverConfigurationSetOptions ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ) +{ + EFI_STATUS Status; + UINT8 Value; + UINT8 NewValue; + UINTN DataSize; + UINTN Index; + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + *ActionRequired = EfiDriverConfigurationActionNone; + + DataSize = sizeof (Value); + Status = gRT->GetVariable ( + L"Configuration", + &gEfiCallerIdGuid, + NULL, + &DataSize, + &Value + ); + + gST->ConOut->OutputString (gST->ConOut, L"IDE Bus Driver Configuration\n"); + gST->ConOut->OutputString (gST->ConOut, L"===============================\n"); + + NewValue = 0; + for (Index = 0; Index < 4; Index++) { + gST->ConOut->OutputString (gST->ConOut, OptionString[Index]); + + Status = GetResponse (); + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + if (!EFI_ERROR (Status)) { + NewValue = (UINT8) (NewValue | (1 << Index)); + } + } + + if (EFI_ERROR (Status) || (NewValue != Value)) { + gRT->SetVariable ( + L"Configuration", + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (NewValue), + &NewValue + ); + + *ActionRequired = EfiDriverConfigurationActionRestartController; + } else { + *ActionRequired = EfiDriverConfigurationActionNone; + } + + return EFI_SUCCESS; +} + +/** + Tests to see if a controller's current configuration options are valid. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test if it's current configuration options + are valid. + @param ChildHandle The handle of the child controller to test if it's current configuration + options are valid. 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 test the configuration options for the bus controller. It will + not be NULL for a bus driver that wishes to test configuration options for + one of its child controllers. + @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle that is being + managed by the driver specified by This has a valid set of configuration + options. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing the controller + specified by ControllerHandle and ChildHandle. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle that is being + managed by the driver specified by This has an invalid set of configuration + options. +**/ +EFI_STATUS +EFIAPI +IDEBusDriverConfigurationOptionsValid ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ) +{ + EFI_STATUS Status; + UINT8 Value; + UINTN DataSize; + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + DataSize = sizeof (Value); + Status = gRT->GetVariable ( + L"Configuration", + &gEfiCallerIdGuid, + NULL, + &DataSize, + &Value + ); + if (EFI_ERROR (Status) || Value > 0x0f) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} +/** + Forces a driver to set the default configuration options for a controller. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to force default configuration options on. + @param ChildHandle The handle of the child controller to force default configuration + options on 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 force default configuration options for the bus + controller. It will not be NULL for a bus driver that wishes to force + default configuration options for one of its child controllers. + @param DefaultType The type of default configuration options to force on the controller + specified by ControllerHandle and ChildHandle. + @param ActionRequired A pointer to the action that the calling agent is required to perform + when this function returns. + + @retval EFI_SUCCESS The driver specified by This successfully forced the + default configuration options on the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default + configuration options on the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type + specified by DefaultType. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration + options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration + options on the controller specified by ControllerHandle and ChildHandle. +**/ +EFI_STATUS +EFIAPI +IDEBusDriverConfigurationForceDefaults ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ) +{ + UINT8 Value; + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + Value = 0x0f; + gRT->SetVariable ( + L"Configuration", + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Value), + &Value + ); + *ActionRequired = EfiDriverConfigurationActionRestartController; + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c new file mode 100644 index 0000000000..73435dd7ac --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c @@ -0,0 +1,245 @@ +/** @file + Implementation of UEFI driver Dialnostics protocol which to perform diagnostic on the IDE + Bus controller. + + 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 "IdeBus.h" + +#define IDE_BUS_DIAGNOSTIC_ERROR L"PCI IDE/ATAPI Driver Diagnostics Failed" + +// +// EFI Driver Diagnostics Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics = { + IDEBusDriverDiagnosticsRunDiagnostics, + "eng" +}; + +// +// EFI Driver Diagnostics 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gIDEBusDriverDiagnostics2 = { + (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) IDEBusDriverDiagnosticsRunDiagnostics, + "en" +}; + +/** + Runs diagnostics on a controller. + + @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance. + @param ControllerHandle The handle of the controller to run diagnostics on. + @param ChildHandle The handle of the child controller to run diagnostics on + 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 run diagnostics on the bus controller. + It will not be NULL for a bus driver that wishes to run + diagnostics on one of its child controllers. + @param DiagnosticType Indicates type of diagnostics to perform on the controller + specified by ControllerHandle and ChildHandle. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language in which the optional error message should + be returned in Buffer, 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 ErrorType A GUID that defines the format of the data returned in Buffer. + @param BufferSize The size, in bytes, of the data returned in Buffer. + @param Buffer A buffer that contains a Null-terminated Unicode string + plus some additional data whose format is defined by ErrorType. + Buffer is allocated by this function with AllocatePool(), and + it is the caller's responsibility to free it with a call to FreePool(). + + @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle passed + the diagnostic. + @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 ErrorType is NULL. + @retval EFI_INVALID_PARAMETER BufferType is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support running + diagnostics for the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + @retval EFI_UNSUPPORTED The driver specified by This does not support the language + specified by Language. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete the + diagnostics. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return the + status information in ErrorType, BufferSize,and Buffer. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle + did not pass the diagnostic. +**/ +EFI_STATUS +EFIAPI +IDEBusDriverDiagnosticsRunDiagnostics ( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + IDE_BLK_IO_DEV *IdeBlkIoDevice; + UINT32 VendorDeviceId; + VOID *BlockBuffer; + CHAR8 *SupportedLanguages; + BOOLEAN Iso639Language; + BOOLEAN Found; + UINTN Index; + + if (Language == NULL || + ErrorType == NULL || + Buffer == NULL || + ControllerHandle == NULL || + BufferSize == NULL) { + + return EFI_INVALID_PARAMETER; + } + + SupportedLanguages = This->SupportedLanguages; + Iso639Language = (BOOLEAN)(This == &gIDEBusDriverDiagnostics); + // + // Make sure Language is in the set of Supported Languages + // + Found = FALSE; + while (*SupportedLanguages != 0) { + if (Iso639Language) { + if (CompareMem (Language, SupportedLanguages, 3) == 0) { + Found = TRUE; + break; + } + SupportedLanguages += 3; + } else { + for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++); + if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) { + Found = TRUE; + break; + } + SupportedLanguages += Index; + for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++); + } + } + // + // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED + // + if (!Found) { + return EFI_UNSUPPORTED; + } + + *ErrorType = NULL; + *BufferSize = 0; + + if (ChildHandle == NULL) { + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiCallerIdGuid, + NULL, + gIDEBusDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + gIDEBusDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Use services of PCI I/O Protocol to test the PCI IDE/ATAPI Controller + // The following test simply reads the Device ID and Vendor ID. + // It should never fail. A real test would perform more advanced + // diagnostics. + // + + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &VendorDeviceId); + if (EFI_ERROR (Status) || VendorDeviceId == 0xffffffff) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + } + + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + gIDEBusDriverBinding.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); + + // + // Use services available from IdeBlkIoDevice to test the IDE/ATAPI device + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + IdeBlkIoDevice->BlkMedia.BlockSize, + (VOID **) &BlockBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IdeBlkIoDevice->BlkIo.ReadBlocks ( + &IdeBlkIoDevice->BlkIo, + IdeBlkIoDevice->BlkMedia.MediaId, + 0, + IdeBlkIoDevice->BlkMedia.BlockSize, + BlockBuffer + ); + + if (EFI_ERROR (Status)) { + *ErrorType = &gEfiCallerIdGuid; + *BufferSize = sizeof (IDE_BUS_DIAGNOSTIC_ERROR); + + Status = gBS->AllocatePool ( + EfiBootServicesData, + (UINTN) (*BufferSize), + (VOID **) Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + CopyMem (*Buffer, IDE_BUS_DIAGNOSTIC_ERROR, *BufferSize); + + Status = EFI_DEVICE_ERROR; + } + + gBS->FreePool (BlockBuffer); + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c new file mode 100644 index 0000000000..ffc818036a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c @@ -0,0 +1,1330 @@ +/** @file + The file ontaining the helper functions implement of the Ide Bus driver + + Copyright (c) 2006 - 2008, Intel 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 "IdeBus.h" + +BOOLEAN ChannelDeviceDetected = FALSE; +BOOLEAN SlaveDeviceExist = FALSE; +UINT8 SlaveDeviceType = INVALID_DEVICE_TYPE; +BOOLEAN MasterDeviceExist = FALSE; +UINT8 MasterDeviceType = INVALID_DEVICE_TYPE; + +/** + read a one-byte data from a IDE port. + + @param PciIo The PCI IO protocol instance + @param Port the IDE Port number + + @return the one-byte data read from IDE port +**/ +UINT8 +IDEReadPortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +{ + UINT8 Data; + + Data = 0; + // + // perform 1-byte data read from register + // + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + return Data; +} +/** + Reads multiple words of data from the IDE data port. + Call the IO abstraction once to do the complete read, + not one word at a time + + @param PciIo Pointer to the EFI_PCI_IO instance + @param Port IO port to read + @param Count No. of UINT16's to read + @param Buffer Pointer to the data buffer for read + +**/ +VOID +IDEReadPortWMultiple ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT16 *AlignedBuffer; + UINT16 *WorkingBuffer; + UINTN Size; + + // + // Prepare an 16-bit alligned working buffer. CpuIo will return failure and + // not perform actual I/O operations if buffer pointer passed in is not at + // natural boundary. The "Buffer" argument is passed in by user and may not + // at 16-bit natural boundary. + // + Size = sizeof (UINT16) * Count; + + gBS->AllocatePool ( + EfiBootServicesData, + Size + 1, + (VOID**)&WorkingBuffer + ); + + AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1))); + + // + // Perform UINT16 data read from FIFO + // + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthFifoUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + Count, + (UINT16*)AlignedBuffer + ); + + // + // Copy data to user buffer + // + CopyMem (Buffer, (UINT16*)AlignedBuffer, Size); + gBS->FreePool (WorkingBuffer); +} + +/** + write a 1-byte data to a specific IDE port. + + @param PciIo PCI IO protocol instance + @param Port The IDE port to be writen + @param Data The data to write to the port +**/ +VOID +IDEWritePortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT8 Data + ) +{ + // + // perform 1-byte data write to register + // + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + +} + +/** + write a 1-word data to a specific IDE port. + + @param PciIo PCI IO protocol instance + @param Port The IDE port to be writen + @param Data The data to write to the port +**/ +VOID +IDEWritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT16 Data + ) +{ + // + // perform 1-word data write to register + // + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); +} + +/** + Write multiple words of data to the IDE data port. + Call the IO abstraction once to do the complete read, + not one word at a time + + @param PciIo Pointer to the EFI_PCI_IO instance + @param Port IO port to read + @param Count No. of UINT16's to read + @param Buffer Pointer to the data buffer for read + +**/ +VOID +IDEWritePortWMultiple ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT16 *AlignedBuffer; + UINT32 *WorkingBuffer; + UINTN Size; + + // + // Prepare an 16-bit alligned working buffer. CpuIo will return failure and + // not perform actual I/O operations if buffer pointer passed in is not at + // natural boundary. The "Buffer" argument is passed in by user and may not + // at 16-bit natural boundary. + // + Size = sizeof (UINT16) * Count; + + gBS->AllocatePool ( + EfiBootServicesData, + Size + 1, + (VOID **) &WorkingBuffer + ); + + AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1))); + + // + // Copy data from user buffer to working buffer + // + CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size); + + // + // perform UINT16 data write to the FIFO + // + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthFifoUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + Count, + (UINT16 *) AlignedBuffer + ); + + gBS->FreePool (WorkingBuffer); +} +/** + Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode, + use fixed addresses. In Native-PCI mode, get base addresses from BARs in + the PCI IDE controller's Configuration Space. + + The steps to get IDE IO port registers' base addresses for each channel + as follows: + + 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE + controller's Configuration Space to determine the operating mode. + + 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below. +
+  ___________________________________________
+  |           | Command Block | Control Block |
+  |  Channel  |   Registers   |   Registers   |
+  |___________|_______________|_______________|
+  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |
+  |___________|_______________|_______________|
+  | Secondary |  170h - 177h  |  376h - 377h  |
+  |___________|_______________|_______________|
+
+  Table 1. Compatibility resource mappings
+  
+ + b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs + in IDE controller's PCI Configuration Space, shown in the Table 2 below. +
+  ___________________________________________________
+  |           |   Command Block   |   Control Block   |
+  |  Channel  |     Registers     |     Registers     |
+  |___________|___________________|___________________|
+  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|
+  |___________|___________________|___________________|
+  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
+  |___________|___________________|___________________|
+
+  Table 2. BARs for Register Mapping
+  
+ @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for + primary, 0374h for secondary. So 2 bytes extra offset should be + added to the base addresses read from BARs. + + For more details, please refer to PCI IDE Controller Specification and Intel + ICH4 Datasheet. + + @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance + @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to + receive IDE IO port registers' base addresses + + @retval EFI_UNSUPPORTED return this value when the BARs is not IO type + @retval EFI_SUCCESS Get the Base address successfully + @retval other read the pci configureation data error + +**/ +EFI_STATUS +GetIdeRegistersBaseAddr ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr + ) +{ + EFI_STATUS Status; + PCI_TYPE00 PciData; + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + sizeof (PciData), + &PciData + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) { + IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0; + IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6; + IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr = + (UINT16)((PciData.Device.Bar[4] & 0x0000fff0)); + } else { + // + // The BARs should be of IO type + // + if ((PciData.Device.Bar[0] & BIT0) == 0 || + (PciData.Device.Bar[1] & BIT0) == 0) { + return EFI_UNSUPPORTED; + } + + IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = + (UINT16) (PciData.Device.Bar[0] & 0x0000fff8); + IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = + (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2); + IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr = + (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); + } + + if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) { + IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170; + IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376; + IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr = + (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); + } else { + // + // The BARs should be of IO type + // + if ((PciData.Device.Bar[2] & BIT0) == 0 || + (PciData.Device.Bar[3] & BIT0) == 0) { + return EFI_UNSUPPORTED; + } + + IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = + (UINT16) (PciData.Device.Bar[2] & 0x0000fff8); + IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = + (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2); + IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr = + (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); + } + + return EFI_SUCCESS; +} + +/** + This function is used to requery IDE resources. The IDE controller will + probably switch between native and legacy modes during the EFI->CSM->OS + transfer. We do this everytime before an BlkIo operation to ensure its + succeess. + + @param IdeDev The BLK_IO private data which specifies the IDE device + + @retval EFI_INVALID_PARAMETER return this value when the channel is invalid + @retval EFI_SUCCESS reassign the IDE IO resource successfully + @retval other get the IDE current base address effor + +**/ +EFI_STATUS +ReassignIdeResources ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_STATUS Status; + IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; + UINT16 CommandBlockBaseAddr; + UINT16 ControlBlockBaseAddr; + + if (IdeDev->Channel >= IdeMaxChannel) { + return EFI_INVALID_PARAMETER; + } + + // + // Requery IDE IO port registers' base addresses in case of the switch of + // native and legacy modes + // + Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS)); + CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr; + ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr; + + IdeDev->IoPort->Data = CommandBlockBaseAddr; + (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); + IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); + IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); + IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); + IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); + IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); + + (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); + (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr; + IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); + IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0); + + IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr; + return EFI_SUCCESS; +} + +/** + This function is called by DiscoverIdeDevice(). It is used for detect + whether the IDE device exists in the specified Channel as the specified + Device Number. + + There is two IDE channels: one is Primary Channel, the other is + Secondary Channel.(Channel is the logical name for the physical "Cable".) + Different channel has different register group. + + On each IDE channel, at most two IDE devices attach, + one is called Device 0 (Master device), the other is called Device 1 + (Slave device). The devices on the same channel co-use the same register + group, so before sending out a command for a specified device via command + register, it is a must to select the current device to accept the command + by set the device number in the Head/Device Register. + + @param IdeDev pointer to IDE_BLK_IO_DEV data structure, used to record all the + information of the IDE device. + + @retval EFI_SUCCESS successfully detects device. + + @retval other any failure during detection process will return this value. + +**/ +EFI_STATUS +DetectIDEController ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_STATUS Status; + UINT8 SectorCountReg; + UINT8 LBALowReg; + UINT8 LBAMidReg; + UINT8 LBAHighReg; + UINT8 InitStatusReg; + UINT8 StatusReg; + + // + // Select slave device + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((1 << 4) | 0xe0) + ); + gBS->Stall (100); + + // + // Save the init slave status register + // + InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // Select Master back + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((0 << 4) | 0xe0) + ); + gBS->Stall (100); + + // + // Send ATA Device Execut Diagnostic command. + // This command should work no matter DRDY is ready or not + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90); + + Status = WaitForBSYClear (IdeDev, 3500); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status)); + return Status; + } + // + // Read device signature + // + // + // Select Master + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((0 << 4) | 0xe0) + ); + gBS->Stall (100); + SectorCountReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->SectorCount + ); + LBALowReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->SectorNumber + ); + LBAMidReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderLsb + ); + LBAHighReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderMsb + ); + if ((SectorCountReg == 0x1) && + (LBALowReg == 0x1) && + (LBAMidReg == 0x0) && + (LBAHighReg == 0x0)) { + MasterDeviceExist = TRUE; + MasterDeviceType = ATA_DEVICE_TYPE; + } else { + if ((LBAMidReg == 0x14) && + (LBAHighReg == 0xeb)) { + MasterDeviceExist = TRUE; + MasterDeviceType = ATAPI_DEVICE_TYPE; + } + } + + // + // For some Hard Drive, it takes some time to get + // the right signature when operating in single slave mode. + // We stall 20ms to work around this. + // + if (!MasterDeviceExist) { + gBS->Stall (20000); + } + + // + // Select Slave + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((1 << 4) | 0xe0) + ); + gBS->Stall (100); + SectorCountReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->SectorCount + ); + LBALowReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->SectorNumber + ); + LBAMidReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderLsb + ); + LBAHighReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderMsb + ); + StatusReg = IDEReadPortB ( + IdeDev->PciIo, + IdeDev->IoPort->Reg.Status + ); + if ((SectorCountReg == 0x1) && + (LBALowReg == 0x1) && + (LBAMidReg == 0x0) && + (LBAHighReg == 0x0)) { + SlaveDeviceExist = TRUE; + SlaveDeviceType = ATA_DEVICE_TYPE; + } else { + if ((LBAMidReg == 0x14) && + (LBAHighReg == 0xeb)) { + SlaveDeviceExist = TRUE; + SlaveDeviceType = ATAPI_DEVICE_TYPE; + } + } + + // + // When single master is plugged, slave device + // will be wrongly detected. Here's the workaround + // for ATA devices by detecting DRY bit in status + // register. + // NOTE: This workaround doesn't apply to ATAPI. + // + if (MasterDeviceExist && SlaveDeviceExist && + (StatusReg & ATA_STSREG_DRDY) == 0 && + (InitStatusReg & ATA_STSREG_DRDY) == 0 && + MasterDeviceType == SlaveDeviceType && + SlaveDeviceType != ATAPI_DEVICE_TYPE) { + SlaveDeviceExist = FALSE; + } + + // + // Indicate this channel has been detected + // + ChannelDeviceDetected = TRUE; + return EFI_SUCCESS; +} +/** + Detect if there is disk attached to this port + + @param IdeDev The BLK_IO private data which specifies the IDE device. + + @retval EFI_NOT_FOUND The device or channel is not found + @retval EFI_SUCCESS The device is found + +**/ +EFI_STATUS +DiscoverIdeDevice ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_STATUS Status; + EFI_STATUS LongPhyStatus; + + // + // If a channel has not been checked, check it now. Then set it to "checked" state + // After this step, all devices in this channel have been checked. + // + if (!ChannelDeviceDetected) { + Status = DetectIDEController (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } + + Status = EFI_NOT_FOUND; + + // + // Device exists. test if it is an ATA device. + // Prefer the result from DetectIDEController, + // if failed, try another device type to handle + // devices that not follow the spec. + // + if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) { + if (MasterDeviceType == ATA_DEVICE_TYPE) { + Status = ATAIdentify (IdeDev); + if (EFI_ERROR (Status)) { + Status = ATAPIIdentify (IdeDev); + if (!EFI_ERROR (Status)) { + MasterDeviceType = ATAPI_DEVICE_TYPE; + } + } + } else { + Status = ATAPIIdentify (IdeDev); + if (EFI_ERROR (Status)) { + Status = ATAIdentify (IdeDev); + if (!EFI_ERROR (Status)) { + MasterDeviceType = ATA_DEVICE_TYPE; + } + } + } + } + if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) { + if (SlaveDeviceType == ATA_DEVICE_TYPE) { + Status = ATAIdentify (IdeDev); + if (EFI_ERROR (Status)) { + Status = ATAPIIdentify (IdeDev); + if (!EFI_ERROR (Status)) { + SlaveDeviceType = ATAPI_DEVICE_TYPE; + } + } + } else { + Status = ATAPIIdentify (IdeDev); + if (EFI_ERROR (Status)) { + Status = ATAIdentify (IdeDev); + if (!EFI_ERROR (Status)) { + SlaveDeviceType = ATA_DEVICE_TYPE; + } + } + } + } + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Init Block I/O interface + // + LongPhyStatus = AtaEnableLongPhysicalSector (IdeDev); + if (!EFI_ERROR (LongPhyStatus)) { + IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; + } else { + IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + } + IdeDev->BlkIo.Reset = IDEBlkIoReset; + IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks; + IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks; + IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks; + + IdeDev->BlkMedia.LogicalPartition = FALSE; + IdeDev->BlkMedia.WriteCaching = FALSE; + + // + // Init Disk Info interface + // + gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID)); + IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry; + IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify; + IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData; + IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde; + + return EFI_SUCCESS; +} + +/** + This interface is used to initialize all state data related to the detection of one + channel. +**/ +VOID +InitializeIDEChannelData ( + VOID + ) +{ + ChannelDeviceDetected = FALSE; + MasterDeviceExist = FALSE; + MasterDeviceType = 0xff; + SlaveDeviceExist = FALSE; + SlaveDeviceType = 0xff; +} +/** + This function is used to poll for the DRQ bit clear in the Status + Register. DRQ is cleared when the device is finished transferring data. + So this function is called after data transfer is finished. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. + + @retval EFI_SUCCESS DRQ bit clear within the time out. + + @retval EFI_TIMEOUT DRQ bit not clear within the time out. + + @note + Read Status Register will clear interrupt status. + +**/ +EFI_STATUS +DRQClear ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +{ + UINT32 Delay; + UINT8 StatusRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // wait for BSY == 0 and DRQ == 0 + // + if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) { + break; + } + + if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} +/** + This function is used to poll for the DRQ bit clear in the Alternate + Status Register. DRQ is cleared when the device is finished + transferring data. So this function is called after data transfer + is finished. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. + + @retval EFI_SUCCESS DRQ bit clear within the time out. + + @retval EFI_TIMEOUT DRQ bit not clear within the time out. + @note Read Alternate Status Register will not clear interrupt status. + +**/ +EFI_STATUS +DRQClear2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +{ + UINT32 Delay; + UINT8 AltRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + + // + // wait for BSY == 0 and DRQ == 0 + // + if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) { + break; + } + + if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + This function is used to poll for the DRQ bit set in the + Status Register. + DRQ is set when the device is ready to transfer data. So this function + is called after the command is sent to the device and before required + data is transferred. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to + record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRQ bit set within the time out. + @retval EFI_TIMEOUT DRQ bit not set within the time out. + @retval EFI_ABORTED DRQ bit not set caused by the command abort. + + @note Read Status Register will clear interrupt status. + +**/ +EFI_STATUS +DRQReady ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +{ + UINT32 Delay; + UINT8 StatusRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + // + // read Status Register will clear interrupt + // + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // BSY==0,DRQ==1 + // + if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { + break; + } + + if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} +/** + This function is used to poll for the DRQ bit set in the Alternate Status Register. + DRQ is set when the device is ready to transfer data. So this function is called after + the command is sent to the device and before required data is transferred. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to + record all the information of the IDE device. + + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRQ bit set within the time out. + @retval EFI_TIMEOUT DRQ bit not set within the time out. + @retval EFI_ABORTED DRQ bit not set caused by the command abort. + @note Read Alternate Status Register will not clear interrupt status. + +**/ +EFI_STATUS +DRQReady2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +{ + UINT32 Delay; + UINT8 AltRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + + do { + // + // Read Alternate Status Register will not clear interrupt status + // + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + // + // BSY == 0 , DRQ == 1 + // + if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { + break; + } + + if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + This function is used to poll for the BSY bit clear in the Status Register. BSY + is clear when the device is not busy. Every command must be sent after device is not busy. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS BSY bit clear within the time out. + @retval EFI_TIMEOUT BSY bit not clear within the time out. + + @note Read Status Register will clear interrupt status. +**/ +EFI_STATUS +WaitForBSYClear ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +{ + UINT32 Delay; + UINT8 StatusRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + if ((StatusRegister & ATA_STSREG_BSY) == 0x00) { + break; + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} +/** + This function is used to poll for the BSY bit clear in the Alternate Status Register. + BSY is clear when the device is not busy. Every command must be sent after device is + not busy. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS BSY bit clear within the time out. + @retval EFI_TIMEOUT BSY bit not clear within the time out. + @note Read Alternate Status Register will not clear interrupt status. + +**/ +EFI_STATUS +WaitForBSYClear2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +{ + UINT32 Delay; + UINT8 AltRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + if ((AltRegister & ATA_STSREG_BSY) == 0x00) { + break; + } + + gBS->Stall (30); + + Delay--; + + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} +/** + This function is used to poll for the DRDY bit set in the Status Register. DRDY + bit is set when the device is ready to accept command. Most ATA commands must be + sent after DRDY set except the ATAPI Packet Command. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRDY bit set within the time out. + @retval EFI_TIMEOUT DRDY bit not set within the time out. + + @note Read Status Register will clear interrupt status. +**/ +EFI_STATUS +DRDYReady ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN DelayInMilliSeconds + ) +{ + UINT32 Delay; + UINT8 StatusRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + // + // BSY == 0 , DRDY == 1 + // + if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) { + break; + } + + if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + } + + gBS->Stall (30); + + Delay--; + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} +/** + This function is used to poll for the DRDY bit set in the Alternate Status Register. + DRDY bit is set when the device is ready to accept command. Most ATA commands must + be sent after DRDY set except the ATAPI Packet Command. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRDY bit set within the time out. + @retval EFI_TIMEOUT DRDY bit not set within the time out. + + @note Read Alternate Status Register will clear interrupt status. + +**/ +EFI_STATUS +DRDYReady2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN DelayInMilliSeconds + ) +{ + UINT32 Delay; + UINT8 AltRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + // + // BSY == 0 , DRDY == 1 + // + if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) { + break; + } + + if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + } + + gBS->Stall (30); + + Delay--; + } while (Delay > 0); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} +/** + Release resources of an IDE device before stopping it. + + @param IdeBlkIoDevice Standard IDE device private data structure + +**/ +VOID +ReleaseIdeResources ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice + ) +{ + if (IdeBlkIoDevice == NULL) { + return ; + } + + // + // Release all the resourses occupied by the IDE_BLK_IO_DEV + // + + if (IdeBlkIoDevice->SenseData != NULL) { + gBS->FreePool (IdeBlkIoDevice->SenseData); + IdeBlkIoDevice->SenseData = NULL; + } + + if (IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + + if (IdeBlkIoDevice->IdData != NULL) { + gBS->FreePool (IdeBlkIoDevice->IdData); + IdeBlkIoDevice->IdData = NULL; + } + + if (IdeBlkIoDevice->InquiryData != NULL) { + gBS->FreePool (IdeBlkIoDevice->InquiryData); + IdeBlkIoDevice->InquiryData = NULL; + } + + if (IdeBlkIoDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable); + IdeBlkIoDevice->ControllerNameTable = NULL; + } + + if (IdeBlkIoDevice->IoPort != NULL) { + gBS->FreePool (IdeBlkIoDevice->IoPort); + } + + if (IdeBlkIoDevice->DevicePath != NULL) { + gBS->FreePool (IdeBlkIoDevice->DevicePath); + } + + if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) { + gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent); + IdeBlkIoDevice->ExitBootServiceEvent = NULL; + } + + gBS->FreePool (IdeBlkIoDevice); + IdeBlkIoDevice = NULL; + + return ; +} +/** + Set the calculated Best transfer mode to a detected device. + + @param IdeDev Standard IDE device private data structure + @param TransferMode The device transfer mode to be set + @return Set transfer mode Command execute status. + +**/ +EFI_STATUS +SetDeviceTransferMode ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATA_TRANSFER_MODE *TransferMode + ) +{ + EFI_STATUS Status; + UINT8 DeviceSelect; + UINT8 SectorCount; + + DeviceSelect = 0; + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + SectorCount = *((UINT8 *) TransferMode); + + // + // Send SET FEATURE command (sub command 0x03) to set pio mode. + // + Status = AtaNonDataCommandIn ( + IdeDev, + ATA_CMD_SET_FEATURES, + DeviceSelect, + 0x03, + SectorCount, + 0, + 0, + 0 + ); + + return Status; +} +/** + Set drive parameters for devices not support PACKETS command. + + @param IdeDev Standard IDE device private data structure + @param DriveParameters The device parameters to be set into the disk + @return SetParameters Command execute status. + +**/ +EFI_STATUS +SetDriveParameters ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATA_DRIVE_PARMS *DriveParameters + ) +{ + EFI_STATUS Status; + UINT8 DeviceSelect; + + DeviceSelect = 0; + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + + // + // Send Init drive parameters + // + Status = AtaNonDataCommandIn ( + IdeDev, + ATA_CMD_INIT_DRIVE_PARAM, + (UINT8) (DeviceSelect + DriveParameters->Heads), + 0, + DriveParameters->Sector, + 0, + 0, + 0 + ); + + // + // Send Set Multiple parameters + // + Status = AtaNonDataCommandIn ( + IdeDev, + ATA_CMD_SET_MULTIPLE_MODE, + DeviceSelect, + 0, + DriveParameters->MultipleSector, + 0, + 0, + 0 + ); + return Status; +} + +/** + Enable Interrupt on IDE controller. + + @param IdeDev Standard IDE device private data structure + + @retval EFI_SUCCESS Enable Interrupt successfully +**/ +EFI_STATUS +EnableInterrupt ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + UINT8 DeviceControl; + + // + // Enable interrupt for DMA operation + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h new file mode 100644 index 0000000000..2b7e6ea5eb --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h @@ -0,0 +1,835 @@ +/** @file + Header file for IDE Bus Driver, containing the helper functions' + prototype. + + Copyright (c) 2006 - 2007, Intel 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. + + @par Revision Reference: + 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including + Add - IDEBlkIoReadBlocksExt() func definition + Add - IDEBlkIoWriteBlocksExt() func definition + +**/ + +#ifndef _IDE_H_ +#define _IDE_H_ + +// +// Helper functions Prototype +// +/** + read a one-byte data from a IDE port. + + @param PciIo The PCI IO protocol instance + @param Port the IDE Port number + + return the one-byte data read from IDE port +**/ +UINT8 +IDEReadPortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ); + +/** + Reads multiple words of data from the IDE data port. + Call the IO abstraction once to do the complete read, + not one word at a time. + + @param PciIo Pointer to the EFI_PCI_IO instance + @param Port IO port to read + @param Count No. of UINT16's to read + @param Buffer Pointer to the data buffer for read + +**/ +VOID +IDEReadPortWMultiple ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + write a 1-byte data to a specific IDE port. + + @param PciIo PCI IO protocol instance + @param Port The IDE port to be writen + @param Data The data to write to the port +**/ +VOID +IDEWritePortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT8 Data + ); + +/** + write a 1-word data to a specific IDE port. + + @param PciIo PCI IO protocol instance + @param Port The IDE port to be writen + @param Data The data to write to the port +**/ +VOID +IDEWritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT16 Data + ); + +/** + Write multiple words of data to the IDE data port. + Call the IO abstraction once to do the complete read, + not one word at a time. + + @param PciIo Pointer to the EFI_PCI_IO instance + @param Port IO port to read + @param Count No. of UINT16's to read + @param Buffer Pointer to the data buffer for read + +**/ +VOID +IDEWritePortWMultiple ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode, + use fixed addresses. In Native-PCI mode, get base addresses from BARs in + the PCI IDE controller's Configuration Space. + + The steps to get IDE IO port registers' base addresses for each channel + as follows: + + 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE + controller's Configuration Space to determine the operating mode. + + 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below. +
+  ___________________________________________
+  |           | Command Block | Control Block |
+  |  Channel  |   Registers   |   Registers   |
+  |___________|_______________|_______________|
+  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |
+  |___________|_______________|_______________|
+  | Secondary |  170h - 177h  |  376h - 377h  |
+  |___________|_______________|_______________|
+
+  Table 1. Compatibility resource mappings
+  
+ + b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs + in IDE controller's PCI Configuration Space, shown in the Table 2 below. +
+  ___________________________________________________
+  |           |   Command Block   |   Control Block   |
+  |  Channel  |     Registers     |     Registers     |
+  |___________|___________________|___________________|
+  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|
+  |___________|___________________|___________________|
+  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
+  |___________|___________________|___________________|
+
+  Table 2. BARs for Register Mapping
+  
+ @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for + primary, 0374h for secondary. So 2 bytes extra offset should be + added to the base addresses read from BARs. + + For more details, please refer to PCI IDE Controller Specification and Intel + ICH4 Datasheet. + + @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance + @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to + receive IDE IO port registers' base addresses + + @retval EFI_UNSUPPORTED return this value when the BARs is not IO type + @retval EFI_SUCCESS Get the Base address successfully + @retval other read the pci configureation data error + +**/ +EFI_STATUS +GetIdeRegistersBaseAddr ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr + ); + +/** + This function is used to requery IDE resources. The IDE controller will + probably switch between native and legacy modes during the EFI->CSM->OS + transfer. We do this everytime before an BlkIo operation to ensure its + succeess. + + @param IdeDev The BLK_IO private data which specifies the IDE device + + @retval EFI_INVALID_PARAMETER return this value when the channel is invalid + @retval EFI_SUCCESS reassign the IDE IO resource successfully + @retval other get the IDE current base address effor + +**/ +EFI_STATUS +ReassignIdeResources ( + IN IDE_BLK_IO_DEV *IdeDev + ); + +/** + Detect if there is disk attached to this port. + + @param IdeDev The BLK_IO private data which specifies the IDE device. + + @retval EFI_NOT_FOUND The device or channel is not found + @retval EFI_SUCCESS The device is found + +**/ +EFI_STATUS +DiscoverIdeDevice ( + IN IDE_BLK_IO_DEV *IdeDev + ); + +/** + This interface is used to initialize all state data related to the + detection of one channel. + +**/ +VOID +InitializeIDEChannelData ( + VOID + ); + +/** + This function is used to poll for the DRQ bit clear in the Status + Register. DRQ is cleared when the device is finished transferring data. + So this function is called after data transfer is finished. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. + + @retval EFI_SUCCESS DRQ bit clear within the time out. + + @retval EFI_TIMEOUT DRQ bit not clear within the time out. + + @note + Read Status Register will clear interrupt status. + +**/ +EFI_STATUS +DRQClear ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ); + +/** + This function is used to poll for the DRQ bit clear in the Alternate + Status Register. DRQ is cleared when the device is finished + transferring data. So this function is called after data transfer + is finished. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. + + @retval EFI_SUCCESS DRQ bit clear within the time out. + + @retval EFI_TIMEOUT DRQ bit not clear within the time out. + @note + Read Alternate Status Register will not clear interrupt status. + +**/ +EFI_STATUS +DRQClear2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ); + +/** + This function is used to poll for the DRQ bit set in the + Status Register. + DRQ is set when the device is ready to transfer data. So this function + is called after the command is sent to the device and before required + data is transferred. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to + record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRQ bit set within the time out. + @retval EFI_TIMEOUT DRQ bit not set within the time out. + @retval EFI_ABORTED DRQ bit not set caused by the command abort. + + @note Read Status Register will clear interrupt status. + +**/ +EFI_STATUS +DRQReady ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ); + +/** + This function is used to poll for the DRQ bit set in the Alternate Status Register. + DRQ is set when the device is ready to transfer data. So this function is called after + the command is sent to the device and before required data is transferred. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to + record all the information of the IDE device. + + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRQ bit set within the time out. + @retval EFI_TIMEOUT DRQ bit not set within the time out. + @retval EFI_ABORTED DRQ bit not set caused by the command abort. + @note Read Alternate Status Register will not clear interrupt status. + +**/ +EFI_STATUS +DRQReady2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ); + +/** + This function is used to poll for the BSY bit clear in the Status Register. BSY + is clear when the device is not busy. Every command must be sent after device is not busy. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS BSY bit clear within the time out. + @retval EFI_TIMEOUT BSY bit not clear within the time out. + + @note Read Status Register will clear interrupt status. +**/ +EFI_STATUS +WaitForBSYClear ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ); + +/** + This function is used to poll for the BSY bit clear in the Alternate Status Register. + BSY is clear when the device is not busy. Every command must be sent after device is + not busy. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS BSY bit clear within the time out. + @retval EFI_TIMEOUT BSY bit not clear within the time out. + @note Read Alternate Status Register will not clear interrupt status. + +**/ +EFI_STATUS +WaitForBSYClear2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ); + +/** + This function is used to poll for the DRDY bit set in the Status Register. DRDY + bit is set when the device is ready to accept command. Most ATA commands must be + sent after DRDY set except the ATAPI Packet Command. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRDY bit set within the time out. + @retval EFI_TIMEOUT DRDY bit not set within the time out. + + @note Read Status Register will clear interrupt status. +**/ +EFI_STATUS +DRDYReady ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN DelayInMilliSeconds + ); + +/** + This function is used to poll for the DRDY bit set in the Alternate Status Register. + DRDY bit is set when the device is ready to accept command. Most ATA commands must + be sent after DRDY set except the ATAPI Packet Command. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRDY bit set within the time out. + @retval EFI_TIMEOUT DRDY bit not set within the time out. + + @note Read Alternate Status Register will clear interrupt status. + +**/ +EFI_STATUS +DRDYReady2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN DelayInMilliSeconds + ); + +// +// ATA device functions' prototype +// +/** + Sends out an ATA Identify Command to the specified device. + + This function is called by DiscoverIdeDevice() during its device + identification. It sends out the ATA Identify Command to the + specified device. Only ATA device responses to this command. If + the command succeeds, it returns the Identify data structure which + contains information about the device. This function extracts the + information it needs to fill the IDE_BLK_IO_DEV data structure, + including device type, media block size, media capacity, and etc. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record + all the information of the IDE device. + + @retval EFI_SUCCESS Identify ATA device successfully. + @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device. + @note parameter IdeDev will be updated in this function. + +**/ +EFI_STATUS +ATAIdentify ( + IN IDE_BLK_IO_DEV *IdeDev + ); + +/** + This function is called by ATAIdentify() or ATAPIIdentify() to print device's module name. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. +**/ +VOID +PrintAtaModuleName ( + IN IDE_BLK_IO_DEV *IdeDev + ); +/** + This function is used to send out ATA commands conforms to the PIO Data In Protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param Buffer buffer contained data transferred from device to host. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param Head value of the Head/Device Register + @param SectorCount value of the Sector Count Register + @param SectorNumber value of the Sector Number Register + @param CylinderLsb value of the low byte of the Cylinder Register + @param CylinderMsb value of the high byte of the Cylinder Register + + @retval EFI_SUCCESS send out the ATA command and device send required data successfully. + @retval EFI_DEVICE_ERROR command sent failed. + +**/ +EFI_STATUS +AtaPioDataIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN UINT8 Head, + IN UINT8 SectorCount, + IN UINT8 SectorNumber, + IN UINT8 CylinderLsb, + IN UINT8 CylinderMsb + ); + +/** + This function is used to send out ATA commands conforms to the + PIO Data Out Protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param *Buffer buffer contained data transferred from host to device. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param Head value of the Head/Device Register + @param SectorCount value of the Sector Count Register + @param SectorNumber value of the Sector Number Register + @param CylinderLsb value of the low byte of the Cylinder Register + @param CylinderMsb value of the high byte of the Cylinder Register + + @retval EFI_SUCCESS send out the ATA command and device received required + data successfully. + @retval EFI_DEVICE_ERROR command sent failed. + +**/ +EFI_STATUS +AtaPioDataOut ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN UINT8 Head, + IN UINT8 SectorCount, + IN UINT8 SectorNumber, + IN UINT8 CylinderLsb, + IN UINT8 CylinderMsb + ); + +/** + This function is used to analyze the Status Register and print out + some debug information and if there is ERR bit set in the Status + Register, the Error Register's value is also be parsed and print out. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to + record all the information of the IDE device. + + @retval EFI_SUCCESS No err information in the Status Register. + @retval EFI_DEVICE_ERROR Any err information in the Status Register. + +**/ +EFI_STATUS +CheckErrorStatus ( + IN IDE_BLK_IO_DEV *IdeDev + ); + +/** + This function is used to implement the Soft Reset on the specified device. But, + the ATA Soft Reset mechanism is so strong a reset method that it will force + resetting on both devices connected to the same cable. + + It is called by IdeBlkIoReset(), a interface function of Block + I/O protocol. + + This function can also be used by the ATAPI device to perform reset when + ATAPI Reset command is failed. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @retval EFI_SUCCESS Soft reset completes successfully. + @retval EFI_DEVICE_ERROR Any step during the reset process is failed. + + @note The registers initial values after ATA soft reset are different + to the ATA device and ATAPI device. +**/ +EFI_STATUS +AtaSoftReset ( + IN IDE_BLK_IO_DEV *IdeDev + ); + +/** + This function is the ATA implementation for ReadBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the read request is for. + @param Lba The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + + @param Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the memory that data is read into. + + @retval EFI_SUCCESS Read Blocks successfully. + @retval EFI_DEVICE_ERROR Read Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the data buffer is not valid. + + @note If Read Block error because of device error, this function will call + AtaSoftReset() function to reset device. + +**/ +EFI_STATUS +AtaBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + This function is the ATA implementation for WriteBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the write request is for. + @param Lba The starting logical block address to write onto the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the source buffer for the data.The caller + is responsible for either having implicit or explicit + ownership of the memory that data is written from. + + @retval EFI_SUCCESS Write Blocks successfully. + @retval EFI_DEVICE_ERROR Write Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the data buffer is not valid. + + @note If Write Block error because of device error, this function will call + AtaSoftReset() function to reset device. +**/ +EFI_STATUS +AtaBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + This function is called by DiscoverIdeDevice() during its device + identification. + Its main purpose is to get enough information for the device media + to fill in the Media data structure of the Block I/O Protocol interface. + + There are 5 steps to reach such objective: + 1. Sends out the ATAPI Identify Command to the specified device. + Only ATAPI device responses to this command. If the command succeeds, + it returns the Identify data structure which filled with information + about the device. Since the ATAPI device contains removable media, + the only meaningful information is the device module name. + 2. Sends out ATAPI Inquiry Packet Command to the specified device. + This command will return inquiry data of the device, which contains + the device type information. + 3. Allocate sense data space for future use. We don't detect the media + presence here to improvement boot performance, especially when CD + media is present. The media detection will be performed just before + each BLK_IO read/write + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @retval EFI_SUCCESS Identify ATAPI device successfully. + @retval EFI_DEVICE_ERROR ATAPI Identify Device Command failed or device type + is not supported by this IDE driver. + @retval EFI_OUT_OF_RESOURCES Allocate memory for sense data failed + + @note Parameter "IdeDev" will be updated in this function. +**/ +EFI_STATUS +ATAPIIdentify ( + IN IDE_BLK_IO_DEV *IdeDev + ); + +/** + This function is used to implement the Soft Reset on the specified + ATAPI device. Different from the AtaSoftReset(), here reset is a ATA + Soft Reset Command special for ATAPI device, and it only take effects + on the specified ATAPI device, not on the whole IDE bus. + Since the ATAPI soft reset is needed when device is in exceptional + condition (such as BSY bit is always set ), I think the Soft Reset + command should be sent without waiting for the BSY clear and DRDY + set. + This function is called by IdeBlkIoReset(), + a interface function of Block I/O protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + @retval EFI_SUCCESS Soft reset completes successfully. + @retval EFI_DEVICE_ERROR Any step during the reset process is failed. + +**/ +EFI_STATUS +AtapiSoftReset ( + IN IDE_BLK_IO_DEV *IdeDev + ); + +/** + This function is the ATAPI implementation for ReadBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the read request is for. + @param Lba The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit + ownership of the memory that data is read into. + + @retval EFI_SUCCESS Read Blocks successfully. + @retval EFI_DEVICE_ERROR Read Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the data buffer is not valid. +**/ +EFI_STATUS +AtapiBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + This function is the ATAPI implementation for WriteBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the write request is for. + @param Lba The starting logical block address to write onto the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the source buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the memory that data is written from. + + @retval EFI_SUCCESS Write Blocks successfully. + @retval EFI_DEVICE_ERROR Write Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the data buffer is not valid. + + @retval EFI_WRITE_PROTECTED The write protected is enabled or the media does not support write +**/ +EFI_STATUS +AtapiBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Release resources of an IDE device before stopping it. + + @param IdeBlkIoDevice Standard IDE device private data structure + +**/ +VOID +ReleaseIdeResources ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice + ); + +/** + Set the calculated Best transfer mode to a detected device + + @param IdeDev Standard IDE device private data structure + @param TransferMode The device transfer mode to be set + @return Set transfer mode Command execute status. +**/ +EFI_STATUS +SetDeviceTransferMode ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATA_TRANSFER_MODE *TransferMode + ); +/** + Send ATA command into device with NON_DATA protocol. + + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaLow The value in LBA_LOW register + @param LbaMiddle The value in LBA_MIDDLE register + @param LbaHigh The value in LBA_HIGH register + + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. + +**/ +EFI_STATUS +AtaNonDataCommandIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT8 Feature, + IN UINT8 SectorCount, + IN UINT8 LbaLow, + IN UINT8 LbaMiddle, + IN UINT8 LbaHigh + ); + +/** + Send ATA Ext command into device with NON_DATA protocol. + + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaAddress The Lba address in 48-bit mode + + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. + +**/ +EFI_STATUS +AtaNonDataCommandInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ); +/** + Enable Long Physical Sector Feature for ATA device. + + @param IdeDev The IDE device data + + @retval EFI_SUCCESS The ATA device supports Long Physical Sector feature + and corresponding fields in BlockIo structure is updated. + @retval EFI_UNSUPPORTED The device is not ATA device or Long Physical Sector + feature is not supported. +**/ +EFI_STATUS +AtaEnableLongPhysicalSector ( + IN IDE_BLK_IO_DEV *IdeDev + ); + +/** + Set drive parameters for devices not support PACKETS command. + + @param IdeDev Standard IDE device private data structure + @param DriveParameters The device parameters to be set into the disk + @return SetParameters Command execute status. + +**/ +EFI_STATUS +SetDriveParameters ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATA_DRIVE_PARMS *DriveParameters + ); + +/** + Enable Interrupt on IDE controller. + + @param IdeDev Standard IDE device private data structure + + @retval EFI_SUCCESS Enable Interrupt successfully +**/ +EFI_STATUS +EnableInterrupt ( + IN IDE_BLK_IO_DEV *IdeDev + ); +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c new file mode 100644 index 0000000000..82fd44f17d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c @@ -0,0 +1,1571 @@ +/** @file + This file implement UEFI driver for IDE Bus which includes device identification, + Child device(Disk, CDROM, etc) enumeration and child handler installation, and + driver stop. + + 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 + 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. + + @par Revision Reference: + This module is modified from DXE\IDE module for Ide Contriller Init support + +**/ + +#include "IdeBus.h" + +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_SUB_CLASS_IDE 0x01 + + +// +// IDE Bus Driver Binding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = { + IDEBusDriverBindingSupported, + IDEBusDriverBindingStart, + IDEBusDriverBindingStop, + 0xa, + NULL, + NULL +}; +/** + Deregister an IDE device and free resources + + @param This Protocol instance pointer. + @param Controller Ide device handle + @param Handle Handle of device to deregister driver on + + @retval EFI_SUCCESS Deregiter a specific IDE device successfully + + +**/ +EFI_STATUS +DeRegisterIdeDevice ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + IDE_BLK_IO_DEV *IdeBlkIoDevice; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); + + // + // Report Status code: Device disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE), + IdeBlkIoDevice->DevicePath + ); + + // + // Close the child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Handle, + &gEfiDevicePathProtocolGuid, + IdeBlkIoDevice->DevicePath, + &gEfiBlockIoProtocolGuid, + &IdeBlkIoDevice->BlkIo, + &gEfiDiskInfoProtocolGuid, + &IdeBlkIoDevice->DiskInfo, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + return Status; + } + + // + // Release allocated resources + // + Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device; + if (Index < MAX_IDE_DEVICE) { + IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE; + } + ReleaseIdeResources (IdeBlkIoDevice); + + return EFI_SUCCESS; +} +/** + Supported function of Driver Binding protocol for this driver. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS Driver loaded. + @retval other Driver not loaded. + +**/ +EFI_STATUS +EFIAPI +IDEBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_DEV_PATH *Node; + EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 PciData; + + if (RemainingDevicePath != NULL) { + Node = (EFI_DEV_PATH *) RemainingDevicePath; + // + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, go on checking other conditions + // + if (!IsDevicePathEnd (Node)) { + // + // If RemainingDevicePath isn't the End of Device Path Node, + // check its validation + // + if (Node->DevPath.Type != MESSAGING_DEVICE_PATH || + Node->DevPath.SubType != MSG_ATAPI_DP || + DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } + } + + // + // Verify the Ide Controller Init Protocol, which installed by the + // IdeController module. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + (VOID **) &IdeInit, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Open the EFI Device Path protocol needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + // + // Close protocol, don't use device path protocol in the Support() function + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Get the EfiPciIoProtocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Now further check the PCI header: Base class (offset 0x0B) and + // Sub Class (offset 0x0A). This controller should be an IDE controller + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + sizeof (PciData), + &PciData + ); + + if (!EFI_ERROR (Status)) { + // + // Examine if it is IDE mode by class code + // + if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) || (PciData.Hdr.ClassCode[1] != PCI_SUB_CLASS_IDE)) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_SUCCESS; + } + } + + return Status; +} + + +/** + Start function of Driver binding protocol which start this driver on Controller + by detecting all disks and installing BlockIo protocol on them. + + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to. + @param RemainingDevicePath produce all possible children. + + @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 +IDEBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_STATUS SavedStatus; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_DEV_PATH *Node; + UINT8 IdeChannel; + UINT8 BeginningIdeChannel; + UINT8 EndIdeChannel; + UINT8 IdeDevice; + UINT8 BeginningIdeDevice; + UINT8 EndIdeDevice; + IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice]; + IDE_BLK_IO_DEV *IdeBlkIoDevicePtr; + IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; + ATA_TRANSFER_MODE TransferMode; + ATA_DRIVE_PARMS DriveParameters; + EFI_DEV_PATH NewNode; + UINT8 ConfigurationOptions; + UINT16 CommandBlockBaseAddr; + UINT16 ControlBlockBaseAddr; + UINTN DataSize; + IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; + UINT64 Supports; + + // + // Local variables declaration for IdeControllerInit support + // + EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; + BOOLEAN EnumAll; + BOOLEAN ChannelEnabled; + UINT8 MaxDevices; + EFI_IDENTIFY_DATA IdentifyData; + EFI_ATA_COLLECTIVE_MODE *SupportedModes; + + IdeBusDriverPrivateData = NULL; + SupportedModes = NULL; + + // + // Perform IdeBus initialization + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { + return Status; + } + + // + // Now open the IDE_CONTROLLER_INIT protocol. Step7.1 + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + (VOID **) &IdeInit, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + // + // The following OpenProtocol function with _GET_PROTOCOL attribute and + // will not return EFI_ALREADY_STARTED, so save it for now + // + SavedStatus = Status; + + if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { + DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status)); + // + // open protocol is not SUCCESS or not ALREADY_STARTED, error exit + // + goto ErrorExit; + } + + // + // Save Enumall. Step7.2 + // + EnumAll = IdeInit->EnumAll; + + // + // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL + // attribute will not return EFI_ALREADY_STARTED + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status)); + goto ErrorExit; + } + + // + // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable + // + if (SavedStatus != EFI_ALREADY_STARTED) { + IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); + if (IdeBusDriverPrivateData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiCallerIdGuid, + IdeBusDriverPrivateData, + NULL + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + } else { + Status = gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + (VOID **) &IdeBusDriverPrivateData, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + IdeBusDriverPrivateData = NULL; + goto ErrorExit; + } + } + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + // + // Read the environment variable that contains the IDEBus Driver's + // Config options that were set by the Driver Configuration Protocol + // + DataSize = sizeof (ConfigurationOptions); + Status = gRT->GetVariable ( + (CHAR16 *) L"Configuration", + &gEfiCallerIdGuid, + NULL, + &DataSize, + &ConfigurationOptions + ); + if (EFI_ERROR (Status)) { + ConfigurationOptions = 0x0f; + } + + if (EnumAll || RemainingDevicePath == NULL) { + // + // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL, + // must enumerate all IDE devices anyway + // + BeginningIdeChannel = IdePrimary; + EndIdeChannel = IdeSecondary; + BeginningIdeDevice = IdeMaster; + EndIdeDevice = IdeSlave; + + } else if (!IsDevicePathEnd (RemainingDevicePath)) { + // + // If RemainingDevicePath isn't the End of Device Path Node, + // only scan the specified device by RemainingDevicePath + // + Node = (EFI_DEV_PATH *) RemainingDevicePath; + BeginningIdeChannel = Node->Atapi.PrimarySecondary; + EndIdeChannel = BeginningIdeChannel; + BeginningIdeDevice = Node->Atapi.SlaveMaster; + EndIdeDevice = BeginningIdeDevice; + if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) { + Status = EFI_INVALID_PARAMETER; + goto ErrorExit; + } + if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) { + Status = EFI_INVALID_PARAMETER; + goto ErrorExit; + } + + } else { + // + // If RemainingDevicePath is the End of Device Path Node, + // skip enumerate any device and return EFI_SUCESSS + // + BeginningIdeChannel = IdeMaxChannel; + EndIdeChannel = IdeMaxChannel - 1; + BeginningIdeDevice = IdeMaxDevice; + EndIdeDevice = IdeMaxDevice - 1; + } + + // + // Obtain IDE IO port registers' base addresses + // + Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + // + // Report status code: begin IdeBus initialization + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), + ParentDevicePath + ); + + // + // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol + // + for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { + + IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel); + + // + // now obtain channel information fron IdeControllerInit protocol. Step9 + // + Status = IdeInit->GetChannelInfo ( + IdeInit, + IdeChannel, + &ChannelEnabled, + &MaxDevices + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status)); + continue; + } + + if (!ChannelEnabled) { + continue; + } + + EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice); + ASSERT (EndIdeDevice < IdeMaxDevice); + // + // Now inform the IDE Controller Init Module. Sept10 + // + IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel); + + // + // No reset channel function implemented. Sept11 + // + IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel); + + // + // Step13 + // + IdeInit->NotifyPhase ( + IdeInit, + EfiIdeBusBeforeDevicePresenceDetection, + IdeChannel + ); + + // + // Prepare to detect IDE device of this channel + // + InitializeIDEChannelData (); + + // + // -- 1st inner loop --- Master/Slave ------------ Step14 + // + for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { + // + // Check whether the configuration options allow this device + // + if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) { + continue; + } + + // + // The device has been scanned in another Start(), No need to scan it again + // for perf optimization. + // + if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) { + continue; + } + + // + // create child handle for the detected device. + // + IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV)); + if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) { + continue; + } + + IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; + + ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV)); + + IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE; + IdeBlkIoDevicePtr->Channel = (EFI_IDE_CHANNEL) IdeChannel; + IdeBlkIoDevicePtr->Device = (EFI_IDE_DEVICE) IdeDevice; + + // + // initialize Block IO interface's Media pointer + // + IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia; + + // + // Initialize IDE IO port addresses, including Command Block registers + // and Control Block registers + // + IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS)); + if (IdeBlkIoDevicePtr->IoPort == NULL) { + continue; + } + + ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS)); + CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr; + ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr; + + IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr; + (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); + IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); + IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); + IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); + IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); + IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); + (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); + + (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr; + IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); + + IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0); + + IdeBlkIoDevicePtr->PciIo = PciIo; + IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData; + IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr; + + // + // Report Status code: is about to detect IDE drive + // + REPORT_STATUS_CODE_EX ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT), + 0, + &gEfiCallerIdGuid, + NULL, + NULL, + 0 + ); + + // + // Discover device, now! + // + PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0); + Status = DiscoverIdeDevice (IdeBlkIoDevicePtr); + PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0); + + IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE; + IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE; + + if (!EFI_ERROR (Status)) { + // + // Set Device Path + // + ZeroMem (&NewNode, sizeof (NewNode)); + NewNode.DevPath.Type = MESSAGING_DEVICE_PATH; + NewNode.DevPath.SubType = MSG_ATAPI_DP; + SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH)); + + NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel; + NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device; + NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun; + IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode ( + ParentDevicePath, + &NewNode.DevPath + ); + if (IdeBlkIoDevicePtr->DevicePath == NULL) { + ReleaseIdeResources (IdeBlkIoDevicePtr); + continue; + } + + // + // Submit identify data to IDE controller init driver + // + CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData)); + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE; + IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData); + } else { + // + // Device detection failed + // + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; + IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL); + ReleaseIdeResources (IdeBlkIoDevicePtr); + IdeBlkIoDevicePtr = NULL; + } + // + // end of 1st inner loop --- + // + } + // + // end of 1st outer loop ========= + // + } + + // + // = 2nd outer loop == Primary/Secondary ================= + // + for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { + + // + // -- 2nd inner loop --- Master/Slave -------- + // + for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { + + ASSERT (IdeChannel * 2 + IdeDevice < MAX_IDE_DEVICE); + if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) { + continue; + } + + if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) { + continue; + } + + Status = IdeInit->CalculateMode ( + IdeInit, + IdeChannel, + IdeDevice, + &SupportedModes + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status)); + continue; + } + + ASSERT (IdeChannel < IdeMaxChannel && IdeDevice < IdeMaxDevice); + IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; + + // + // Set best supported PIO mode on this IDE device + // + if (SupportedModes->PioMode.Mode <= AtaPioMode2) { + TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO; + } else { + TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO; + } + + TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode); + + if (SupportedModes->ExtModeCount == 0){ + Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); + + if (EFI_ERROR (Status)) { + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; + ReleaseIdeResources (IdeBlkIoDevicePtr); + IdeBlkIoDevicePtr = NULL; + continue; + } + } + + // + // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't + // be set together. Only one DMA mode can be set to a device. If setting + // DMA mode operation fails, we can continue moving on because we only use + // PIO mode at boot time. DMA modes are used by certain kind of OS booting + // + if (SupportedModes->UdmaMode.Valid) { + + TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA; + TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode); + Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); + + if (EFI_ERROR (Status)) { + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; + ReleaseIdeResources (IdeBlkIoDevicePtr); + IdeBlkIoDevicePtr = NULL; + continue; + } + // + // Record Udma Mode + // + IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE; + IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode; + EnableInterrupt (IdeBlkIoDevicePtr); + } else if (SupportedModes->MultiWordDmaMode.Valid) { + + TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA; + TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode; + Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); + + if (EFI_ERROR (Status)) { + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; + ReleaseIdeResources (IdeBlkIoDevicePtr); + IdeBlkIoDevicePtr = NULL; + continue; + } + + EnableInterrupt (IdeBlkIoDevicePtr); + } + // + // Init driver parameters + // + DriveParameters.Sector = (UINT8) ((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->sectors_per_track; + DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->heads - 1); + DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt; + // + // Set Parameters for the device: + // 1) Init + // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command + // + if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) { + Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters); + } + + // + // Record PIO mode used in private data + // + IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode; + + // + // Set IDE controller Timing Blocks in the PCI Configuration Space + // + IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes); + + // + // Add Component Name for the IDE/ATAPI device that was discovered. + // + IdeBlkIoDevicePtr->ControllerNameTable = NULL; + ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &IdeBlkIoDevicePtr->Handle, + &gEfiDevicePathProtocolGuid, + IdeBlkIoDevicePtr->DevicePath, + &gEfiBlockIoProtocolGuid, + &IdeBlkIoDevicePtr->BlkIo, + &gEfiDiskInfoProtocolGuid, + &IdeBlkIoDevicePtr->DiskInfo, + NULL + ); + + if (EFI_ERROR (Status)) { + ReleaseIdeResources (IdeBlkIoDevicePtr); + } + + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + IdeBlkIoDevicePtr->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + + IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE; + + // + // Report status code: device eanbled! + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE), + IdeBlkIoDevicePtr->DevicePath + ); + + // + // Create event to clear pending IDE interrupt + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ClearInterrupt, + IdeBlkIoDevicePtr, + &gEfiEventExitBootServicesGuid, + &IdeBlkIoDevicePtr->ExitBootServiceEvent + ); + + // + // end of 2nd inner loop ---- + // + } + // + // end of 2nd outer loop ========== + // + } + + // + // All configurations done! Notify IdeController to do post initialization + // work such as saving IDE controller PCI settings for S3 resume + // + IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0); + + if (SupportedModes != NULL) { + FreePool (SupportedModes); + } + + PERF_START (NULL, "Finish IDE detection", "IDE", 1); + PERF_END (NULL, "Finish IDE detection", "IDE", 0); + + return EFI_SUCCESS; + +ErrorExit: + + // + // Report error code: controller error + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR), + ParentDevicePath + ); + + gBS->CloseProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + IdeBusDriverPrivateData, + NULL + ); + + if (IdeBusDriverPrivateData != NULL) { + gBS->FreePool (IdeBusDriverPrivateData); + } + + if (SupportedModes != NULL) { + gBS->FreePool (SupportedModes); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; + +} +/** + Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all + child handle attached to the controller handle if there are. + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on + @param NumberOfChildren Not used + @param ChildHandleBuffer Not used + + @retval EFI_SUCCESS This driver is removed DeviceHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +IDEBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + BOOLEAN AllChildrenStopped; + UINTN Index; + IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; + UINT64 Supports; + + IdeBusDriverPrivateData = NULL; + + if (NumberOfChildren == 0) { + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE); + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, + Supports, + NULL + ); + } + } + + gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + (VOID **) &IdeBusDriverPrivateData, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + IdeBusDriverPrivateData, + NULL + ); + + if (IdeBusDriverPrivateData != NULL) { + gBS->FreePool (IdeBusDriverPrivateData); + } + // + // Close the bus driver + // + gBS->CloseProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]); + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + issue ATA or ATAPI command to reset a block IO device. + @param This Block IO protocol instance pointer. + @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method + If TRUE, for ATAPI device, driver need invoke ATA reset method after + invoke ATAPI reset method + + @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device. + @retval EFI_SUCCESS The device reset successfully + +**/ +EFI_STATUS +EFIAPI +IDEBlkIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + EFI_STATUS Status; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); + // + // Requery IDE IO resources in case of the switch of native and legacy modes + // + ReassignIdeResources (IdeBlkIoDevice); + + // + // for ATA device, using ATA reset method + // + if (IdeBlkIoDevice->Type == IdeHardDisk || + IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + Status = AtaSoftReset (IdeBlkIoDevice); + goto Done; + } + + if (IdeBlkIoDevice->Type == IdeUnknown) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // for ATAPI device, using ATAPI reset method + // + Status = AtapiSoftReset (IdeBlkIoDevice); + if (ExtendedVerification) { + Status = AtaSoftReset (IdeBlkIoDevice); + } + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Read data from a block IO device + + @param This Block IO protocol instance pointer. + @param MediaId The media ID of the device + @param Lba Starting LBA address to read data + @param BufferSize The size of data to be read + @param Buffer Caller supplied buffer to save data + + @retval EFI_DEVICE_ERROR unknown device type + @retval other read data status. + +**/ +EFI_STATUS +EFIAPI +IDEBlkIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + EFI_STATUS Status; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); + + // + // Requery IDE IO resources in case of the switch of native and legacy modes + // + ReassignIdeResources (IdeBlkIoDevice); + + // + // For ATA compatible device, use ATA read block's mechanism + // + if (IdeBlkIoDevice->Type == IdeHardDisk || + IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + Status = AtaBlkIoReadBlocks ( + IdeBlkIoDevice, + MediaId, + Lba, + BufferSize, + Buffer + ); + goto Done; + } + + if (IdeBlkIoDevice->Type == IdeUnknown) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // for ATAPI device, using ATAPI read block's mechanism + // + Status = AtapiBlkIoReadBlocks ( + IdeBlkIoDevice, + MediaId, + Lba, + BufferSize, + Buffer + ); + +Done: + gBS->RestoreTPL (OldTpl); + + return Status; +} + +/** + Write data to block io device. + + @param This Protocol instance pointer. + @param MediaId The media ID of the device + @param Lba Starting LBA address to write data + @param BufferSize The size of data to be written + @param Buffer Caller supplied buffer to save data + + @retval EFI_DEVICE_ERROR unknown device type + @retval other write data status + +**/ +EFI_STATUS +EFIAPI +IDEBlkIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + EFI_STATUS Status; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); + // + // Requery IDE IO resources in case of the switch of native and legacy modes + // + ReassignIdeResources (IdeBlkIoDevice); + + // + // for ATA device, using ATA write block's mechanism + // + if (IdeBlkIoDevice->Type == IdeHardDisk || + IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + + Status = AtaBlkIoWriteBlocks ( + IdeBlkIoDevice, + MediaId, + Lba, + BufferSize, + Buffer + ); + goto Done; + } + + if (IdeBlkIoDevice->Type == IdeUnknown) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // for ATAPI device, using ATAPI write block's mechanism + // + Status = AtapiBlkIoWriteBlocks ( + IdeBlkIoDevice, + MediaId, + Lba, + BufferSize, + Buffer + ); + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} +/** + Flushes all modified data to a physical block devices + + @param This Indicates a pointer to the calling context which to sepcify a + sepcific block device + + @retval EFI_SUCCESS Always return success. +**/ +EFI_STATUS +EFIAPI +IDEBlkIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + // + // return directly + // + return EFI_SUCCESS; +} + +/** + This function is used by the IDE bus driver to get inquiry data. + Data format of Identify data is defined by the Interface GUID. + + @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param InquiryData Pointer to a buffer for the inquiry data. + @param InquiryDataSize Pointer to the value for the inquiry data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading InquiryData from device + @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough + +**/ +EFI_STATUS +EFIAPI +IDEDiskInfoInquiry ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *InquiryData, + IN OUT UINT32 *InquiryDataSize + ) +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); + + if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) { + *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA); + return EFI_BUFFER_TOO_SMALL; + } + + if (IdeBlkIoDevice->InquiryData == NULL) { + return EFI_NOT_FOUND; + } + + gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA)); + *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA); + + return EFI_SUCCESS; +} + +/** + This function is used by the IDE bus driver to get identify data. + Data format of Identify data is defined by the Interface GUID. + + @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param IdentifyData Pointer to a buffer for the identify data. + @param IdentifyDataSize Pointer to the value for the identify data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading IdentifyData from device + @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough + +**/ +EFI_STATUS +EFIAPI +IDEDiskInfoIdentify ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *IdentifyData, + IN OUT UINT32 *IdentifyDataSize + ) +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); + + if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) { + *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA); + return EFI_BUFFER_TOO_SMALL; + } + + if (IdeBlkIoDevice->IdData == NULL) { + return EFI_NOT_FOUND; + } + + gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA)); + *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA); + + return EFI_SUCCESS; +} + +/** + This function is used by the IDE bus driver to get sense data. + Data format of Sense data is defined by the Interface GUID. + + @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param SenseData Pointer to the SenseData. + @param SenseDataSize Size of SenseData in bytes. + @param SenseDataNumber Pointer to the value for the identify data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading InquiryData from device + @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough + +**/ +EFI_STATUS +EFIAPI +IDEDiskInfoSenseData ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *SenseData, + IN OUT UINT32 *SenseDataSize, + OUT UINT8 *SenseDataNumber + ) +{ + return EFI_NOT_FOUND; +} + +/** + This function is used by the IDE bus driver to get controller information. + + @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param IdeChannel Pointer to the Ide Channel number. Primary or secondary. + @param IdeDevice Pointer to the Ide Device number. Master or slave. + + @retval EFI_SUCCESS IdeChannel and IdeDevice are valid + @retval EFI_UNSUPPORTED This is not an IDE device + +**/ +EFI_STATUS +EFIAPI +IDEDiskInfoWhichIde ( + IN EFI_DISK_INFO_PROTOCOL *This, + OUT UINT32 *IdeChannel, + OUT UINT32 *IdeDevice + ) +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); + *IdeChannel = IdeBlkIoDevice->Channel; + *IdeDevice = IdeBlkIoDevice->Device; + + return EFI_SUCCESS; +} + +/** + The is an event(generally the event is exitBootService event) call back function. + Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. + + @param Event Pointer to this event + @param Context Event handler private data + +**/ +VOID +EFIAPI +ClearInterrupt ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINT64 IoPortForBmis; + UINT8 RegisterValue; + IDE_BLK_IO_DEV *IdeDev; + + // + // Get our context + // + IdeDev = (IDE_BLK_IO_DEV *) Context; + + // + // Obtain IDE IO port registers' base addresses + // + Status = ReassignIdeResources (IdeDev); + if (EFI_ERROR (Status)) { + return; + } + + // + // Check whether interrupt is pending + // + + // + // Reset IDE device to force it de-assert interrupt pin + // Note: this will reset all devices on this IDE channel + // + Status = AtaSoftReset (IdeDev); + if (EFI_ERROR (Status)) { + return; + } + + // + // Get base address of IDE Bus Master Status Regsiter + // + if (IdePrimary == IdeDev->Channel) { + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; + } else { + if (IdeSecondary == IdeDev->Channel) { + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; + } else { + return; + } + } + // + // Read BMIS register and clear ERROR and INTR bit + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + // + // Select the other device on this channel to ensure this device to release the interrupt pin + // + if (IdeDev->Device == 0) { + RegisterValue = (1 << 4) | 0xe0; + } else { + RegisterValue = (0 << 4) | 0xe0; + } + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + RegisterValue + ); + +} + +/** + The user Entry Point for module IdeBus. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeIdeBus( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols2 ( + ImageHandle, + SystemTable, + &gIDEBusDriverBinding, + ImageHandle, + &gIDEBusComponentName, + &gIDEBusComponentName2, + NULL, + NULL, + &gIDEBusDriverDiagnostics, + &gIDEBusDriverDiagnostics2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h new file mode 100644 index 0000000000..a3db16ca85 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h @@ -0,0 +1,540 @@ +/** @file + Header file for IDE Bus 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. + +**/ + +#ifndef _IDE_BUS_H_ +#define _IDE_BUS_H_ + + + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "IdeData.h" + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding; +extern EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics; +extern EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gIDEBusDriverDiagnostics2; + +// +// Extra Definition to porting +// +#define MAX_IDE_DEVICE 4 +#define MAX_IDE_CHANNELS 2 +#define MAX_IDE_DRIVES 2 + +#define INVALID_DEVICE_TYPE 0xff +#define ATA_DEVICE_TYPE 0x00 +#define ATAPI_DEVICE_TYPE 0x01 + +typedef struct { + BOOLEAN HaveScannedDevice[MAX_IDE_DEVICE]; + BOOLEAN DeviceFound[MAX_IDE_DEVICE]; + BOOLEAN DeviceProcessed[MAX_IDE_DEVICE]; +} IDE_BUS_DRIVER_PRIVATE_DATA; + +#define IDE_BLK_IO_DEV_SIGNATURE SIGNATURE_32 ('i', 'b', 'i', 'd') + +typedef struct { + UINT32 Signature; + + EFI_HANDLE Handle; + EFI_BLOCK_IO_PROTOCOL BlkIo; + EFI_BLOCK_IO_MEDIA BlkMedia; + EFI_DISK_INFO_PROTOCOL DiskInfo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; + + // + // Local Data for IDE interface goes here + // + EFI_IDE_CHANNEL Channel; + EFI_IDE_DEVICE Device; + UINT16 Lun; + IDE_DEVICE_TYPE Type; + + IDE_BASE_REGISTERS *IoPort; + UINT16 AtapiError; + + ATAPI_INQUIRY_DATA *InquiryData; + EFI_IDENTIFY_DATA *IdData; + ATA_PIO_MODE PioMode; + EFI_ATA_MODE UdmaMode; + CHAR8 ModelName[41]; + ATAPI_REQUEST_SENSE_DATA *SenseData; + UINT8 SenseDataNumber; + UINT8 *Cache; + + // + // ExitBootService Event, it is used to clear pending IDE interrupt + // + EFI_EVENT ExitBootServiceEvent; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} IDE_BLK_IO_DEV; + +#include "ComponentName.h" + +#define IDE_BLOCK_IO_DEV_FROM_THIS(a) CR (a, IDE_BLK_IO_DEV, BlkIo, IDE_BLK_IO_DEV_SIGNATURE) +#define IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS(a) CR (a, IDE_BLK_IO_DEV, DiskInfo, IDE_BLK_IO_DEV_SIGNATURE) + +#include "Ide.h" + + +/** + Supported function of Driver Binding protocol for this driver. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS Driver loaded. + @retval other Driver not loaded. + +**/ +EFI_STATUS +EFIAPI +IDEBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start function of Driver binding protocol which start this driver on Controller + by detecting all disks and installing BlockIo protocol on them. + + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to. + @param RemainingDevicePath produce all possible children. + + @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 +IDEBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all + child handle attached to the controller handle if there are. + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on + @param NumberOfChildren Not used + @param ChildHandleBuffer Not used + + @retval EFI_SUCCESS This driver is removed DeviceHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +IDEBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// EFI Driver Configuration Functions +// +/** + Allows the user to set controller specific options for a controller that a + driver is currently managing. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to set options on. + @param ChildHandle The handle of the child controller to set options on. + This is an optional parameter that may be NULL. + It will be NULL for device drivers, and for a bus drivers + that wish to set options for the bus controller. + It will not be NULL for a bus driver that wishes to set + options for one of its child controllers. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the user interface that should be presented + to the user, 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 ActionRequired A pointer to the action that the calling agent is required + to perform when this function returns. + + + @retval EFI_SUCCESS The driver specified by This successfully set the configuration + options for the controller specified by ControllerHandle.. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support setting configuration options for + the controller specified by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the language specified by Language. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the configuration options for the + controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to set the configuration options for the + controller specified by ControllerHandle and ChildHandle +**/ +EFI_STATUS +EFIAPI +IDEBusDriverConfigurationSetOptions ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +/** + Tests to see if a controller's current configuration options are valid. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test if it's current configuration options + are valid. + @param ChildHandle The handle of the child controller to test if it's current configuration + options are valid. 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 test the configuration options for the bus controller. It will + not be NULL for a bus driver that wishes to test configuration options for + one of its child controllers. + @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle that is being + managed by the driver specified by This has a valid set of configuration + options. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing the controller + specified by ControllerHandle and ChildHandle. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle that is being + managed by the driver specified by This has an invalid set of configuration + options. +**/ +EFI_STATUS +EFIAPI +IDEBusDriverConfigurationOptionsValid ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +/** + Forces a driver to set the default configuration options for a controller. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to force default configuration options on. + @param ChildHandle The handle of the child controller to force default configuration + options on 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 force default configuration options for the bus + controller. It will not be NULL for a bus driver that wishes to force + default configuration options for one of its child controllers. + @param DefaultType The type of default configuration options to force on the controller + specified by ControllerHandle and ChildHandle. + @param ActionRequired A pointer to the action that the calling agent is required to perform + when this function returns. + + @retval EFI_SUCCESS The driver specified by This successfully forced the + default configuration options on the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default + configuration options on the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type + specified by DefaultType. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration + options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration + options on the controller specified by ControllerHandle and ChildHandle. +**/ +EFI_STATUS +EFIAPI +IDEBusDriverConfigurationForceDefaults ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +// +// EFI Driver Diagnostics Functions +// +/** + Runs diagnostics on a controller. + + @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance. + @param ControllerHandle The handle of the controller to run diagnostics on. + @param ChildHandle The handle of the child controller to run diagnostics on + 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 run diagnostics on the bus controller. + It will not be NULL for a bus driver that wishes to run + diagnostics on one of its child controllers. + @param DiagnosticType Indicates type of diagnostics to perform on the controller + specified by ControllerHandle and ChildHandle. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language in which the optional error message should + be returned in Buffer, 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 ErrorType A GUID that defines the format of the data returned in Buffer. + @param BufferSize The size, in bytes, of the data returned in Buffer. + @param Buffer A buffer that contains a Null-terminated Unicode string + plus some additional data whose format is defined by ErrorType. + Buffer is allocated by this function with AllocatePool(), and + it is the caller's responsibility to free it with a call to FreePool(). + + @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle passed + the diagnostic. + @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 ErrorType is NULL. + @retval EFI_INVALID_PARAMETER BufferType is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support running + diagnostics for the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + @retval EFI_UNSUPPORTED The driver specified by This does not support the language + specified by Language. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete the + diagnostics. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return the + status information in ErrorType, BufferSize,and Buffer. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle + did not pass the diagnostic. +**/ +EFI_STATUS +EFIAPI +IDEBusDriverDiagnosticsRunDiagnostics ( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ); + +/** + issue ATA or ATAPI command to reset a block IO device. + @param This Block IO protocol instance pointer. + @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method + If TRUE, for ATAPI device, driver need invoke ATA reset method after + invoke ATAPI reset method + + @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device. + @retval EFI_SUCCESS The device reset successfully + +**/ +EFI_STATUS +EFIAPI +IDEBlkIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Read data from a block IO device. + + @param This Block IO protocol instance pointer. + @param MediaId The media ID of the device + @param Lba Starting LBA address to read data + @param BufferSize The size of data to be read + @param Buffer Caller supplied buffer to save data + + @retval EFI_DEVICE_ERROR unknown device type + @retval EFI_SUCCESS read the data successfully. + +**/ +EFI_STATUS +EFIAPI +IDEBlkIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Write data to block io device + + @param This Protocol instance pointer. + @param MediaId The media ID of the device + @param Lba Starting LBA address to write data + @param BufferSize The size of data to be written + @param Buffer Caller supplied buffer to save data + + @retval EFI_DEVICE_ERROR unknown device type + @retval other write data status + +**/ +EFI_STATUS +EFIAPI +IDEBlkIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flushes all modified data to a physical block devices + + @param This Indicates a pointer to the calling context which to sepcify a + sepcific block device + + @retval EFI_SUCCESS Always return success. +**/ +EFI_STATUS +EFIAPI +IDEBlkIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); +/** + This function is used by the IDE bus driver to get inquiry data. + Data format of Identify data is defined by the Interface GUID. + + @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param InquiryData Pointer to a buffer for the inquiry data. + @param InquiryDataSize Pointer to the value for the inquiry data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading InquiryData from device + @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough + +**/ +EFI_STATUS +EFIAPI +IDEDiskInfoInquiry ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *InquiryData, + IN OUT UINT32 *InquiryDataSize + ); + +/** + This function is used by the IDE bus driver to get identify data. + Data format of Identify data is defined by the Interface GUID. + + @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param IdentifyData Pointer to a buffer for the identify data. + @param IdentifyDataSize Pointer to the value for the identify data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading IdentifyData from device + @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough + +**/ +EFI_STATUS +EFIAPI +IDEDiskInfoIdentify ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *IdentifyData, + IN OUT UINT32 *IdentifyDataSize + ); + +/** + This function is used by the IDE bus driver to get sense data. + Data format of Sense data is defined by the Interface GUID. + + @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param SenseData Pointer to the SenseData. + @param SenseDataSize Size of SenseData in bytes. + @param SenseDataNumber Pointer to the value for the identify data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading InquiryData from device + @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough + +**/ +EFI_STATUS +EFIAPI +IDEDiskInfoSenseData ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *SenseData, + IN OUT UINT32 *SenseDataSize, + OUT UINT8 *SenseDataNumber + ); + +/** + This function is used by the IDE bus driver to get controller information. + + @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param IdeChannel Pointer to the Ide Channel number. Primary or secondary. + @param IdeDevice Pointer to the Ide Device number. Master or slave. + + @retval EFI_SUCCESS IdeChannel and IdeDevice are valid + @retval EFI_UNSUPPORTED This is not an IDE device + +**/ +EFI_STATUS +EFIAPI +IDEDiskInfoWhichIde ( + IN EFI_DISK_INFO_PROTOCOL *This, + OUT UINT32 *IdeChannel, + OUT UINT32 *IdeDevice + ); +/** + The is an event(generally the event is exitBootService event) call back function. + Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. + + @param Event Pointer to this event + @param Context Event handler private data + +**/ +VOID +EFIAPI +ClearInterrupt ( + IN EFI_EVENT Event, + IN VOID *Context + ); +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf new file mode 100644 index 0000000000..8beea2d9ca --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf @@ -0,0 +1,88 @@ +## @file +# IDE bus driver. +# +# This driver will enumerate IDE device and export the blockIo protocol for every device. +# +# 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 +# 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 = IdeBusDxe + MODULE_UNI_FILE = IdeBusDxe.uni + FILE_GUID = 69FD8E47-A161-4550-B01A-5594CEB2B2B2 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeIdeBus + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gIDEBusDriverBinding +# COMPONENT_NAME = gIDEBusComponentName +# COMPONENT_NAME2 = gIDEBusComponentName2 +# Variable Guid C Name: gConfigurationGuid Variable Name: L"Configuration" +# +# + +[Sources] + DriverDiagnostics.c + DriverConfiguration.c + ComponentName.h + ComponentName.c + Atapi.c + Ata.c + Ide.c + IdeBus.c + IdeData.h + Ide.h + IdeBus.h + + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +[LibraryClasses] + DevicePathLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PerformanceLib + MemoryAllocationLib + ReportStatusCodeLib + BaseMemoryLib + UefiLib + BaseLib + UefiDriverEntryPoint + DebugLib + + +[Guids] + gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # DiskInfo Interface Guid + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + + +[Protocols] + gEfiDiskInfoProtocolGuid ## BY_START + gEfiBlockIoProtocolGuid ## BY_START + gEfiIdeControllerInitProtocolGuid ## TO_START + gEfiPciIoProtocolGuid ## TO_START + ## TO_START + ## BY_START + gEfiDevicePathProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + IdeBusDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.uni b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.uni new file mode 100644 index 0000000000..ebe7f19e75 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni new file mode 100644 index 0000000000..24ad99a10e Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeData.h b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeData.h new file mode 100644 index 0000000000..487fe6f3ea --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeData.h @@ -0,0 +1,311 @@ +/** @file + Header file for IDE Bus Driver's Data Structures + + Copyright (c) 2006 - 2007, Intel 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 _IDE_DATA_H_ +#define _IDE_DATA_H_ + +#include + +// +// common constants +// +#define STALL_1_MILLI_SECOND 1000 // stall 1 ms +#define STALL_1_SECOND 1000000 // stall 1 second +typedef enum { + IdePrimary = 0, + IdeSecondary = 1, + IdeMaxChannel = 2 +} EFI_IDE_CHANNEL; + +typedef enum { + IdeMaster = 0, + IdeSlave = 1, + IdeMaxDevice = 2 +} EFI_IDE_DEVICE; + +typedef enum { + IdeMagnetic, /* ZIP Drive or LS120 Floppy Drive */ + IdeCdRom, /* ATAPI CDROM */ + IdeHardDisk, /* Hard Disk */ + Ide48bitAddressingHardDisk, /* Hard Disk larger than 120GB */ + IdeUnknown +} IDE_DEVICE_TYPE; + +typedef enum { + SenseNoSenseKey, + SenseDeviceNotReadyNoRetry, + SenseDeviceNotReadyNeedRetry, + SenseNoMedia, + SenseMediaChange, + SenseMediaError, + SenseOtherSense +} SENSE_RESULT; + +typedef enum { + AtaUdmaReadOp, + AtaUdmaReadExtOp, + AtaUdmaWriteOp, + AtaUdmaWriteExtOp +} ATA_UDMA_OPERATION; + +// +// IDE Registers +// +typedef union { + UINT16 Command; /* when write */ + UINT16 Status; /* when read */ +} IDE_CMD_OR_STATUS; + +typedef union { + UINT16 Error; /* when read */ + UINT16 Feature; /* when write */ +} IDE_ERROR_OR_FEATURE; + +typedef union { + UINT16 AltStatus; /* when read */ + UINT16 DeviceControl; /* when write */ +} IDE_ALTSTATUS_OR_DEVICECONTROL; + +// +// IDE registers set +// +typedef struct { + UINT16 Data; + IDE_ERROR_OR_FEATURE Reg1; + UINT16 SectorCount; + UINT16 SectorNumber; + UINT16 CylinderLsb; + UINT16 CylinderMsb; + UINT16 Head; + IDE_CMD_OR_STATUS Reg; + + IDE_ALTSTATUS_OR_DEVICECONTROL Alt; + UINT16 DriveAddress; + + UINT16 MasterSlave; + UINT16 BusMasterBaseAddr; +} IDE_BASE_REGISTERS; + +// +// IDE registers' base addresses +// +typedef struct { + UINT16 CommandBlockBaseAddr; + UINT16 ControlBlockBaseAddr; + UINT16 BusMasterBaseAddr; +} IDE_REGISTERS_BASE_ADDR; + +// +// Bit definitions in Programming Interface byte of the Class Code field +// in PCI IDE controller's Configuration Space +// +#define IDE_PRIMARY_OPERATING_MODE BIT0 +#define IDE_PRIMARY_PROGRAMMABLE_INDICATOR BIT1 +#define IDE_SECONDARY_OPERATING_MODE BIT2 +#define IDE_SECONDARY_PROGRAMMABLE_INDICATOR BIT3 + + +// +// Bus Master Reg +// +#define BMIC_NREAD BIT3 +#define BMIC_START BIT0 +#define BMIS_INTERRUPT BIT2 +#define BMIS_ERROR BIT1 + +#define BMICP_OFFSET 0x00 +#define BMISP_OFFSET 0x02 +#define BMIDP_OFFSET 0x04 +#define BMICS_OFFSET 0x08 +#define BMISS_OFFSET 0x0A +#define BMIDS_OFFSET 0x0C + +// +// Time Out Value For IDE Device Polling +// + +// +// ATATIMEOUT is used for waiting time out for ATA device +// + +// +// 1 second +// +#define ATATIMEOUT 1000 + +// +// ATAPITIMEOUT is used for waiting operation +// except read and write time out for ATAPI device +// + +// +// 1 second +// +#define ATAPITIMEOUT 1000 + +// +// ATAPILONGTIMEOUT is used for waiting read and +// write operation timeout for ATAPI device +// + +// +// 2 seconds +// +#define CDROMLONGTIMEOUT 2000 + +// +// 5 seconds +// +#define ATAPILONGTIMEOUT 5000 + +// +// 10 seconds +// +#define ATASMARTTIMEOUT 10000 + + +// +// ATAPI6 related data structure definition +// + +// +// The maximum sectors count in 28 bit addressing mode +// +#define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff + +#pragma pack(1) + +typedef struct { + UINT32 RegionBaseAddr; + UINT16 ByteCount; + UINT16 EndOfTable; +} IDE_DMA_PRD; + +#pragma pack() + +#define SETFEATURE TRUE +#define CLEARFEATURE FALSE + +/// +/// PIO mode definition +/// +typedef enum _ATA_PIO_MODE_ { + AtaPioModeBelow2, + AtaPioMode2, + AtaPioMode3, + AtaPioMode4 +} ATA_PIO_MODE; + +// +// Multi word DMA definition +// +typedef enum _ATA_MDMA_MODE_ { + AtaMdmaMode0, + AtaMdmaMode1, + AtaMdmaMode2 +} ATA_MDMA_MODE; + +// +// UDMA mode definition +// +typedef enum _ATA_UDMA_MODE_ { + AtaUdmaMode0, + AtaUdmaMode1, + AtaUdmaMode2, + AtaUdmaMode3, + AtaUdmaMode4, + AtaUdmaMode5 +} ATA_UDMA_MODE; + +#define ATA_MODE_CATEGORY_DEFAULT_PIO 0x00 +#define ATA_MODE_CATEGORY_FLOW_PIO 0x01 +#define ATA_MODE_CATEGORY_MDMA 0x04 +#define ATA_MODE_CATEGORY_UDMA 0x08 + +#pragma pack(1) + +typedef struct { + UINT8 ModeNumber : 3; + UINT8 ModeCategory : 5; +} ATA_TRANSFER_MODE; + +typedef struct { + UINT8 Sector; + UINT8 Heads; + UINT8 MultipleSector; +} ATA_DRIVE_PARMS; + +#pragma pack() +// +// IORDY Sample Point field value +// +#define ISP_5_CLK 0 +#define ISP_4_CLK 1 +#define ISP_3_CLK 2 +#define ISP_2_CLK 3 + +// +// Recovery Time field value +// +#define RECVY_4_CLK 0 +#define RECVY_3_CLK 1 +#define RECVY_2_CLK 2 +#define RECVY_1_CLK 3 + +// +// Slave IDE Timing Register Enable +// +#define SITRE BIT14 + +// +// DMA Timing Enable Only Select 1 +// +#define DTE1 BIT7 + +// +// Pre-fetch and Posting Enable Select 1 +// +#define PPE1 BIT6 + +// +// IORDY Sample Point Enable Select 1 +// +#define IE1 BIT5 + +// +// Fast Timing Bank Drive Select 1 +// +#define TIME1 BIT4 + +// +// DMA Timing Enable Only Select 0 +// +#define DTE0 BIT3 + +// +// Pre-fetch and Posting Enable Select 0 +// +#define PPE0 BIT2 + +// +// IOREY Sample Point Enable Select 0 +// +#define IE0 BIT1 + +// +// Fast Timing Bank Drive Select 0 +// +#define TIME0 BIT0 + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/ComponentName.c new file mode 100644 index 0000000000..e495d96af8 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/ComponentName.c @@ -0,0 +1,168 @@ +/** @file + Implements EFI Component Name Protocol for VGA Mini Port 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 "VgaMiniPort.h" + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPciVgaMiniPortComponentName = { + PciVgaMiniPortComponentNameGetDriverName, + PciVgaMiniPortComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciVgaMiniPortComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciVgaMiniPortComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciVgaMiniPortComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPciVgaMiniPortDriverNameTable[] = { + { + "eng;en", + L"PCI VGA Mini Port Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language 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 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 +PciVgaMiniPortComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mPciVgaMiniPortDriverNameTable, + DriverName, + (BOOLEAN)(This == &gPciVgaMiniPortComponentName) + ); +} + +/** + 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 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + 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 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 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 +PciVgaMiniPortComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c new file mode 100644 index 0000000000..25d1e3beb7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c @@ -0,0 +1,331 @@ +/** @file + Implements EFI Driver Binding Protocol and VGA Mini Port Protocol for VGA Mini Port Driver. + +Copyright (c) 2006 - 2009, Intel 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 "VgaMiniPort.h" + +// +// EFI Driver Binding Protocol Instance +// +// This driver has a version value of 0x00000000. This is the +// lowest possible priority for a driver. This is done on purpose to help +// the developers of UGA drivers. This driver can bind if no UGA driver +// is present, so a console is available. Then, when a UGA driver is loaded +// this driver can be disconnected, and the UGA driver can be connected. +// As long as the UGA driver has a version value greater than 0x00000000, it +// will be connected first and will block this driver from connecting. +// +EFI_DRIVER_BINDING_PROTOCOL gPciVgaMiniPortDriverBinding = { + PciVgaMiniPortDriverBindingSupported, + PciVgaMiniPortDriverBindingStart, + PciVgaMiniPortDriverBindingStop, + 0x00000000, + NULL, + NULL +}; + +/** + Entrypoint of VGA Mini Port Driver. + + This function is the entrypoint of UVGA Mini Port Driver. It installs Driver Binding + Protocols together with Component Name Protocols. + + @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. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gPciVgaMiniPortDriverBinding, + ImageHandle, + &gPciVgaMiniPortComponentName, + &gPciVgaMiniPortComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + +/** + Check whether VGA Mini Port driver supports this device. + + @param This The driver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The driver supports this controller. + @retval EFI_UNSUPPORTED This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // See if this is a PCI VGA Controller by looking at the Command register and + // Class Code Register + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = EFI_UNSUPPORTED; + // + // See if the device is an enabled VGA device. + // Most systems can only have on VGA device on at a time. + // + if (((Pci.Hdr.Command & 0x03) == 0x03) && IS_PCI_VGA (&Pci)) { + Status = EFI_SUCCESS; + } + +Done: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + + +/** + Starts the VGA device with this driver. + + This function consumes PCI I/O Protocol, and installs VGA Mini Port Protocol + onto the VGA device handle. + + @param This The driver binding instance. + @param Controller The controller to check. + @param RemainingDevicePath The remaining device patch. + + @retval EFI_SUCCESS The controller is controlled by the driver. + @retval EFI_ALREADY_STARTED The controller is already controlled by the driver. + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_VGA_MINI_PORT_DEV *PciVgaMiniPortPrivate; + + PciVgaMiniPortPrivate = NULL; + PciIo = NULL; + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Allocate the private device structure + // + PciVgaMiniPortPrivate = AllocateZeroPool (sizeof (PCI_VGA_MINI_PORT_DEV)); + ASSERT (PciVgaMiniPortPrivate != NULL); + + // + // Initialize the private device structure + // + PciVgaMiniPortPrivate->Signature = PCI_VGA_MINI_PORT_DEV_SIGNATURE; + PciVgaMiniPortPrivate->Handle = Controller; + PciVgaMiniPortPrivate->PciIo = PciIo; + + PciVgaMiniPortPrivate->VgaMiniPort.SetMode = PciVgaMiniPortSetMode; + PciVgaMiniPortPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000; + PciVgaMiniPortPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4; + PciVgaMiniPortPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5; + PciVgaMiniPortPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR; + PciVgaMiniPortPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; + PciVgaMiniPortPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; + PciVgaMiniPortPrivate->VgaMiniPort.MaxMode = 1; + + // + // Install VGA Mini Port Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiVgaMiniPortProtocolGuid, + &PciVgaMiniPortPrivate->VgaMiniPort, + NULL + ); +Done: + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (PciVgaMiniPortPrivate != NULL) { + FreePool (PciVgaMiniPortPrivate); + } + } + + return Status; +} + + +/** + Stop the VGA device with this driver. + + This function uninstalls VGA Mini Port Protocol from the VGA device handle, + and closes PCI I/O Protocol. + + @param This The driver binding protocol. + @param Controller The controller to release. + @param NumberOfChildren The child number that opened controller + BY_CHILD. + @param ChildHandleBuffer The array of child handle. + + @retval EFI_SUCCESS The controller or children are stopped. + @retval EFI_DEVICE_ERROR Failed to stop the driver. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + PCI_VGA_MINI_PORT_DEV *PciVgaMiniPortPrivate; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + (VOID **) &VgaMiniPort, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + PciVgaMiniPortPrivate = PCI_VGA_MINI_PORT_DEV_FROM_THIS (VgaMiniPort); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + &PciVgaMiniPortPrivate->VgaMiniPort + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + FreePool (PciVgaMiniPortPrivate); + + return EFI_SUCCESS; +} +// +// VGA Mini Port Protocol Functions +// + +/** + Sets the text display mode of a VGA controller. + + This function implements EFI_VGA_MINI_PORT_PROTOCOL.SetMode(). + If ModeNumber exceeds the valid range, then EFI_UNSUPPORTED is returned. + Otherwise, EFI_SUCCESS is directly returned without real operation. + + @param This Protocol instance pointer. + @param ModeNumber Mode number. 0 - 80x25 1-80x50 + + @retval EFI_SUCCESS The mode was set + @retval EFI_UNSUPPORTED ModeNumber is not supported. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortSetMode ( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + if (ModeNumber > This->MaxMode) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h new file mode 100644 index 0000000000..f39c00364b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h @@ -0,0 +1,271 @@ +/** @file + Internal include file for VGA Mini Port 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. + +**/ + +#ifndef _VGA_MINIPORT_H_ +#define _VGA_MINIPORT_H_ + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include + + +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include + +#include + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gPciVgaMiniPortDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gPciVgaMiniPortComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gPciVgaMiniPortComponentName2; + +// +// PCI VGA MiniPort Device Structure +// +#define PCI_VGA_MINI_PORT_DEV_SIGNATURE SIGNATURE_32('P','V','M','P') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort; + EFI_PCI_IO_PROTOCOL *PciIo; +} PCI_VGA_MINI_PORT_DEV; + +#define PCI_VGA_MINI_PORT_DEV_FROM_THIS(a) CR(a, PCI_VGA_MINI_PORT_DEV, VgaMiniPort, PCI_VGA_MINI_PORT_DEV_SIGNATURE) + +// +// Driver Binding Protocol functions +// +/** + Check whether VGA Mini Port driver supports this device. + + @param This The driver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The driver supports this controller. + @retval EFI_UNSUPPORTED This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Starts the VGA device with this driver. + + This function consumes PCI I/O Protocol, and installs VGA Mini Port Protocol + onto the VGA device handle. + + @param This The driver binding instance. + @param Controller The controller to check. + @param RemainingDevicePath The remaining device patch. + + @retval EFI_SUCCESS The controller is controlled by the driver. + @retval EFI_ALREADY_STARTED The controller is already controlled by the driver. + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop the VGA device with this driver. + + This function uninstalls VGA Mini Port Protocol from the VGA device handle, + and closes PCI I/O Protocol. + + @param This The driver binding protocol. + @param Controller The controller to release. + @param NumberOfChildren The child number that opened controller + BY_CHILD. + @param ChildHandleBuffer The array of child handle. + + @retval EFI_SUCCESS The controller or children are stopped. + @retval EFI_DEVICE_ERROR Failed to stop the driver. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language 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 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 +PciVgaMiniPortComponentNameGetDriverName ( + 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 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + 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 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 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 +PciVgaMiniPortComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// VGA Mini Port Protocol functions +// +/** + Sets the text display mode of a VGA controller. + + This function implements EFI_VGA_MINI_PORT_PROTOCOL.SetMode(). + If ModeNumber exceeds the valid range, then EFI_UNSUPPORTED is returned. + Otherwise, EFI_SUCCESS is directly returned without real operation. + + @param This Protocol instance pointer. + @param ModeNumber Mode number. 0 - 80x25 1-80x50 + + @retval EFI_SUCCESS The mode was set + @retval EFI_UNSUPPORTED ModeNumber is not supported. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +EFI_STATUS +EFIAPI +PciVgaMiniPortSetMode ( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni new file mode 100644 index 0000000000..ca9d2446d6 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni differ diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf new file mode 100644 index 0000000000..d3c35faa6c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf @@ -0,0 +1,57 @@ +## @file +# VGA Mini Port Driver that manages VGA device and produces VGA Mini Port 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 +# 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 = VgaMiniPort + MODULE_UNI_FILE = VgaMiniPort.uni + FILE_GUID = 15C5E761-58D8-461a-9173-CAB020916264 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PciVgaMiniPortDriverEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# DRIVER_BINDING = gPciVgaMiniPortDriverBinding; +# COMPONENT_NAME = gPciVgaMiniPortComponentName; +# COMPONENT_NAME2 = gPciVgaMiniPortComponentName2; +# + +[Sources] + ComponentName.c + VgaMiniPort.c + VgaMiniPort.h + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiLib + DebugLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + MemoryAllocationLib + +[Protocols] + gEfiPciIoProtocolGuid ## TO_START + gEfiVgaMiniPortProtocolGuid ## BY_START + +[UserExtensions.TianoCore."ExtraFiles"] + VgaMiniPortExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni new file mode 100644 index 0000000000..731713fbc6 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Contributions.txt b/Core/IntelFrameworkModulePkg/Contributions.txt new file mode 100644 index 0000000000..f87cbd73c6 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Contributions.txt @@ -0,0 +1,218 @@ + +====================== += Code Contributions = +====================== + +To make a contribution to a TianoCore project, follow these steps. +1. Create a change description in the format specified below to + use in the source control commit log. +2. Your commit message must include your "Signed-off-by" signature, + and "Contributed-under" message. +3. Your "Contributed-under" message explicitly states that the + contribution is made under the terms of the specified + contribution agreement. Your "Contributed-under" message + must include the name of contribution agreement and version. + For example: Contributed-under: TianoCore Contribution Agreement 1.0 + The "TianoCore Contribution Agreement" is included below in + this document. +4. Submit your code to the TianoCore project using the process + that the project documents on its web page. If the process is + not documented, then submit the code on development email list + for the project. +5. It is preferred that contributions are submitted using the same + copyright license as the base project. When that is not possible, + then contributions using the following licenses can be accepted: + * BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause + * BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause + * MIT: http://opensource.org/licenses/MIT + * Python-2.0: http://opensource.org/licenses/Python-2.0 + * Zlib: http://opensource.org/licenses/Zlib + + Contributions of code put into the public domain can also be + accepted. + + Contributions using other licenses might be accepted, but further + review will be required. + +===================================================== += Change Description / Commit Message / Patch Email = +===================================================== + +Your change description should use the standard format for a +commit message, and must include your "Signed-off-by" signature +and the "Contributed-under" message. + +== Sample Change Description / Commit Message = + +=== Start of sample patch email message === + +From: Contributor Name +Subject: [PATCH] CodeModule: Brief-single-line-summary + +Full-commit-message + +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Contributor Name +--- + +An extra message for the patch email which will not be considered part +of the commit message can be added here. + +Patch content inline or attached + +=== End of sample patch email message === + +=== Notes for sample patch email === + +* The first line of commit message is taken from the email's subject + line following [PATCH]. The remaining portion of the commit message + is the email's content until the '---' line. +* git format-patch is one way to create this format + +=== Definitions for sample patch email === + +* "CodeModule" is a short idenfier for the affected code. For + example MdePkg, or MdeModulePkg UsbBusDxe. +* "Brief-single-line-summary" is a short summary of the change. +* The entire first line should be less than ~70 characters. +* "Full-commit-message" a verbose multiple line comment describing + the change. Each line should be less than ~70 characters. +* "Contributed-under" explicitely states that the contribution is + made under the terms of the contribtion agreement. This + agreement is included below in this document. +* "Signed-off-by" is the contributor's signature identifying them + by their real/legal name and their email address. + +======================================== += TianoCore Contribution Agreement 1.0 = +======================================== + +INTEL CORPORATION ("INTEL") MAKES AVAILABLE SOFTWARE, DOCUMENTATION, +INFORMATION AND/OR OTHER MATERIALS FOR USE IN THE TIANOCORE OPEN SOURCE +PROJECT (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE +TERMS AND CONDITIONS OF THIS AGREEMENT BETWEEN YOU AND INTEL AND/OR THE +TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR +REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE +CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS +OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED +BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS +AGREEMENT AND THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE +AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT +USE THE CONTENT. + +Unless otherwise indicated, all Content made available on the TianoCore +site is provided to you under the terms and conditions of the BSD +License ("BSD"). A copy of the BSD License is available at +http://opensource.org/licenses/bsd-license.php +or when applicable, in the associated License.txt file. + +Certain other content may be made available under other licenses as +indicated in or with such Content. (For example, in a License.txt file.) + +You accept and agree to the following terms and conditions for Your +present and future Contributions submitted to TianoCore site. Except +for the license granted to Intel hereunder, You reserve all right, +title, and interest in and to Your Contributions. + +== SECTION 1: Definitions == +* "You" or "Contributor" shall mean the copyright owner or legal + entity authorized by the copyright owner that is making a + Contribution hereunder. All other entities that control, are + controlled by, or are under common control with that entity are + considered to be a single Contributor. For the purposes of this + definition, "control" means (i) the power, direct or indirect, to + cause the direction or management of such entity, whether by + contract or otherwise, or (ii) ownership of fifty percent (50%) + or more of the outstanding shares, or (iii) beneficial ownership + of such entity. +* "Contribution" shall mean any original work of authorship, + including any modifications or additions to an existing work, + that is intentionally submitted by You to the TinaoCore site for + inclusion in, or documentation of, any of the Content. For the + purposes of this definition, "submitted" means any form of + electronic, verbal, or written communication sent to the + TianoCore site or its representatives, including but not limited + to communication on electronic mailing lists, source code + control systems, and issue tracking systems that are managed by, + or on behalf of, the TianoCore site for the purpose of + discussing and improving the Content, but excluding + communication that is conspicuously marked or otherwise + designated in writing by You as "Not a Contribution." + +== SECTION 2: License for Contributions == +* Contributor hereby agrees that redistribution and use of the + Contribution in source and binary forms, with or without + modification, are permitted provided that the following + conditions are met: +** Redistributions of source code must retain the Contributor's + copyright notice, this list of conditions and the following + disclaimer. +** Redistributions in binary form must reproduce the Contributor's + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +* Disclaimer. None of the names of Contributor, Intel, or the names + of their respective contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. +* Contributor grants a license (with the right to sublicense) under + claims of Contributor's patents that Contributor can license that + are infringed by the Contribution (as delivered by Contributor) to + make, use, distribute, sell, offer for sale, and import the + Contribution and derivative works thereof solely to the minimum + extent necessary for licensee to exercise the granted copyright + license; this patent license applies solely to those portions of + the Contribution that are unmodified. No hardware per se is + licensed. +* EXCEPT AS EXPRESSLY SET FORTH IN SECTION 3 BELOW, THE + CONTRIBUTION IS PROVIDED BY THE CONTRIBUTOR "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + CONTRIBUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +== SECTION 3: Representations == +* You represent that You are legally entitled to grant the above + license. If your employer(s) has rights to intellectual property + that You create that includes Your Contributions, You represent + that You have received permission to make Contributions on behalf + of that employer, that Your employer has waived such rights for + Your Contributions. +* You represent that each of Your Contributions is Your original + creation (see Section 4 for submissions on behalf of others). + You represent that Your Contribution submissions include complete + details of any third-party license or other restriction + (including, but not limited to, related patents and trademarks) + of which You are personally aware and which are associated with + any part of Your Contributions. + +== SECTION 4: Third Party Contributions == +* Should You wish to submit work that is not Your original creation, + You may submit it to TianoCore site separately from any + Contribution, identifying the complete details of its source + and of any license or other restriction (including, but not + limited to, related patents, trademarks, and license agreements) + of which You are personally aware, and conspicuously marking the + work as "Submitted on behalf of a third-party: [named here]". + +== SECTION 5: Miscellaneous == +* Applicable Laws. Any claims arising under or relating to this + Agreement shall be governed by the internal substantive laws of + the State of Delaware or federal courts located in Delaware, + without regard to principles of conflict of laws. +* Language. This Agreement is in the English language only, which + language shall be controlling in all respects, and all versions + of this Agreement in any other language shall be for accommodation + only and shall not be binding. All communications and notices made + or given pursuant to this Agreement, and all documentation and + support to be provided, unless otherwise noted, shall be in the + English language. + diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c new file mode 100644 index 0000000000..e8ea11c4f8 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c @@ -0,0 +1,780 @@ +/** @file + EFI glue for BIOS INT 13h block devices. + + This file is coded to EDD 3.0 as defined by T13 D1386 Revision 4 + Availible on http://www.t13.org/#Project drafts + Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r4.pdf + +Copyright (c) 1999 - 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 "BiosBlkIo.h" + +// +// Global data declaration +// +// +// EFI Driver Binding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gBiosBlockIoDriverBinding = { + BiosBlockIoDriverBindingSupported, + BiosBlockIoDriverBindingStart, + BiosBlockIoDriverBindingStop, + 0x3, + NULL, + NULL +}; + +// +// Semaphore to control access to global variables mActiveInstances and mBufferUnder1Mb +// +EFI_LOCK mGlobalDataLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_APPLICATION); + +// +// Number of active instances of this protocol. This is used to allocate/free +// the shared buffer. You must acquire the semaphore to modify. +// +UINTN mActiveInstances = 0; + +// +// Pointer to the beginning of the buffer used for real mode thunk +// You must acquire the semaphore to modify. +// +EFI_PHYSICAL_ADDRESS mBufferUnder1Mb = 0; + +// +// Address packet is a buffer under 1 MB for all version EDD calls +// +EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb; + +// +// This is a buffer for INT 13h func 48 information +// +BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb; + +// +// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB +// 0xFE00 bytes is the max transfer size supported. +// +VOID *mEdd11Buffer; + +/** + Driver entry point. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Entrypoint successfully executed. + @retval Others Fail to execute entrypoint. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install protocols + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gBiosBlockIoDriverBinding, + ImageHandle, + &gBiosBlockIoComponentName, + &gBiosBlockIoComponentName2 + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver + // + return gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiLegacyBiosGuid, + NULL, + NULL + ); +} + +/** + Check whether the driver supports this device. + + @param This The Udriver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The driver supports this controller. + @retval other This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + PCI_TYPE00 Pci; + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // See if this is a PCI VGA Controller by looking at the Command register and + // Class Code Register + // + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = EFI_UNSUPPORTED; + if (Pci.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE || + (Pci.Hdr.ClassCode[2] == PCI_BASE_CLASS_INTELLIGENT && Pci.Hdr.ClassCode[1] == PCI_SUB_CLASS_INTELLIGENT) + ) { + Status = EFI_SUCCESS; + } + +Done: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Starts the device with this driver. + + @param This The driver binding instance. + @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 The controller is controlled by the driver. + @retval Other This controller cannot be started. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 DiskStart; + UINT8 DiskEnd; + BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; + EFI_DEVICE_PATH_PROTOCOL *PciDevPath; + UINTN Index; + UINTN Flags; + UINTN TmpAddress; + BOOLEAN DeviceEnable; + + // + // Initialize variables + // + PciIo = NULL; + PciDevPath = NULL; + + DeviceEnable = FALSE; + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &PciDevPath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + goto Error; + } + // + // Enable the device and make sure VGA cycles are being forwarded to this VGA device + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + DeviceEnable = TRUE; + + // + // Check to see if there is a legacy option ROM image associated with this PCI device + // + Status = LegacyBios->CheckPciRom ( + LegacyBios, + Controller, + NULL, + NULL, + &Flags + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // Post the legacy option ROM if it is available. + // + Status = LegacyBios->InstallPciRom ( + LegacyBios, + Controller, + NULL, + &Flags, + &DiskStart, + &DiskEnd, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // All instances share a buffer under 1MB to put real mode thunk code in + // If it has not been allocated, then we allocate it. + // + if (mBufferUnder1Mb == 0) { + // + // Should only be here if there are no active instances + // + ASSERT (mActiveInstances == 0); + + // + // Acquire the lock + // + EfiAcquireLock (&mGlobalDataLock); + + // + // Allocate below 1MB + // + mBufferUnder1Mb = 0x00000000000FFFFF; + Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb); + + // + // Release the lock + // + EfiReleaseLock (&mGlobalDataLock); + + // + // Check memory allocation success + // + if (EFI_ERROR (Status)) { + // + // In checked builds we want to assert if the allocate failed. + // + ASSERT_EFI_ERROR (Status); + Status = EFI_OUT_OF_RESOURCES; + mBufferUnder1Mb = 0; + goto Error; + } + + TmpAddress = (UINTN) mBufferUnder1Mb; + // + // Adjusting the value to be on proper boundary + // + mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress); + + TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER; + // + // Adjusting the value to be on proper boundary + // + mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress); + + TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE); + // + // Adjusting the value to be on proper boundary + // + mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress); + } + // + // Allocate the private device structure for each disk + // + for (Index = DiskStart; Index < DiskEnd; Index++) { + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (BIOS_BLOCK_IO_DEV), + (VOID **) &BiosBlockIoPrivate + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // Zero the private device structure + // + ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV)); + + // + // Initialize the private device structure + // + BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE; + BiosBlockIoPrivate->ControllerHandle = Controller; + BiosBlockIoPrivate->LegacyBios = LegacyBios; + BiosBlockIoPrivate->PciIo = PciIo; + + BiosBlockIoPrivate->Bios.Floppy = FALSE; + BiosBlockIoPrivate->Bios.Number = (UINT8) Index; + BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C'); + BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE; + + if (BiosInitBlockIo (BiosBlockIoPrivate)) { + SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath); + + // + // Install the Block Io Protocol onto a new child handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BiosBlockIoPrivate->Handle, + &gEfiBlockIoProtocolGuid, + &BiosBlockIoPrivate->BlockIo, + &gEfiDevicePathProtocolGuid, + BiosBlockIoPrivate->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (BiosBlockIoPrivate); + } + // + // Open For Child Device + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &BiosBlockIoPrivate->PciIo, + This->DriverBindingHandle, + BiosBlockIoPrivate->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + + } else { + gBS->FreePool (BiosBlockIoPrivate); + } + } + +Error: + if (EFI_ERROR (Status)) { + if (PciIo != NULL) { + if (DeviceEnable) { + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + } + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (PciDevPath != NULL) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + if (mBufferUnder1Mb != 0 && mActiveInstances == 0) { + gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); + + // + // Clear the buffer back to 0 + // + EfiAcquireLock (&mGlobalDataLock); + mBufferUnder1Mb = 0; + EfiReleaseLock (&mGlobalDataLock); + } + } + } else { + // + // Successfully installed, so increment the number of active instances + // + EfiAcquireLock (&mGlobalDataLock); + mActiveInstances++; + EfiReleaseLock (&mGlobalDataLock); + } + + return Status; +} + +/** + Stop the device handled by this driver. + + @param This The driver binding protocol. + @param Controller The controller to release. + @param NumberOfChildren The number of handles in ChildHandleBuffer. + @param ChildHandleBuffer The array of child handle. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + @retval Others Fail to uninstall protocols attached on the device. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + BOOLEAN AllChildrenStopped; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; + UINTN Index; + + // + // Decrement the number of active instances + // + if (mActiveInstances != 0) { + // + // Add a check since the stop function will be called 2 times for each handle + // + EfiAcquireLock (&mGlobalDataLock); + mActiveInstances--; + EfiReleaseLock (&mGlobalDataLock); + } + + if ((mActiveInstances == 0) && (mBufferUnder1Mb != 0)) { + // + // Free our global buffer + // + Status = gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); + ASSERT_EFI_ERROR (Status); + + EfiAcquireLock (&mGlobalDataLock); + mBufferUnder1Mb = 0; + EfiReleaseLock (&mGlobalDataLock); + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + BiosBlockIoPrivate = BIOS_BLOCK_IO_FROM_THIS (BlockIo); + + // + // Release PCI I/O and Block IO Protocols on the clild handle. + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiBlockIoProtocolGuid, + &BiosBlockIoPrivate->BlockIo, + &gEfiDevicePathProtocolGuid, + BiosBlockIoPrivate->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + // + // Shutdown the hardware + // + BiosBlockIoPrivate->PciIo->Attributes ( + BiosBlockIoPrivate->PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + gBS->FreePool (BiosBlockIoPrivate); + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +/** + Build device path for device. + + @param BaseDevicePath Base device path. + @param Drive Legacy drive. + @param DevicePath Device path for output. + +**/ +VOID +SetBiosInitBlockIoDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, + IN BIOS_LEGACY_DRIVE *Drive, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_STATUS Status; + BLOCKIO_VENDOR_DEVICE_PATH VendorNode; + + Status = EFI_UNSUPPORTED; + + // + // BugBug: Check for memory leaks! + // + if (Drive->EddVersion == EDD_VERSION_30) { + // + // EDD 3.0 case. + // + Status = BuildEdd30DevicePath (BaseDevicePath, Drive, DevicePath); + } + + if (EFI_ERROR (Status)) { + // + // EDD 1.1 device case or it is unrecognized EDD 3.0 device + // + ZeroMem (&VendorNode, sizeof (VendorNode)); + VendorNode.DevicePath.Header.Type = HARDWARE_DEVICE_PATH; + VendorNode.DevicePath.Header.SubType = HW_VENDOR_DP; + SetDevicePathNodeLength (&VendorNode.DevicePath.Header, sizeof (VendorNode)); + CopyMem (&VendorNode.DevicePath.Guid, &gBlockIoVendorGuid, sizeof (EFI_GUID)); + VendorNode.LegacyDriveLetter = Drive->Number; + *DevicePath = AppendDevicePathNode (BaseDevicePath, &VendorNode.DevicePath.Header); + } +} + +/** + Build device path for EDD 3.0. + + @param BaseDevicePath Base device path. + @param Drive Legacy drive. + @param DevicePath Device path for output. + + @retval EFI_SUCCESS The device path is built successfully. + @retval EFI_UNSUPPORTED It is failed to built device path. + +**/ +EFI_STATUS +BuildEdd30DevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, + IN BIOS_LEGACY_DRIVE *Drive, + IN EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + // + // AVL UINT64 Address; + // AVL EFI_HANDLE Handle; + // + EFI_DEV_PATH Node; + UINT32 Controller; + + Controller = (UINT32) Drive->Parameters.InterfacePath.Pci.Controller; + + ZeroMem (&Node, sizeof (Node)); + if ((AsciiStrnCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) || + (AsciiStrnCmp ("ATA", Drive->Parameters.InterfaceType, 3) == 0) + ) { + // + // ATA or ATAPI drive found + // + Node.Atapi.Header.Type = MESSAGING_DEVICE_PATH; + Node.Atapi.Header.SubType = MSG_ATAPI_DP; + SetDevicePathNodeLength (&Node.Atapi.Header, sizeof (ATAPI_DEVICE_PATH)); + Node.Atapi.SlaveMaster = Drive->Parameters.DevicePath.Atapi.Master; + Node.Atapi.Lun = Drive->Parameters.DevicePath.Atapi.Lun; + Node.Atapi.PrimarySecondary = (UINT8) Controller; + } else { + // + // Not an ATA/ATAPI drive + // + if (Controller != 0) { + ZeroMem (&Node, sizeof (Node)); + Node.Controller.Header.Type = HARDWARE_DEVICE_PATH; + Node.Controller.Header.SubType = HW_CONTROLLER_DP; + SetDevicePathNodeLength (&Node.Controller.Header, sizeof (CONTROLLER_DEVICE_PATH)); + Node.Controller.ControllerNumber = Controller; + *DevicePath = AppendDevicePathNode (*DevicePath, &Node.DevPath); + } + + ZeroMem (&Node, sizeof (Node)); + + if (AsciiStrnCmp ("SCSI", Drive->Parameters.InterfaceType, 4) == 0) { + // + // SCSI drive + // + Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH; + Node.Scsi.Header.SubType = MSG_SCSI_DP; + SetDevicePathNodeLength (&Node.Scsi.Header, sizeof (SCSI_DEVICE_PATH)); + + // + // Lun is miss aligned in both EDD and Device Path data structures. + // thus we do a byte copy, to prevent alignment traps on IA-64. + // + CopyMem (&Node.Scsi.Lun, &Drive->Parameters.DevicePath.Scsi.Lun, sizeof (UINT16)); + Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.Pun; + + } else if (AsciiStrnCmp ("USB", Drive->Parameters.InterfaceType, 3) == 0) { + // + // USB drive + // + Node.Usb.Header.Type = MESSAGING_DEVICE_PATH; + Node.Usb.Header.SubType = MSG_USB_DP; + SetDevicePathNodeLength (&Node.Usb.Header, sizeof (USB_DEVICE_PATH)); + Node.Usb.ParentPortNumber = (UINT8) Drive->Parameters.DevicePath.Usb.Reserved; + + } else if (AsciiStrnCmp ("1394", Drive->Parameters.InterfaceType, 4) == 0) { + // + // 1394 drive + // + Node.F1394.Header.Type = MESSAGING_DEVICE_PATH; + Node.F1394.Header.SubType = MSG_1394_DP; + SetDevicePathNodeLength (&Node.F1394.Header, sizeof (F1394_DEVICE_PATH)); + Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid; + + } else if (AsciiStrnCmp ("FIBRE", Drive->Parameters.InterfaceType, 5) == 0) { + // + // Fibre drive + // + Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH; + Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP; + SetDevicePathNodeLength (&Node.FibreChannel.Header, sizeof (FIBRECHANNEL_DEVICE_PATH)); + Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn; + Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun; + + } else { + DEBUG ( + ( + DEBUG_BLKIO, "It is unrecognized EDD 3.0 device, Drive Number = %x, InterfaceType = %s\n", + Drive->Number, + Drive->Parameters.InterfaceType + ) + ); + } + } + + if (Node.DevPath.Type == 0) { + return EFI_UNSUPPORTED; + } + + *DevicePath = AppendDevicePathNode (BaseDevicePath, &Node.DevPath); + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h new file mode 100644 index 0000000000..91617b79d9 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h @@ -0,0 +1,432 @@ +/** @file + +Copyright (c) 1999 - 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 _BIOS_BLOCK_IO_H_ +#define _BIOS_BLOCK_IO_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Edd.h" + +// +// Global Variables +// +extern EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2; + + +// +// Define the I2O class code +// +#define PCI_BASE_CLASS_INTELLIGENT 0x0e +#define PCI_SUB_CLASS_INTELLIGENT 0x00 + +// +// Number of pages needed for our buffer under 1MB +// +#define BLOCK_IO_BUFFER_PAGE_SIZE (((sizeof (EDD_DEVICE_ADDRESS_PACKET) + sizeof (BIOS_LEGACY_DRIVE) + MAX_EDD11_XFER) / EFI_PAGE_SIZE) + 1 \ + ) + +// +// Driver Binding Protocol functions +// + +/** + Check whether the driver supports this device. + + @param This The Udriver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The driver supports this controller. + @retval other This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + + +/** + Starts the device with this driver. + + @param This The driver binding instance. + @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 The controller is controlled by the driver. + @retval Other This controller cannot be started. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop the device handled by this driver. + + @param This The driver binding protocol. + @param Controller The controller to release. + @param NumberOfChildren The number of handles in ChildHandleBuffer. + @param ChildHandleBuffer The array of child handle. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + @retval Others Fail to uninstall protocols attached on the device. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Other internal functions +// + +/** + Build device path for EDD 3.0. + + @param BaseDevicePath Base device path. + @param Drive Legacy drive. + @param DevicePath Device path for output. + + @retval EFI_SUCCESS The device path is built successfully. + @retval EFI_UNSUPPORTED It is failed to built device path. + +**/ +EFI_STATUS +BuildEdd30DevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, + IN BIOS_LEGACY_DRIVE *Drive, + IN EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Initialize block I/O device instance + + @param Dev Instance of block I/O device instance + + @retval TRUE Initialization succeeds. + @retval FALSE Initialization fails. + +**/ +BOOLEAN +BiosInitBlockIo ( + IN BIOS_BLOCK_IO_DEV *Dev + ); + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +Edd30BiosReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *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. + +**/ +EFI_STATUS +EFIAPI +Edd30BiosWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT 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. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *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. + +**/ +EFI_STATUS +EFIAPI +Edd11BiosReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *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. + +**/ +EFI_STATUS +EFIAPI +Edd11BiosWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +BiosReadLegacyDrive ( + IN EFI_BLOCK_IO_PROTOCOL *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. + +**/ +EFI_STATUS +EFIAPI +BiosWriteLegacyDrive ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Gets parameters of block I/O device. + + @param BiosBlockIoDev Instance of block I/O device. + @param Drive Legacy drive. + + @return Result of device parameter retrieval. + +**/ +UINTN +Int13GetDeviceParameters ( + IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, + IN BIOS_LEGACY_DRIVE *Drive + ); + +/** + Extension of INT13 call. + + @param BiosBlockIoDev Instance of block I/O device. + @param Drive Legacy drive. + + @return Result of this extension. + +**/ +UINTN +Int13Extensions ( + IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, + IN BIOS_LEGACY_DRIVE *Drive + ); + +/** + Gets parameters of legacy drive. + + @param BiosBlockIoDev Instance of block I/O device. + @param Drive Legacy drive. + + @return Result of drive parameter retrieval. + +**/ +UINTN +GetDriveParameters ( + IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, + IN BIOS_LEGACY_DRIVE *Drive + ); + +/** + Build device path for device. + + @param BaseDevicePath Base device path. + @param Drive Legacy drive. + @param DevicePath Device path for output. + +**/ +VOID +SetBiosInitBlockIoDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, + IN BIOS_LEGACY_DRIVE *Drive, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c new file mode 100644 index 0000000000..698bb620e8 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c @@ -0,0 +1,1495 @@ +/** @file + Routines that use BIOS to support INT 13 devices. + +Copyright (c) 1999 - 2015, Intel 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 "BiosBlkIo.h" + +// +// Module global variables +// +// +// Address packet is a buffer under 1 MB for all version EDD calls +// +extern EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb; + +// +// This is a buffer for INT 13h func 48 information +// +extern BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb; + +// +// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB +// 0xFE00 bytes is the max transfer size supported. +// +extern VOID *mEdd11Buffer; + + +/** + Initialize block I/O device instance + + @param Dev Instance of block I/O device instance + + @retval TRUE Initialization succeeds. + @retval FALSE Initialization fails. + +**/ +BOOLEAN +BiosInitBlockIo ( + IN BIOS_BLOCK_IO_DEV *Dev + ) +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *BlockMedia; + BIOS_LEGACY_DRIVE *Bios; + + BlockIo = &Dev->BlockIo; + BlockIo->Media = &Dev->BlockMedia; + BlockMedia = BlockIo->Media; + Bios = &Dev->Bios; + + if (Int13GetDeviceParameters (Dev, Bios) != 0) { + if (Int13Extensions (Dev, Bios) != 0) { + BlockMedia->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; + BlockMedia->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; + + if ((Bios->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) { + BlockMedia->RemovableMedia = TRUE; + } + + } else { + // + // Legacy Interfaces + // + BlockMedia->BlockSize = 512; + BlockMedia->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; + } + + DEBUG ((DEBUG_INIT, "BlockSize = %d LastBlock = %d\n", BlockMedia->BlockSize, BlockMedia->LastBlock)); + + BlockMedia->LogicalPartition = FALSE; + BlockMedia->WriteCaching = FALSE; + + // + // BugBug: Need to set this for removable media devices if they do not + // have media present + // + BlockMedia->ReadOnly = FALSE; + BlockMedia->MediaPresent = TRUE; + + BlockIo->Reset = BiosBlockIoReset; + BlockIo->FlushBlocks = BiosBlockIoFlushBlocks; + + if (!Bios->ExtendedInt13) { + // + // Legacy interfaces + // + BlockIo->ReadBlocks = BiosReadLegacyDrive; + BlockIo->WriteBlocks = BiosWriteLegacyDrive; + } else if ((Bios->EddVersion == EDD_VERSION_30) && (Bios->Extensions64Bit)) { + // + // EDD 3.0 Required for Device path, but extended reads are not required. + // + BlockIo->ReadBlocks = Edd30BiosReadBlocks; + BlockIo->WriteBlocks = Edd30BiosWriteBlocks; + } else { + // + // Assume EDD 1.1 - Read and Write functions. + // This could be EDD 3.0 without Extensions64Bit being set. + // If it's EDD 1.1 this will work, but the device path will not + // be correct. This will cause confusion to EFI OS installation. + // + BlockIo->ReadBlocks = Edd11BiosReadBlocks; + BlockIo->WriteBlocks = Edd11BiosWriteBlocks; + } + + BlockMedia->LogicalPartition = FALSE; + BlockMedia->WriteCaching = FALSE; + + return TRUE; + } + + return FALSE; +} + +/** + Gets parameters of block I/O device. + + @param BiosBlockIoDev Instance of block I/O device. + @param Drive Legacy drive. + + @return Result of device parameter retrieval. + +**/ +UINTN +Int13GetDeviceParameters ( + IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, + IN BIOS_LEGACY_DRIVE *Drive + ) +{ + UINTN CarryFlag; + UINT16 Cylinder; + EFI_IA32_REGISTER_SET Regs; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + Regs.H.AH = 0x08; + Regs.H.DL = Drive->Number; + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ((DEBUG_INIT, "Int13GetDeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); + if (CarryFlag != 0 || Regs.H.AH != 0x00) { + Drive->ErrorCode = Regs.H.AH; + return FALSE; + } + + if (Drive->Floppy) { + if (Regs.H.BL == 0x10) { + Drive->AtapiFloppy = TRUE; + } else { + Drive->MaxHead = Regs.H.DH; + Drive->MaxSector = Regs.H.CL; + Drive->MaxCylinder = Regs.H.CH; + if (Drive->MaxSector == 0) { + // + // BugBug: You can not trust the Carry flag. + // + return FALSE; + } + } + } else { + Drive->MaxHead = (UINT8) (Regs.H.DH & 0x3f); + Cylinder = (UINT16) (((UINT16) Regs.H.DH & 0xc0) << 4); + Cylinder = (UINT16) (Cylinder | ((UINT16) Regs.H.CL & 0xc0) << 2); + Drive->MaxCylinder = (UINT16) (Cylinder + Regs.H.CH); + Drive->MaxSector = (UINT8) (Regs.H.CL & 0x3f); + } + + return TRUE; +} + +/** + Extension of INT13 call. + + @param BiosBlockIoDev Instance of block I/O device. + @param Drive Legacy drive. + + @return Result of this extension. + +**/ +UINTN +Int13Extensions ( + IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, + IN BIOS_LEGACY_DRIVE *Drive + ) +{ + INTN CarryFlag; + EFI_IA32_REGISTER_SET Regs; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + Regs.H.AH = 0x41; + Regs.X.BX = 0x55aa; + Regs.H.DL = Drive->Number; + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ((DEBUG_INIT, "Int13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX)); + if (CarryFlag != 0 || Regs.X.BX != 0xaa55) { + Drive->ExtendedInt13 = FALSE; + Drive->DriveLockingAndEjecting = FALSE; + Drive->Edd = FALSE; + return FALSE; + } + + Drive->EddVersion = Regs.H.AH; + Drive->ExtendedInt13 = (BOOLEAN) ((Regs.X.CX & 0x01) == 0x01); + Drive->DriveLockingAndEjecting = (BOOLEAN) ((Regs.X.CX & 0x02) == 0x02); + Drive->Edd = (BOOLEAN) ((Regs.X.CX & 0x04) == 0x04); + Drive->Extensions64Bit = (BOOLEAN) (Regs.X.CX & 0x08); + + Drive->ParametersValid = (UINT8) GetDriveParameters (BiosBlockIoDev, Drive); + return TRUE; +} + +/** + Gets parameters of legacy drive. + + @param BiosBlockIoDev Instance of block I/O device. + @param Drive Legacy drive. + + @return Result of drive parameter retrieval. + +**/ +UINTN +GetDriveParameters ( + IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, + IN BIOS_LEGACY_DRIVE *Drive + ) +{ + INTN CarryFlag; + EFI_IA32_REGISTER_SET Regs; + UINTN PointerMath; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + Regs.H.AH = 0x48; + Regs.H.DL = Drive->Number; + + // + // EDD Buffer must be passed in with max buffer size as first entry in the buffer + // + mLegacyDriverUnder1Mb->Parameters.StructureSize = (UINT16) sizeof (EDD_DRIVE_PARAMETERS); + Regs.X.DS = EFI_SEGMENT ((UINTN)(&mLegacyDriverUnder1Mb->Parameters)); + Regs.X.SI = EFI_OFFSET ((UINTN)(&mLegacyDriverUnder1Mb->Parameters)); + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 48 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); + if (CarryFlag != 0 || Regs.H.AH != 0x00) { + Drive->ErrorCode = Regs.H.AH; + SetMem (&Drive->Parameters, sizeof (Drive->Parameters), 0xaf); + return FALSE; + } + // + // We only have one buffer < 1MB, so copy into our instance data + // + CopyMem ( + &Drive->Parameters, + &mLegacyDriverUnder1Mb->Parameters, + sizeof (Drive->Parameters) + ); + + if (Drive->AtapiFloppy) { + // + // Sense Media Type + // + Regs.H.AH = 0x20; + Regs.H.DL = Drive->Number; + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 20 DL=%02x : CF=%d AL=%02x\n", Drive->Number, CarryFlag, Regs.H.AL)); + if (CarryFlag != 0) { + // + // Media not present or unknown media present + // + if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) { + Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1); + Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack; + ASSERT (Drive->MaxSector != 0); + Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1); + } else { + Drive->MaxHead = 0; + Drive->MaxSector = 1; + Drive->MaxCylinder = 0; + } + + } else { + // + // Media Present + // + switch (Regs.H.AL) { + case 0x03: + // + // 720 KB + // + Drive->MaxHead = 1; + Drive->MaxSector = 9; + Drive->MaxCylinder = 79; + break; + + case 0x04: + // + // 1.44MB + // + Drive->MaxHead = 1; + Drive->MaxSector = 18; + Drive->MaxCylinder = 79; + break; + + case 0x06: + // + // 2.88MB + // + Drive->MaxHead = 1; + Drive->MaxSector = 36; + Drive->MaxCylinder = 79; + break; + + case 0x0C: + // + // 360 KB + // + Drive->MaxHead = 1; + Drive->MaxSector = 9; + Drive->MaxCylinder = 39; + break; + + case 0x0D: + // + // 1.2 MB + // + Drive->MaxHead = 1; + Drive->MaxSector = 15; + Drive->MaxCylinder = 79; + break; + + case 0x0E: + // + // Toshiba 3 mode + // + case 0x0F: + // + // NEC 3 mode + // + case 0x10: + // + // Default Media + // + if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) { + Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1); + Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack; + ASSERT (Drive->MaxSector != 0); + Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1); + } else { + Drive->MaxHead = 0; + Drive->MaxSector = 1; + Drive->MaxCylinder = 0; + } + break; + + default: + // + // Unknown media type. + // + Drive->MaxHead = 0; + Drive->MaxSector = 1; + Drive->MaxCylinder = 0; + break; + } + } + + Drive->Parameters.PhysicalSectors = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1); + Drive->Parameters.BytesPerSector = 512; + } + // + // This data comes from the BIOS so it may not allways be valid + // since the BIOS may reuse this buffer for future accesses + // + PointerMath = EFI_SEGMENT (Drive->Parameters.Fdpt) << 4; + PointerMath += EFI_OFFSET (Drive->Parameters.Fdpt); + Drive->FdptPointer = (VOID *) PointerMath; + + return TRUE; +} +// +// Block IO Routines +// + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +Edd30BiosReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + BIOS_BLOCK_IO_DEV *BiosBlockIoDev; + EDD_DEVICE_ADDRESS_PACKET *AddressPacket; + // + // I exist only for readability + // + EFI_IA32_REGISTER_SET Regs; + UINT64 TransferBuffer; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN BlockSize; + BIOS_LEGACY_DRIVE *Bios; + UINTN CarryFlag; + UINTN MaxTransferBlocks; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + Media = This->Media; + BlockSize = Media->BlockSize; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); + AddressPacket = mEddBufferUnder1Mb; + + MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; + + TransferBuffer = (UINT64)(UINTN) Buffer; + for (; BufferSize > 0;) { + NumberOfBlocks = BufferSize / BlockSize; + NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; + // + // Max transfer MaxTransferBlocks + // + AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); + AddressPacket->Zero = 0; + AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; + AddressPacket->Zero2 = 0; + AddressPacket->SegOffset = 0xffffffff; + AddressPacket->Lba = (UINT64) Lba; + AddressPacket->TransferBuffer = TransferBuffer; + + Regs.H.AH = 0x42; + Regs.H.DL = BiosBlockIoDev->Bios.Number; + Regs.X.SI = EFI_OFFSET (AddressPacket); + Regs.X.DS = EFI_SEGMENT (AddressPacket); + + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ( + ( + DEBUG_BLKIO, "Edd30BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, + CarryFlag, Regs.H.AH + ) + ); + + Media->MediaPresent = TRUE; + if (CarryFlag != 0) { + // + // Return Error Status + // + BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; + if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { + Media->MediaId++; + Bios = &BiosBlockIoDev->Bios; + if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { + if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { + Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; + } else { + ASSERT (FALSE); + } + + Media->ReadOnly = FALSE; + gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); + gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + return EFI_MEDIA_CHANGED; + } + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + return EFI_DEVICE_ERROR; + } + + TransferByteSize = NumberOfBlocks * BlockSize; + BufferSize = BufferSize - TransferByteSize; + TransferBuffer += TransferByteSize; + Lba += NumberOfBlocks; + } + + return EFI_SUCCESS; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +Edd30BiosWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + BIOS_BLOCK_IO_DEV *BiosBlockIoDev; + EDD_DEVICE_ADDRESS_PACKET *AddressPacket; + // + // I exist only for readability + // + EFI_IA32_REGISTER_SET Regs; + UINT64 TransferBuffer; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN BlockSize; + BIOS_LEGACY_DRIVE *Bios; + UINTN CarryFlag; + UINTN MaxTransferBlocks; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + Media = This->Media; + BlockSize = Media->BlockSize; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (Lba > Media->LastBlock) { + return EFI_DEVICE_ERROR; + } + + if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); + AddressPacket = mEddBufferUnder1Mb; + + MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; + + TransferBuffer = (UINT64)(UINTN) Buffer; + for (; BufferSize > 0;) { + NumberOfBlocks = BufferSize / BlockSize; + NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; + // + // Max transfer MaxTransferBlocks + // + AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); + AddressPacket->Zero = 0; + AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; + AddressPacket->Zero2 = 0; + AddressPacket->SegOffset = 0xffffffff; + AddressPacket->Lba = (UINT64) Lba; + AddressPacket->TransferBuffer = TransferBuffer; + + Regs.H.AH = 0x43; + Regs.H.AL = 0x00; + // + // Write Verify Off + // + Regs.H.DL = (UINT8) (BiosBlockIoDev->Bios.Number); + Regs.X.SI = EFI_OFFSET (AddressPacket); + Regs.X.DS = EFI_SEGMENT (AddressPacket); + + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ( + ( + DEBUG_BLKIO, "Edd30BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, + CarryFlag, Regs.H.AH + ) + ); + + Media->MediaPresent = TRUE; + if (CarryFlag != 0) { + // + // Return Error Status + // + BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; + if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { + Media->MediaId++; + Bios = &BiosBlockIoDev->Bios; + if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { + if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { + Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; + } else { + ASSERT (FALSE); + } + + Media->ReadOnly = FALSE; + gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); + gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + return EFI_MEDIA_CHANGED; + } + } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { + Media->ReadOnly = TRUE; + return EFI_WRITE_PROTECTED; + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + return EFI_DEVICE_ERROR; + } + + Media->ReadOnly = FALSE; + TransferByteSize = NumberOfBlocks * BlockSize; + BufferSize = BufferSize - TransferByteSize; + TransferBuffer += TransferByteSize; + Lba += NumberOfBlocks; + } + + return EFI_SUCCESS; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + BIOS_BLOCK_IO_DEV *BiosBlockIoDev; + EFI_IA32_REGISTER_SET Regs; + UINTN CarryFlag; + + BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + Regs.H.AH = 0x00; + Regs.H.DL = BiosBlockIoDev->Bios.Number; + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ( + ( + DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag, + Regs.H.AH + ) + ); + if (CarryFlag != 0) { + if (Regs.H.AL == BIOS_RESET_FAILED) { + Regs.H.AH = 0x00; + Regs.H.DL = BiosBlockIoDev->Bios.Number; + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ( + ( + DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag, + Regs.H.AH + ) + ); + if (CarryFlag != 0) { + BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; + return EFI_DEVICE_ERROR; + } + } + } + + return EFI_SUCCESS; +} +// +// +// These functions need to double buffer all data under 1MB! +// +// + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +Edd11BiosReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + BIOS_BLOCK_IO_DEV *BiosBlockIoDev; + EDD_DEVICE_ADDRESS_PACKET *AddressPacket; + // + // I exist only for readability + // + EFI_IA32_REGISTER_SET Regs; + UINT64 TransferBuffer; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN BlockSize; + BIOS_LEGACY_DRIVE *Bios; + UINTN CarryFlag; + UINTN MaxTransferBlocks; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + Media = This->Media; + BlockSize = Media->BlockSize; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); + AddressPacket = mEddBufferUnder1Mb; + + MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; + + TransferBuffer = (UINT64)(UINTN) mEdd11Buffer; + for (; BufferSize > 0;) { + NumberOfBlocks = BufferSize / BlockSize; + NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; + // + // Max transfer MaxTransferBlocks + // + AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); + AddressPacket->Zero = 0; + AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; + AddressPacket->Zero2 = 0; + // + // TransferBuffer has been 4KB alignment. Normalize TransferBuffer to make offset as 0 in seg:offset + // format to transfer maximum 127 blocks of data. + // Otherwise when offset adding data size exceeds 0xFFFF, if OpROM does not normalize TransferBuffer, + // INT13 function 42H will return data boundary error 09H. + // + AddressPacket->SegOffset = (UINT32) LShiftU64 (RShiftU64(TransferBuffer, 4), 16); + AddressPacket->Lba = (UINT64) Lba; + + Regs.H.AH = 0x42; + Regs.H.DL = BiosBlockIoDev->Bios.Number; + Regs.X.SI = EFI_OFFSET (AddressPacket); + Regs.X.DS = EFI_SEGMENT (AddressPacket); + + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ( + ( + DEBUG_BLKIO, "Edd11BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n", + BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks + ) + ); + Media->MediaPresent = TRUE; + if (CarryFlag != 0) { + // + // Return Error Status + // + BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; + if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { + Media->MediaId++; + Bios = &BiosBlockIoDev->Bios; + if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { + if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { + Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; + } else { + ASSERT (FALSE); + } + + Media->ReadOnly = FALSE; + gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); + gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + return EFI_MEDIA_CHANGED; + } + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + return EFI_DEVICE_ERROR; + } + + TransferByteSize = NumberOfBlocks * BlockSize; + CopyMem (Buffer, (VOID *) (UINTN) TransferBuffer, TransferByteSize); + BufferSize = BufferSize - TransferByteSize; + Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); + Lba += NumberOfBlocks; + } + + return EFI_SUCCESS; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +Edd11BiosWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + BIOS_BLOCK_IO_DEV *BiosBlockIoDev; + EDD_DEVICE_ADDRESS_PACKET *AddressPacket; + // + // I exist only for readability + // + EFI_IA32_REGISTER_SET Regs; + UINT64 TransferBuffer; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN BlockSize; + BIOS_LEGACY_DRIVE *Bios; + UINTN CarryFlag; + UINTN MaxTransferBlocks; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + Media = This->Media; + BlockSize = Media->BlockSize; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); + AddressPacket = mEddBufferUnder1Mb; + + MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; + + TransferBuffer = (UINT64)(UINTN) mEdd11Buffer; + for (; BufferSize > 0;) { + NumberOfBlocks = BufferSize / BlockSize; + NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; + // + // Max transfer MaxTransferBlocks + // + AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); + AddressPacket->Zero = 0; + AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; + AddressPacket->Zero2 = 0; + // + // TransferBuffer has been 4KB alignment. Normalize TransferBuffer to make offset as 0 in seg:offset + // format to transfer maximum 127 blocks of data. + // Otherwise when offset adding data size exceeds 0xFFFF, if OpROM does not normalize TransferBuffer, + // INT13 function 42H will return data boundary error 09H. + // + AddressPacket->SegOffset = (UINT32) LShiftU64 (RShiftU64(TransferBuffer, 4), 16); + AddressPacket->Lba = (UINT64) Lba; + + Regs.H.AH = 0x43; + Regs.H.AL = 0x00; + // + // Write Verify disable + // + Regs.H.DL = BiosBlockIoDev->Bios.Number; + Regs.X.SI = EFI_OFFSET (AddressPacket); + Regs.X.DS = EFI_SEGMENT (AddressPacket); + + TransferByteSize = NumberOfBlocks * BlockSize; + CopyMem ((VOID *) (UINTN) TransferBuffer, Buffer, TransferByteSize); + + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ( + ( + DEBUG_BLKIO, "Edd11BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n", + BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks + ) + ); + Media->MediaPresent = TRUE; + if (CarryFlag != 0) { + // + // Return Error Status + // + BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; + if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { + Media->MediaId++; + Bios = &BiosBlockIoDev->Bios; + if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { + if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { + Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; + } else { + ASSERT (FALSE); + } + + Media->ReadOnly = FALSE; + gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); + gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + return EFI_MEDIA_CHANGED; + } + } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { + Media->ReadOnly = TRUE; + return EFI_WRITE_PROTECTED; + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + return EFI_DEVICE_ERROR; + } + + Media->ReadOnly = FALSE; + BufferSize = BufferSize - TransferByteSize; + Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); + Lba += NumberOfBlocks; + } + + return EFI_SUCCESS; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +BiosReadLegacyDrive ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + BIOS_BLOCK_IO_DEV *BiosBlockIoDev; + EFI_IA32_REGISTER_SET Regs; + UINTN UpperCylinder; + UINTN Temp; + UINTN Cylinder; + UINTN Head; + UINTN Sector; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN ShortLba; + UINTN CheckLba; + UINTN BlockSize; + BIOS_LEGACY_DRIVE *Bios; + UINTN CarryFlag; + UINTN Retry; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + Media = This->Media; + BlockSize = Media->BlockSize; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); + ShortLba = (UINTN) Lba; + + while (BufferSize != 0) { + // + // Compute I/O location in Sector, Head, Cylinder format + // + Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1; + Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector; + Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1); + Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1); + + // + // Limit transfer to this Head & Cylinder + // + NumberOfBlocks = BufferSize / BlockSize; + Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1; + NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks; + + Retry = 3; + do { + // + // Perform the IO + // + Regs.H.AH = 2; + Regs.H.AL = (UINT8) NumberOfBlocks; + Regs.H.DL = BiosBlockIoDev->Bios.Number; + + UpperCylinder = (Cylinder & 0x0f00) >> 2; + + CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head; + CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1; + + DEBUG ( + (DEBUG_BLKIO, + "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n", + ShortLba, + CheckLba, + Sector, + BiosBlockIoDev->Bios.MaxSector, + Head, + BiosBlockIoDev->Bios.MaxHead, + Cylinder, + UpperCylinder) + ); + ASSERT (CheckLba == ShortLba); + + Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)); + Regs.H.DH = (UINT8) (Head & 0x3f); + Regs.H.CH = (UINT8) (Cylinder & 0xff); + + Regs.X.BX = EFI_OFFSET (mEdd11Buffer); + Regs.X.ES = EFI_SEGMENT (mEdd11Buffer); + + DEBUG ( + (DEBUG_BLKIO, + "INT 13h: AX:(02%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n", + Regs.H.AL, + (UINT8) (Head & 0x3f), + Regs.H.DL, + (UINT8) (Cylinder & 0xff), + (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)), + EFI_OFFSET (mEdd11Buffer), + EFI_SEGMENT (mEdd11Buffer)) + ); + + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ( + ( + DEBUG_BLKIO, "BiosReadLegacyDrive: INT 13 02 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, + CarryFlag, Regs.H.AH + ) + ); + Retry--; + } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED); + + Media->MediaPresent = TRUE; + if (CarryFlag != 0) { + // + // Return Error Status + // + BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; + if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { + Media->MediaId++; + Bios = &BiosBlockIoDev->Bios; + if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { + // + // If the size of the media changed we need to reset the disk geometry + // + if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { + Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; + } else { + // + // Legacy Interfaces + // + Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; + Media->BlockSize = 512; + } + + Media->ReadOnly = FALSE; + gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); + gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + return EFI_MEDIA_CHANGED; + } + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + return EFI_DEVICE_ERROR; + } + + TransferByteSize = NumberOfBlocks * BlockSize; + CopyMem (Buffer, mEdd11Buffer, TransferByteSize); + + ShortLba = ShortLba + NumberOfBlocks; + BufferSize = BufferSize - TransferByteSize; + Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); + } + + return EFI_SUCCESS; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +BiosWriteLegacyDrive ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_BLOCK_IO_MEDIA *Media; + BIOS_BLOCK_IO_DEV *BiosBlockIoDev; + EFI_IA32_REGISTER_SET Regs; + UINTN UpperCylinder; + UINTN Temp; + UINTN Cylinder; + UINTN Head; + UINTN Sector; + UINTN NumberOfBlocks; + UINTN TransferByteSize; + UINTN ShortLba; + UINTN CheckLba; + UINTN BlockSize; + BIOS_LEGACY_DRIVE *Bios; + UINTN CarryFlag; + UINTN Retry; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + Media = This->Media; + BlockSize = Media->BlockSize; + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (Lba > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); + ShortLba = (UINTN) Lba; + + while (BufferSize != 0) { + // + // Compute I/O location in Sector, Head, Cylinder format + // + Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1; + Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector; + Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1); + Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1); + + // + // Limit transfer to this Head & Cylinder + // + NumberOfBlocks = BufferSize / BlockSize; + Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1; + NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks; + + Retry = 3; + do { + // + // Perform the IO + // + Regs.H.AH = 3; + Regs.H.AL = (UINT8) NumberOfBlocks; + Regs.H.DL = BiosBlockIoDev->Bios.Number; + + UpperCylinder = (Cylinder & 0x0f00) >> 2; + + CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head; + CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1; + + DEBUG ( + (DEBUG_BLKIO, + "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n", + ShortLba, + CheckLba, + Sector, + BiosBlockIoDev->Bios.MaxSector, + Head, + BiosBlockIoDev->Bios.MaxHead, + Cylinder, + UpperCylinder) + ); + ASSERT (CheckLba == ShortLba); + + Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)); + Regs.H.DH = (UINT8) (Head & 0x3f); + Regs.H.CH = (UINT8) (Cylinder & 0xff); + + Regs.X.BX = EFI_OFFSET (mEdd11Buffer); + Regs.X.ES = EFI_SEGMENT (mEdd11Buffer); + + TransferByteSize = NumberOfBlocks * BlockSize; + CopyMem (mEdd11Buffer, Buffer, TransferByteSize); + + DEBUG ( + (DEBUG_BLKIO, + "INT 13h: AX:(03%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n", + Regs.H.AL, + (UINT8) (Head & 0x3f), + Regs.H.DL, + (UINT8) (Cylinder & 0xff), + (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)), + EFI_OFFSET (mEdd11Buffer), + EFI_SEGMENT (mEdd11Buffer)) + ); + + CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); + DEBUG ( + ( + DEBUG_BLKIO, "BiosWriteLegacyDrive: INT 13 03 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, + CarryFlag, Regs.H.AH + ) + ); + Retry--; + } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED); + + Media->MediaPresent = TRUE; + if (CarryFlag != 0) { + // + // Return Error Status + // + BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; + if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { + Media->MediaId++; + Bios = &BiosBlockIoDev->Bios; + if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { + if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { + Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; + Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; + } else { + // + // Legacy Interfaces + // + Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; + Media->BlockSize = 512; + } + // + // If the size of the media changed we need to reset the disk geometry + // + Media->ReadOnly = FALSE; + gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); + gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); + return EFI_MEDIA_CHANGED; + } + } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { + Media->ReadOnly = TRUE; + return EFI_WRITE_PROTECTED; + } + + if (Media->RemovableMedia) { + Media->MediaPresent = FALSE; + } + + return EFI_DEVICE_ERROR; + } + + Media->ReadOnly = FALSE; + ShortLba = ShortLba + NumberOfBlocks; + BufferSize = BufferSize - TransferByteSize; + Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); + } + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf new file mode 100644 index 0000000000..86dd325d23 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf @@ -0,0 +1,65 @@ +## @file +# BIOS Block IO module. +# +# This is the UEFI driver to thunk legacy BIOS int13 interface into UEFI block IO interface. +# Once connected it installs EfiBlockIoProtocol on top of legacy BIOS int13. +# +# 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 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 = BlockIoDxe + MODULE_UNI_FILE = BlockIoDxe.uni + FILE_GUID = 4495E47E-42A9-4007-8c17-B6664F909D04 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = BiosBlockIoDriverEntryPoint + +[Sources] + BiosBlkIo.h + Edd.h + BiosBlkIo.c + BiosInt13.c + ComponentName.c + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + BaseMemoryLib + UefiBootServicesTableLib + UefiLib + DevicePathLib + MemoryAllocationLib + + +[Protocols] + gEfiBlockIoProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## TO_START + gEfiPciIoProtocolGuid ## TO_START + gEfiLegacyBiosProtocolGuid ## TO_START + + +[Guids] + gEfiLegacyBiosGuid ## PRODUCES ## UNDEFINED + gBlockIoVendorGuid ## SOMETIMES_CONSUMES ## UNDEFINED + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[UserExtensions.TianoCore."ExtraFiles"] + BlockIoDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni new file mode 100644 index 0000000000..6698430ee1 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni new file mode 100644 index 0000000000..900682d090 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c new file mode 100644 index 0000000000..21d17305fa --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c @@ -0,0 +1,309 @@ +/** @file + +Copyright (c) 1999 - 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 "BiosBlkIo.h" + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoComponentNameGetDriverName ( + 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 +BiosBlockIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName = { + BiosBlockIoComponentNameGetDriverName, + BiosBlockIoComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosBlockIoComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosBlockIoComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosBlockIoDriverNameTable[] = { + { + "eng;en", + L"BIOS[INT13] Block Io Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosBlockIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mBiosBlockIoDriverNameTable, + DriverName, + (BOOLEAN)(This == &gBiosBlockIoComponentName) + ); +} + +/** + 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 +BiosBlockIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h new file mode 100644 index 0000000000..be4d8302cf --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h @@ -0,0 +1,209 @@ +/** @file + Include file to suport EDD 3.0. + This file is coded to T13 D1386 Revision 3 + Availible on http://www.t13.org/#Project drafts + Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r3.pdf + +Copyright (c) 1999 - 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 _EDD_H_ +#define _EDD_H_ + +// +// packing with no compiler padding, so that the fields +// of the following architected structures can be +// properly accessed from C code. +// +#pragma pack(1) + +typedef struct { + UINT8 Bus; + UINT8 Device; + UINT8 Function; + UINT8 Controller; + UINT32 Reserved; +} EDD_PCI; + +typedef struct { + UINT16 Base; + UINT16 Reserved; + UINT32 Reserved2; +} EDD_LEGACY; + +typedef union { + EDD_PCI Pci; + EDD_LEGACY Legacy; +} EDD_INTERFACE_PATH; + +typedef struct { + UINT8 Master; + UINT8 Reserved[15]; +} EDD_ATA; + +typedef struct { + UINT8 Master; + UINT8 Lun; + UINT8 Reserved[14]; +} EDD_ATAPI; + +typedef struct { + UINT16 Pun; + UINT64 Lun; + UINT8 Reserved[6]; +} EDD_SCSI; + +typedef struct { + UINT64 SerialNumber; + UINT64 Reserved; +} EDD_USB; + +typedef struct { + UINT64 Guid; + UINT64 Reserved; +} EDD_1394; + +typedef struct { + UINT64 Wwn; + UINT64 Lun; +} EDD_FIBRE; + +typedef union { + EDD_ATA Ata; + EDD_ATAPI Atapi; + EDD_SCSI Scsi; + EDD_USB Usb; + EDD_1394 FireWire; + EDD_FIBRE FibreChannel; +} EDD_DEVICE_PATH; + +typedef struct { + UINT16 StructureSize; + UINT16 Flags; + UINT32 MaxCylinders; + UINT32 MaxHeads; + UINT32 SectorsPerTrack; + UINT64 PhysicalSectors; + UINT16 BytesPerSector; + UINT32 Fdpt; + UINT16 Key; + UINT8 DevicePathLength; + UINT8 Reserved1; + UINT16 Reserved2; + CHAR8 HostBusType[4]; + CHAR8 InterfaceType[8]; + EDD_INTERFACE_PATH InterfacePath; + EDD_DEVICE_PATH DevicePath; + UINT8 Reserved3; + UINT8 Checksum; +} EDD_DRIVE_PARAMETERS; + +// +// EDD_DRIVE_PARAMETERS.Flags defines +// +#define EDD_GEOMETRY_VALID 0x02 +#define EDD_DEVICE_REMOVABLE 0x04 +#define EDD_WRITE_VERIFY_SUPPORTED 0x08 +#define EDD_DEVICE_CHANGE 0x10 +#define EDD_DEVICE_LOCKABLE 0x20 + +// +// BUGBUG: This bit does not follow the spec. It tends to be always set +// to work properly with Win98. +// +#define EDD_DEVICE_GEOMETRY_MAX 0x40 + +typedef struct { + UINT8 PacketSizeInBytes; // 0x18 + UINT8 Zero; + UINT8 NumberOfBlocks; // Max 0x7f + UINT8 Zero2; + UINT32 SegOffset; + UINT64 Lba; + UINT64 TransferBuffer; + UINT32 ExtendedBlockCount; // Max 0xffffffff + UINT32 Zero3; +} EDD_DEVICE_ADDRESS_PACKET; + +#define EDD_VERSION_30 0x30 + +// +// Int 13 BIOS Errors +// +#define BIOS_PASS 0x00 +#define BIOS_WRITE_PROTECTED 0x03 +#define BIOS_SECTOR_NOT_FOUND 0x04 +#define BIOS_RESET_FAILED 0x05 +#define BIOS_DISK_CHANGED 0x06 +#define BIOS_DRIVE_DOES_NOT_EXIST 0x07 +#define BIOS_DMA_ERROR 0x08 +#define BIOS_DATA_BOUNDRY_ERROR 0x09 +#define BIOS_BAD_SECTOR 0x0a +#define BIOS_BAD_TRACK 0x0b +#define BIOS_MEADIA_TYPE_NOT_FOUND 0x0c +#define BIOS_INVALED_FORMAT 0x0d +#define BIOS_ECC_ERROR 0x10 +#define BIOS_ECC_CORRECTED_ERROR 0x11 +#define BIOS_HARD_DRIVE_FAILURE 0x20 +#define BIOS_SEEK_FAILED 0x40 +#define BIOS_DRIVE_TIMEOUT 0x80 +#define BIOS_DRIVE_NOT_READY 0xaa +#define BIOS_UNDEFINED_ERROR 0xbb +#define BIOS_WRITE_FAULT 0xcc +#define BIOS_SENSE_FAILED 0xff + +#define MAX_EDD11_XFER 0xfe00 + +#pragma pack() +// +// Internal Data Structures +// +typedef struct { + CHAR8 Letter; + UINT8 Number; + UINT8 EddVersion; + BOOLEAN ExtendedInt13; + BOOLEAN DriveLockingAndEjecting; + BOOLEAN Edd; + BOOLEAN Extensions64Bit; + BOOLEAN ParametersValid; + UINT8 ErrorCode; + VOID *FdptPointer; + BOOLEAN Floppy; + BOOLEAN AtapiFloppy; + UINT8 MaxHead; + UINT8 MaxSector; + UINT16 MaxCylinder; + UINT16 Pad; + EDD_DRIVE_PARAMETERS Parameters; +} BIOS_LEGACY_DRIVE; + +#define BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE SIGNATURE_32 ('b', 'b', 'i', 'o') +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_HANDLE ControllerHandle; + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_BLOCK_IO_MEDIA BlockMedia; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + BIOS_LEGACY_DRIVE Bios; + +} BIOS_BLOCK_IO_DEV; + +#define BIOS_BLOCK_IO_FROM_THIS(a) CR (a, BIOS_BLOCK_IO_DEV, BlockIo, BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE) + +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c new file mode 100644 index 0000000000..8c7019f4f6 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c @@ -0,0 +1,2428 @@ +/** @file + ConsoleOut Routines that speak VGA. + +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 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 "BiosKeyboard.h" + +// +// EFI Driver Binding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding = { + BiosKeyboardDriverBindingSupported, + BiosKeyboardDriverBindingStart, + BiosKeyboardDriverBindingStop, + 0x3, + NULL, + NULL +}; + + +/** + Enqueue the key. + + @param Queue The queue to be enqueued. + @param KeyData The key data to be enqueued. + + @retval EFI_NOT_READY The queue is full. + @retval EFI_SUCCESS Successfully enqueued the key data. + +**/ +EFI_STATUS +Enqueue ( + IN SIMPLE_QUEUE *Queue, + IN EFI_KEY_DATA *KeyData + ) +{ + if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) { + return EFI_NOT_READY; + } + + CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA)); + Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT; + + return EFI_SUCCESS; +} + + +/** + Dequeue the key. + + @param Queue The queue to be dequeued. + @param KeyData The key data to be dequeued. + + @retval EFI_NOT_READY The queue is empty. + @retval EFI_SUCCESS Successfully dequeued the key data. + +**/ +EFI_STATUS +Dequeue ( + IN SIMPLE_QUEUE *Queue, + IN EFI_KEY_DATA *KeyData + ) +{ + if (Queue->Front == Queue->Rear) { + return EFI_NOT_READY; + } + + CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA)); + Queue->Front = (Queue->Front + 1) % QUEUE_MAX_COUNT; + + return EFI_SUCCESS; +} + + +/** + Check whether the queue is empty. + + @param Queue The queue to be checked. + + @retval EFI_NOT_READY The queue is empty. + @retval EFI_SUCCESS The queue is not empty. + +**/ +EFI_STATUS +CheckQueue ( + IN SIMPLE_QUEUE *Queue + ) +{ + if (Queue->Front == Queue->Rear) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +// +// EFI Driver Binding Protocol Functions +// + +/** + Check whether the driver supports this device. + + @param This The Udriver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The driver supports this controller. + @retval other This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_ISA_IO_PROTOCOL *IsaIo; + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID **) &LegacyBios + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Use the ISA I/O Protocol to see if Controller is the Keyboard controller + // + if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) { + Status = EFI_UNSUPPORTED; + } + + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Starts the device with this driver. + + @param This The driver binding instance. + @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 The controller is controlled by the driver. + @retval Other This controller cannot be started. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_ISA_IO_PROTOCOL *IsaIo; + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + EFI_IA32_REGISTER_SET Regs; + BOOLEAN CarryFlag; + EFI_PS2_POLICY_PROTOCOL *Ps2Policy; + UINT8 Command; + EFI_STATUS_CODE_VALUE StatusCode; + + BiosKeyboardPrivate = NULL; + IsaIo = NULL; + StatusCode = 0; + + // + // Get Ps2 policy to set. Will be use if present. + // + gBS->LocateProtocol ( + &gEfiPs2PolicyProtocolGuid, + NULL, + (VOID **) &Ps2Policy + ); + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID **) &LegacyBios + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate the private device structure + // + BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV)); + if (NULL == BiosKeyboardPrivate) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Initialize the private device structure + // + BiosKeyboardPrivate->Signature = BIOS_KEYBOARD_DEV_SIGNATURE; + BiosKeyboardPrivate->Handle = Controller; + BiosKeyboardPrivate->LegacyBios = LegacyBios; + BiosKeyboardPrivate->IsaIo = IsaIo; + + BiosKeyboardPrivate->SimpleTextIn.Reset = BiosKeyboardReset; + BiosKeyboardPrivate->SimpleTextIn.ReadKeyStroke = BiosKeyboardReadKeyStroke; + + BiosKeyboardPrivate->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER; + BiosKeyboardPrivate->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER; + BiosKeyboardPrivate->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER; + BiosKeyboardPrivate->ExtendedKeyboard = TRUE; + + BiosKeyboardPrivate->Queue.Front = 0; + BiosKeyboardPrivate->Queue.Rear = 0; + BiosKeyboardPrivate->SimpleTextInputEx.Reset = BiosKeyboardResetEx; + BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx; + BiosKeyboardPrivate->SimpleTextInputEx.SetState = BiosKeyboardSetState; + BiosKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify = BiosKeyboardRegisterKeyNotify; + BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify; + InitializeListHead (&BiosKeyboardPrivate->NotifyList); + + // + // Report that the keyboard is being enabled + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE + ); + + // + // Setup the WaitForKey event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + BiosKeyboardWaitForKey, + &(BiosKeyboardPrivate->SimpleTextIn), + &((BiosKeyboardPrivate->SimpleTextIn).WaitForKey) + ); + if (EFI_ERROR (Status)) { + (BiosKeyboardPrivate->SimpleTextIn).WaitForKey = NULL; + goto Done; + } + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + BiosKeyboardWaitForKeyEx, + &(BiosKeyboardPrivate->SimpleTextInputEx), + &(BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx) + ); + if (EFI_ERROR (Status)) { + BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL; + goto Done; + } + + // + // Setup a periodic timer, used for reading keystrokes at a fixed interval + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + BiosKeyboardTimerHandler, + BiosKeyboardPrivate, + &BiosKeyboardPrivate->TimerEvent + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; + goto Done; + } + + Status = gBS->SetTimer ( + BiosKeyboardPrivate->TimerEvent, + TimerPeriodic, + KEYBOARD_TIMER_INTERVAL + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; + goto Done; + } + + // + // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT + ); + + // + // Reset the keyboard device + // + Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset ( + &BiosKeyboardPrivate->SimpleTextInputEx, + FeaturePcdGet (PcdPs2KbdExtendedVerification) + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status)); + StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; + goto Done; + } + // + // Do platform specific policy like port swapping and keyboard light default + // + if (Ps2Policy != NULL) { + + Ps2Policy->Ps2InitHardware (Controller); + + Command = 0; + if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) { + Command |= 4; + } + + if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) { + Command |= 2; + } + + if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) { + Command |= 1; + } + + KeyboardWrite (BiosKeyboardPrivate, 0xed); + KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT); + KeyboardWrite (BiosKeyboardPrivate, Command); + // + // Call Legacy BIOS Protocol to set whatever is necessary + // + LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command); + } + // + // Get Configuration + // + Regs.H.AH = 0xc0; + CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 ( + BiosKeyboardPrivate->LegacyBios, + 0x15, + &Regs + ); + + if (!CarryFlag) { + // + // Check bit 6 of Feature Byte 2. + // If it is set, then Int 16 Func 09 is supported + // + if (*(UINT8 *)(UINTN) ((Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) { + // + // Get Keyboard Functionality + // + Regs.H.AH = 0x09; + CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 ( + BiosKeyboardPrivate->LegacyBios, + 0x16, + &Regs + ); + + if (!CarryFlag) { + // + // Check bit 5 of AH. + // If it is set, then INT 16 Finc 10-12 are supported. + // + if ((Regs.H.AL & 0x40) != 0) { + // + // Set the flag to use INT 16 Func 10-12 + // + BiosKeyboardPrivate->ExtendedKeyboard = TRUE; + } + } + } + } + DEBUG ((EFI_D_INFO, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN)BiosKeyboardPrivate->ExtendedKeyboard)); + // + // Install protocol interfaces for the keyboard device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextInProtocolGuid, + &BiosKeyboardPrivate->SimpleTextIn, + &gEfiSimpleTextInputExProtocolGuid, + &BiosKeyboardPrivate->SimpleTextInputEx, + NULL + ); + +Done: + if (StatusCode != 0) { + // + // Report an Error Code for failing to start the keyboard device + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + StatusCode + ); + } + + if (EFI_ERROR (Status)) { + + if (BiosKeyboardPrivate != NULL) { + if ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) { + gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey); + } + + if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) { + gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx); + } + BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList); + + if (BiosKeyboardPrivate->TimerEvent != NULL) { + gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent); + } + + FreePool (BiosKeyboardPrivate); + } + + if (IsaIo != NULL) { + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + } + + return Status; +} + +/** + Stop the device handled by this driver. + + @param This The driver binding protocol. + @param Controller The controller to release. + @param NumberOfChildren The number of handles in ChildHandleBuffer. + @param ChildHandleBuffer The array of child handle. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + @retval Others Fail to uninstall protocols attached on the device. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn; + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + + // + // Disable Keyboard + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &SimpleTextIn, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextInputExProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (SimpleTextIn); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleTextInProtocolGuid, + &BiosKeyboardPrivate->SimpleTextIn, + &gEfiSimpleTextInputExProtocolGuid, + &BiosKeyboardPrivate->SimpleTextInputEx, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Release the IsaIo protocol on the controller handle + // + gBS->CloseProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Free other resources + // + gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey); + gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent); + gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx); + BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList); + + FreePool (BiosKeyboardPrivate); + + return EFI_SUCCESS; +} + +/** + Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer-empty state. + + @param BiosKeyboardPrivate Keyboard instance pointer. + + @return The data byte read from output buffer of Keyboard Controller from data port which often is port 60H. + +**/ +UINT8 +KeyReadDataRegister ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate + ) +{ + UINT8 Data; + + // + // Use IsaIo protocol to perform IO operations + // + BiosKeyboardPrivate->IsaIo->Io.Read ( + BiosKeyboardPrivate->IsaIo, + EfiIsaIoWidthUint8, + BiosKeyboardPrivate->DataRegisterAddress, + 1, + &Data + ); + + return Data; +} + +/** + Read status byte from status register of Keyboard Controller without delay and waiting for buffer-empty state. + + @param BiosKeyboardPrivate Keyboard instance pointer. + + @return The status byte read from status register of Keyboard Controller from command port which often is port 64H. + +**/ +UINT8 +KeyReadStatusRegister ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate + ) +{ + UINT8 Data; + + // + // Use IsaIo protocol to perform IO operations + // + BiosKeyboardPrivate->IsaIo->Io.Read ( + BiosKeyboardPrivate->IsaIo, + EfiIsaIoWidthUint8, + BiosKeyboardPrivate->StatusRegisterAddress, + 1, + &Data + ); + + return Data; +} + +/** + Write command byte to control register of Keyboard Controller without delay and waiting for buffer-empty state. + + @param BiosKeyboardPrivate Keyboard instance pointer. + @param Data Data byte to write. + +**/ +VOID +KeyWriteCommandRegister ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + IN UINT8 Data + ) +{ + // + // Use IsaIo protocol to perform IO operations + // + BiosKeyboardPrivate->IsaIo->Io.Write ( + BiosKeyboardPrivate->IsaIo, + EfiIsaIoWidthUint8, + BiosKeyboardPrivate->CommandRegisterAddress, + 1, + &Data + ); +} + +/** + Write data byte to input buffer or input/output ports of Keyboard Controller without delay and waiting for buffer-empty state. + + @param BiosKeyboardPrivate Keyboard instance pointer. + @param Data Data byte to write. + +**/ +VOID +KeyWriteDataRegister ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + IN UINT8 Data + ) +{ + // + // Use IsaIo protocol to perform IO operations + // + BiosKeyboardPrivate->IsaIo->Io.Write ( + BiosKeyboardPrivate->IsaIo, + EfiIsaIoWidthUint8, + BiosKeyboardPrivate->DataRegisterAddress, + 1, + &Data + ); +} + +/** + Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer-empty state. + + @param BiosKeyboardPrivate Keyboard instance pointer. + @param Data The pointer for data that being read out. + + @retval EFI_SUCCESS The data byte read out successfully. + @retval EFI_TIMEOUT Timeout occurred during reading out data byte. + +**/ +EFI_STATUS +KeyboardRead ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + OUT UINT8 *Data + ) +{ + UINT32 TimeOut; + UINT32 RegFilled; + + TimeOut = 0; + RegFilled = 0; + + // + // wait till output buffer full then perform the read + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) { + RegFilled = 1; + *Data = KeyReadDataRegister (BiosKeyboardPrivate); + break; + } + + gBS->Stall (30); + } + + if (RegFilled == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state. + + @param BiosKeyboardPrivate Keyboard instance pointer. + @param Data Data byte to write. + + @retval EFI_SUCCESS The data byte is written successfully. + @retval EFI_TIMEOUT Timeout occurred during writing. + +**/ +EFI_STATUS +KeyboardWrite ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + IN UINT8 Data + ) +{ + UINT32 TimeOut; + UINT32 RegEmptied; + + TimeOut = 0; + RegEmptied = 0; + + // + // wait for input buffer empty + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) { + RegEmptied = 1; + break; + } + + gBS->Stall (30); + } + + if (RegEmptied == 0) { + return EFI_TIMEOUT; + } + // + // Write it + // + KeyWriteDataRegister (BiosKeyboardPrivate, Data); + + return EFI_SUCCESS; +} + +/** + Write command byte to control register of Keyboard Controller with delay and waiting for buffer-empty state. + + @param BiosKeyboardPrivate Keyboard instance pointer. + @param Data Command byte to write. + + @retval EFI_SUCCESS The command byte is written successfully. + @retval EFI_TIMEOUT Timeout occurred during writing. + +**/ +EFI_STATUS +KeyboardCommand ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + IN UINT8 Data + ) +{ + UINT32 TimeOut; + UINT32 RegEmptied; + + TimeOut = 0; + RegEmptied = 0; + + // + // Wait For Input Buffer Empty + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) { + RegEmptied = 1; + break; + } + + gBS->Stall (30); + } + + if (RegEmptied == 0) { + return EFI_TIMEOUT; + } + // + // issue the command + // + KeyWriteCommandRegister (BiosKeyboardPrivate, Data); + + // + // Wait For Input Buffer Empty again + // + RegEmptied = 0; + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) { + RegEmptied = 1; + break; + } + + gBS->Stall (30); + } + + if (RegEmptied == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Wait for a specific value to be presented in + Data register of Keyboard Controller by keyboard and then read it, + used in keyboard commands ack + + @param BiosKeyboardPrivate Keyboard instance pointer. + @param Value The value to be waited for + @param WaitForValueTimeOut The limit of microseconds for timeout + + @retval EFI_SUCCESS The command byte is written successfully. + @retval EFI_TIMEOUT Timeout occurred during writing. + +**/ +EFI_STATUS +KeyboardWaitForValue ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + IN UINT8 Value, + IN UINTN WaitForValueTimeOut + ) +{ + UINT8 Data; + UINT32 TimeOut; + UINT32 SumTimeOut; + UINT32 GotIt; + + GotIt = 0; + TimeOut = 0; + SumTimeOut = 0; + + // + // Make sure the initial value of 'Data' is different from 'Value' + // + Data = 0; + if (Data == Value) { + Data = 1; + } + // + // Read from 8042 (multiple times if needed) + // until the expected value appears + // use SumTimeOut to control the iteration + // + while (1) { + // + // Perform a read + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) { + Data = KeyReadDataRegister (BiosKeyboardPrivate); + break; + } + + gBS->Stall (30); + } + + SumTimeOut += TimeOut; + + if (Data == Value) { + GotIt = 1; + break; + } + + if (SumTimeOut >= WaitForValueTimeOut) { + break; + } + } + // + // Check results + // + if (GotIt != 0) { + return EFI_SUCCESS; + } else { + return EFI_TIMEOUT; + } + +} + +/** + 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 BiosKeyboardPrivate Bioskeyboard driver private structure. + @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 +KeyboardReadKeyStrokeWorker ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + OUT EFI_KEY_DATA *KeyData + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Use TimerEvent callback funciton to check whether there's any key pressed + // + + // + // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event. + // Csm will be used to check whether there is a key pending, but the csm will disable all + // interrupt before switch to compatibility16, which mean all the efiCompatibility timer + // event will stop work during the compatibility16. And If a caller recursivly invoke this function, + // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period, + // e.g. usb keyboard driver. + // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked. + // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input. + // + gBS->Stall (1000); + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + BiosKeyboardTimerHandler (NULL, BiosKeyboardPrivate); + // + // If there's no key, just return + // + Status = CheckQueue (&BiosKeyboardPrivate->Queue); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + return EFI_NOT_READY; + } + + Status = Dequeue (&BiosKeyboardPrivate->Queue, KeyData); + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +// +// EFI Simple Text In Protocol Functions +// +/** + Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations. + + @param This Pointer of simple text Protocol. + @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip. + + @retval EFI_SUCCESS The command byte is written successfully. + @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + EFI_STATUS Status; + EFI_TPL OldTpl; + UINT8 CommandByte; + BOOLEAN MouseEnable; + EFI_INPUT_KEY Key; + + MouseEnable = FALSE; + BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This); + + // + // 1 + // Report reset progress code + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET + ); + + // + // Report a Progress Code for clearing the keyboard buffer + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER + ); + + // + // 2 + // Raise TPL to avoid mouse operation impact + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // + // Exhaust output buffer data + // + do { + Status = BiosKeyboardReadKeyStroke ( + This, + &Key + ); + } while (!EFI_ERROR (Status)); + // + // 3 + // check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H + // if not skip step 4&5 and jump to step 6 to selftest KBC and report this + // else go step 4 + // + if (!PcdGetBool (PcdFastPS2Detection)) { + if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) { + // + // 4 + // CheckMouseStatus to decide enable it later or not + // + // + // Read the command byte of KBC + // + Status = KeyboardCommand ( + BiosKeyboardPrivate, + KBC_CMDREG_VIA64_CMDBYTE_R + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardRead ( + BiosKeyboardPrivate, + &CommandByte + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + // + // Check mouse enabled or not before + // + if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) { + MouseEnable = FALSE; + } else { + MouseEnable = TRUE; + } + // + // 5 + // disable mouse (via KBC) and Keyborad device + // + Status = KeyboardCommand ( + BiosKeyboardPrivate, + KBC_CMDREG_VIA64_AUX_DISABLE + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardCommand ( + BiosKeyboardPrivate, + KBC_CMDREG_VIA64_KB_DISABLE + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + } else { + // + // 6 + // KBC Self Test + // + // + // Report a Progress Code for performing a self test on the keyboard controller + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST + ); + + Status = KeyboardCommand ( + BiosKeyboardPrivate, + KBC_CMDREG_VIA64_KBC_SLFTEST + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardWaitForValue ( + BiosKeyboardPrivate, + KBC_CMDECHO_KBCSLFTEST_OK, + KEYBOARD_WAITFORVALUE_TIMEOUT + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + } + } + // + // 7 + // Disable Mouse interface, enable Keyboard interface and declare selftest success + // + // Mouse device will block keyboard interface before it be configured, so we should disable mouse first. + // + Status = KeyboardCommand ( + BiosKeyboardPrivate, + KBC_CMDREG_VIA64_CMDBYTE_W + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + // + // Write 8042 Command Byte, set System Flag + // While at the same time: + // 1. disable mouse interface, + // 2. enable kbd interface, + // 3. enable PC/XT kbd translation mode + // 4. enable mouse and kbd interrupts + // + //Command Byte bits: + // 7: Reserved + // 6: PC/XT translation mode + // 5: Disable Auxiliary device interface + // 4: Disable keyboard interface + // 3: Reserved + // 2: System Flag + // 1: Enable Auxiliary device interrupt + // 0: Enable Keyboard interrupt + // + CommandByte = 0; + Status = KeyboardWrite ( + BiosKeyboardPrivate, + (UINT8) ((CommandByte & + (~KB_CMMBYTE_DISABLE_KB)) | + KB_CMMBYTE_KSCAN2UNI_COV | + KB_CMMBYTE_ENABLE_AUXINT | + KB_CMMBYTE_ENABLE_KBINT | + KB_CMMBYTE_SLFTEST_SUCC | + KB_CMMBYTE_DISABLE_AUX) + ); + + // + // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow, + // so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped. + // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected, + // Real reset will not do. + // + if (ExtendedVerification && CheckKeyboardConnect (BiosKeyboardPrivate)) { + // + // 8 + // Send keyboard reset command then read ACK + // + Status = KeyboardWrite ( + BiosKeyboardPrivate, + KBC_INPBUF_VIA60_KBRESET + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardWaitForValue ( + BiosKeyboardPrivate, + KBC_CMDECHO_ACK, + KEYBOARD_WAITFORVALUE_TIMEOUT + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + // + // 9 + // Wait for keyboard return test OK. + // + Status = KeyboardWaitForValue ( + BiosKeyboardPrivate, + KBC_CMDECHO_BATTEST_OK, + KEYBOARD_WAITFORVALUE_TIMEOUT + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + // + // 10 + // set keyboard scan code set = 02 (standard configuration) + // + Status = KeyboardWrite ( + BiosKeyboardPrivate, + KBC_INPBUF_VIA60_KBSCODE + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardWaitForValue ( + BiosKeyboardPrivate, + KBC_CMDECHO_ACK, + KEYBOARD_WAITFORVALUE_TIMEOUT + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardWrite ( + BiosKeyboardPrivate, + KBC_INPBUF_VIA60_SCODESET2 + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardWaitForValue ( + BiosKeyboardPrivate, + KBC_CMDECHO_ACK, + KEYBOARD_WAITFORVALUE_TIMEOUT + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + // + // 11 + // enable keyboard itself (not via KBC) by writing CMD F4 via 60H + // + Status = KeyboardWrite ( + BiosKeyboardPrivate, + KBC_INPBUF_VIA60_KBEN + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardWaitForValue ( + BiosKeyboardPrivate, + KBC_CMDECHO_ACK, + KEYBOARD_WAITFORVALUE_TIMEOUT + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + // + // 12 + // Additional validation, do it as follow: + // 1). check for status register of PARE && TIM via 64H + // 2). perform KB checking by writing ABh via 64H + // + if ((KeyReadStatusRegister (BiosKeyboardPrivate) & (KBC_STSREG_VIA64_PARE | KBC_STSREG_VIA64_TIM)) != 0) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardCommand ( + BiosKeyboardPrivate, + KBC_CMDREG_VIA64_KB_CKECK + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + Status = KeyboardWaitForValue ( + BiosKeyboardPrivate, + KBC_CMDECHO_KBCHECK_OK, + KEYBOARD_WAITFORVALUE_TIMEOUT + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + } + // + // 13 + // Done for validating keyboard. Enable keyboard (via KBC) + // and recover the command byte to proper value + // + if (!PcdGetBool (PcdFastPS2Detection)) { + Status = KeyboardCommand ( + BiosKeyboardPrivate, + KBC_CMDREG_VIA64_KB_ENABLE + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + } + + // + // 14 + // conditionally enable mouse (via KBC) + // + if (MouseEnable) { + Status = KeyboardCommand ( + BiosKeyboardPrivate, + KBC_CMDREG_VIA64_AUX_ENABLE + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + + } + } + +Exit: + // + // 15 + // resume priority of task level + // + gBS->RestoreTPL (OldTpl); + + return Status; + +} + +/** + Read out the scan code of the key that has just been stroked. + + @param This Pointer of simple text Protocol. + @param Key Pointer for store the key that read out. + + @retval EFI_SUCCESS The key is read out successfully. + @retval other The key reading failed. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +{ + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + EFI_STATUS Status; + EFI_KEY_DATA KeyData; + + BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This); + + Status = KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, &KeyData); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Convert the Ctrl+[a-z] to Ctrl+[1-26] + // + if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { + if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); + } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); + } + } + + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + + return EFI_SUCCESS; +} + +/** + Waiting on the keyboard event, if there's any key pressed by the user, signal the event + + @param Event The event that be siganlled when any key has been stroked. + @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL. + +**/ +VOID +EFIAPI +BiosKeyboardWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event. + // Csm will be used to check whether there is a key pending, but the csm will disable all + // interrupt before switch to compatibility16, which mean all the efiCompatibility timer + // event will stop work during the compatibility16. And If a caller recursivly invoke this function, + // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period, + // e.g. usb keyboard driver. + // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked. + // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input. + // + gBS->Stall (1000); + // + // Use TimerEvent callback funciton to check whether there's any key pressed + // + BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context)); + + if (!EFI_ERROR (BiosKeyboardCheckForKey (Context))) { + gBS->SignalEvent (Event); + } +} + +/** + Check key buffer to get the key stroke status. + + @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL. + + @retval EFI_SUCCESS A key is being pressed now. + @retval Other No key is now pressed. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardCheckForKey ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This + ) +{ + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + + BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This); + + return CheckQueue (&BiosKeyboardPrivate->Queue); +} +// +// Private worker functions +// +#define TABLE_END 0x0 + +typedef struct _CONVERT_TABLE_ENTRY { + UINT16 ScanCode; + UINT16 EfiScanCode; +} CONVERT_TABLE_ENTRY; + +CONVERT_TABLE_ENTRY mConvertTable[] = { + { + 0x47, + SCAN_HOME + }, + { + 0x48, + SCAN_UP + }, + { + 0x49, + SCAN_PAGE_UP + }, + { + 0x4b, + SCAN_LEFT + }, + { + 0x4d, + SCAN_RIGHT + }, + { + 0x4f, + SCAN_END + }, + { + 0x50, + SCAN_DOWN + }, + { + 0x51, + SCAN_PAGE_DOWN + }, + { + 0x52, + SCAN_INSERT + }, + { + 0x53, + SCAN_DELETE + }, + // + // Function Keys are only valid if KeyChar == 0x00 + // This function does not require KeyChar to be 0x00 + // + { + 0x3b, + SCAN_F1 + }, + { + 0x3c, + SCAN_F2 + }, + { + 0x3d, + SCAN_F3 + }, + { + 0x3e, + SCAN_F4 + }, + { + 0x3f, + SCAN_F5 + }, + { + 0x40, + SCAN_F6 + }, + { + 0x41, + SCAN_F7 + }, + { + 0x42, + SCAN_F8 + }, + { + 0x43, + SCAN_F9 + }, + { + 0x44, + SCAN_F10 + }, + { + 0x85, + SCAN_F11 + }, + { + 0x86, + SCAN_F12 + }, + // + // Convert ALT + Fn keys + // + { + 0x68, + SCAN_F1 + }, + { + 0x69, + SCAN_F2 + }, + { + 0x6a, + SCAN_F3 + }, + { + 0x6b, + SCAN_F4 + }, + { + 0x6c, + SCAN_F5 + }, + { + 0x6d, + SCAN_F6 + }, + { + 0x6e, + SCAN_F7 + }, + { + 0x6f, + SCAN_F8 + }, + { + 0x70, + SCAN_F9 + }, + { + 0x71, + SCAN_F10 + }, + { + TABLE_END, + SCAN_NULL + }, +}; + +/** + Convert unicode combined with scan code of key to the counterpart of EFIScancode of it. + + @param KeyChar Unicode of key. + @param ScanCode Scan code of key. + + @return The value of EFI Scancode for the key. + @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key. + +**/ +UINT16 +ConvertToEFIScanCode ( + IN CHAR16 KeyChar, + IN UINT16 ScanCode + ) +{ + UINT16 EfiScanCode; + UINT16 Index; + + if (KeyChar == CHAR_ESC) { + EfiScanCode = SCAN_ESC; + } else if (KeyChar == 0x00 || KeyChar == 0xe0) { + // + // Movement & Function Keys + // + for (Index = 0; (Index < sizeof (mConvertTable) / sizeof (CONVERT_TABLE_ENTRY)) && (mConvertTable[Index].ScanCode != TABLE_END); Index += 1) { + if (ScanCode == mConvertTable[Index].ScanCode) { + return mConvertTable[Index].EfiScanCode; + } + } + // + // Reach Table end, return default value + // + return SCAN_NULL; + } else { + return SCAN_NULL; + } + + return EfiScanCode; +} + +/** + Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command + If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device + should not be in system. + + @param BiosKeyboardPrivate Keyboard Private Data Struture + + @retval TRUE Keyboard in System. + @retval FALSE Keyboard not in System. + +**/ +BOOLEAN +CheckKeyboardConnect ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + // + // enable keyboard itself and wait for its ack + // If can't receive ack, Keyboard should not be connected. + // + if (!PcdGetBool (PcdFastPS2Detection)) { + Status = KeyboardWrite ( + BiosKeyboardPrivate, + KBC_INPBUF_VIA60_KBEN + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n")); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR + ); + return FALSE; + } + + Status = KeyboardWaitForValue ( + BiosKeyboardPrivate, + KBC_CMDECHO_ACK, + KEYBOARD_WAITFORVALUE_TIMEOUT + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Timeout!\n")); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR + ); + return FALSE; + } + return TRUE; + } else { + return TRUE; + } +} + +/** + Timer event handler: read a series of key stroke from 8042 + and put them into memory key buffer. + It is registered as running under TPL_NOTIFY + + @param Event The timer event + @param Context A BIOS_KEYBOARD_DEV pointer + +**/ +VOID +EFIAPI +BiosKeyboardTimerHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_TPL OldTpl; + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + EFI_IA32_REGISTER_SET Regs; + UINT8 KbFlag1; // 0040h:0017h - KEYBOARD - STATUS FLAGS 1 + UINT8 KbFlag2; // 0040h:0018h - KEYBOARD - STATUS FLAGS 2 + EFI_KEY_DATA KeyData; + LIST_ENTRY *Link; + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + + BiosKeyboardPrivate = Context; + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // if there is no key present, just return + // + if (BiosKeyboardPrivate->ExtendedKeyboard) { + Regs.H.AH = 0x11; + } else { + Regs.H.AH = 0x01; + } + + BiosKeyboardPrivate->LegacyBios->Int86 ( + BiosKeyboardPrivate->LegacyBios, + 0x16, + &Regs + ); + if (Regs.X.Flags.ZF != 0) { + gBS->RestoreTPL (OldTpl); + return; + } + + // + // Read the key + // + if (BiosKeyboardPrivate->ExtendedKeyboard) { + Regs.H.AH = 0x10; + } else { + Regs.H.AH = 0x00; + } + + BiosKeyboardPrivate->LegacyBios->Int86 ( + BiosKeyboardPrivate->LegacyBios, + 0x16, + &Regs + ); + + KeyData.Key.ScanCode = (UINT16) Regs.H.AH; + KeyData.Key.UnicodeChar = (UINT16) Regs.H.AL; + DEBUG (( + EFI_D_INFO, + "[KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n", + KeyData.Key.ScanCode, + KeyData.Key.UnicodeChar + )); + + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; + KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; + // + // Leagcy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB buffer in BDA (BIOS DATE AREA), then + // Int 16 depend KB buffer and some key bits in BDA to translate the scancode to ASCII code, and return both the scancode and ASCII + // code to Int 16 caller. This translation process works well if the Int 9 could response user input in time. But in Tiano enviorment, the Int 9 + // will be disabled after the thunk call finish, which means if user crazy input during int 9 being disabled, some keystrokes will be lost when + // KB device own hardware buffer overflows. And if the lost keystroke code is CTRL or ALT or SHIFT release code, these function key flags bit + // in BDA will not be updated. So the Int 16 will believe the CTRL or ALT or SHIFT is still pressed, and Int 16 will translate later scancode + // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other dirvers + // performance, like USB. + // + // 1. If CTRL or ALT release code is missed, all later input keys will be translated to wrong ASCII codes which the Tiano cannot support. In + // this case, the KB input seems fail to work, and user input is blocked. To solve the problem, we can help to clear the CTRL or ALT flag in BDA + // after every Int 16 finish. Thus persist to press CTRL or ALT has same effection as only press one time. It is Ok, since user not often use the + // CTRL and ALT. + // + // 2. If SHIFT release code is missed, all later lowercase input will become capital. This is ugly, but not block user input. If user press the lost + // SHIFT again, the lowercase will come back to normal. Since user often use the SHIFT, it is not reasonable to help to clear the SHIFT flag in BDA, + // which will let persist to press SHIFT has same effection as only press one time. + // + //0040h:0017h - KEYBOARD - STATUS FLAGS 1 + // 7 INSert active + // 6 Caps Lock active + // 5 Num Lock active + // 4 Scroll Lock active + // 3 either Alt pressed + // 2 either Ctrl pressed + // 1 Left Shift pressed + // 0 Right Shift pressed + + + // + // Clear the CTRL and ALT BDA flag + // + KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1 + KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2 + + DEBUG_CODE ( + { + if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) { + DEBUG ((EFI_D_INFO, "[KBD]Caps Lock Key is pressed.\n")); + } + if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) { + DEBUG ((EFI_D_INFO, "[KBD]Num Lock Key is pressed.\n")); + } + if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) { + DEBUG ((EFI_D_INFO, "[KBD]Scroll Lock Key is pressed.\n")); + } + if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) { + if ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) { + DEBUG ((EFI_D_INFO, "[KBD]Left Alt Key is pressed.\n")); + } else { + DEBUG ((EFI_D_INFO, "[KBD]Right Alt Key is pressed.\n")); + } + } + if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) { + if ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) { + DEBUG ((EFI_D_INFO, "[KBD]Left Ctrl Key is pressed.\n")); + } else { + DEBUG ((EFI_D_INFO, "[KBD]Right Ctrl Key is pressed.\n")); + } + } + if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) { + DEBUG ((EFI_D_INFO, "[KBD]Left Shift Key is pressed.\n")); + } + if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) { + DEBUG ((EFI_D_INFO, "[KBD]Right Shift Key is pressed.\n")); + } + } + ); + + // + // Record toggle state + // + if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) { + KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE; + } + if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) { + KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE; + } + if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) { + KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE; + } + // + // Record shift state + // BUGBUG: Need add Menu key and Left/Right Logo key state in the future + // + if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) { + KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) ? EFI_LEFT_ALT_PRESSED : EFI_RIGHT_ALT_PRESSED; + } + if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) { + KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) ? EFI_LEFT_CONTROL_PRESSED : EFI_RIGHT_CONTROL_PRESSED; + } + if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) { + KeyData.KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED; + } + if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) { + KeyData.KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED; + } + + // + // Clear left alt and left ctrl BDA flag + // + KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED); + *((UINT8 *) (UINTN) 0x418) = KbFlag2; + KbFlag1 &= ~0x0C; + *((UINT8 *) (UINTN) 0x417) = KbFlag1; + + + // + // Output EFI input key and shift/toggle state + // + if (KeyData.Key.UnicodeChar == CHAR_NULL || KeyData.Key.UnicodeChar == CHAR_SCANCODE || KeyData.Key.UnicodeChar == CHAR_ESC) { + KeyData.Key.ScanCode = ConvertToEFIScanCode (KeyData.Key.UnicodeChar, KeyData.Key.ScanCode); + KeyData.Key.UnicodeChar = CHAR_NULL; + } else { + KeyData.Key.ScanCode = SCAN_NULL; + } + + // + // CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back. + // + if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { + if (KeyData.Key.UnicodeChar >= 1 && KeyData.Key.UnicodeChar <= 26) { + if (((KeyData.KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) == + ((KeyData.KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0) + ) { + KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'a' - 1); + } else { + KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'A' - 1); + } + } + } + + DEBUG (( + EFI_D_INFO, + "[KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n", + KeyData.Key.ScanCode, + KeyData.Key.UnicodeChar + )); + + // + // Need not return associated shift state if a class of printable characters that + // are normally adjusted by shift modifiers. + // e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'. + // + if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') || + (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') + ) { + DEBUG ((EFI_D_INFO, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n")); + KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED); + } + + // + // Invoke notification functions if exist + // + for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { + CurrentNotify->KeyNotificationFn (&KeyData); + } + } + + Enqueue (&BiosKeyboardPrivate->Queue, &KeyData); + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return ; +} + +/** + Free keyboard notify list. + + @param ListHead The list head + + @retval EFI_SUCCESS Free the notify list successfully + @retval EFI_INVALID_PARAMETER ListHead is invalid. + +**/ +EFI_STATUS +BiosKeyboardFreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ) +{ + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode; + + if (ListHead == NULL) { + return EFI_INVALID_PARAMETER; + } + while (!IsListEmpty (ListHead)) { + NotifyNode = CR ( + ListHead->ForwardLink, + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + RemoveEntryList (ListHead->ForwardLink); + gBS->FreePool (NotifyNode); + } + + return EFI_SUCCESS; +} + +/** + Check if key is registered. + + @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; + +} + +/** + Waiting on the keyboard event, if there's any key pressed by the user, signal the event + + @param Event The event that be siganlled when any key has been stroked. + @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. + +**/ +VOID +EFIAPI +BiosKeyboardWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + + BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (Context); + BiosKeyboardWaitForKey (Event, &BiosKeyboardPrivate->SimpleTextIn); + +} + +/** + 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 +BiosKeyboardResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + EFI_STATUS Status; + EFI_TPL OldTpl; + + BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); + + Status = BiosKeyboardPrivate->SimpleTextIn.Reset ( + &BiosKeyboardPrivate->SimpleTextIn, + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; + +} + +/** + 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 +BiosKeyboardReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ) +{ + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); + + return KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, 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 +BiosKeyboardSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ) +{ + EFI_STATUS Status; + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + EFI_TPL OldTpl; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT8 Command; + + if (KeyToggleState == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Thunk keyboard driver doesn't support partial keystroke. + // + if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID || + (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED + ) { + return EFI_UNSUPPORTED; + } + + BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID **) &LegacyBios + ); + + ASSERT_EFI_ERROR (Status); + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Command = 0; + if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { + Command |= 4; + } + if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) { + Command |= 2; + } + if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { + Command |= 1; + } + + Status = KeyboardWrite (BiosKeyboardPrivate, 0xed); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + Status = KeyboardWrite (BiosKeyboardPrivate, Command); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + // + // Call Legacy BIOS Protocol to set whatever is necessary + // + LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command); + + Status = EFI_SUCCESS; + +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; + +} + +/** + 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 NotifyHandle is NULL. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ) +{ + EFI_STATUS Status; + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + EFI_TPL OldTpl; + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify; + LIST_ENTRY *Link; + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + + if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. + // + for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify; + Status = EFI_SUCCESS; + goto Exit; + } + } + } + + // + // Allocate resource to save the notification function + // + + NewNotify = (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY)); + if (NewNotify == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + NewNotify->Signature = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); + InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry); + + *NotifyHandle = NewNotify; + Status = EFI_SUCCESS; + +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + 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 +BiosKeyboardUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ) +{ + EFI_STATUS Status; + BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; + EFI_TPL OldTpl; + LIST_ENTRY *Link; + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + + // + // Check incoming notification handle + // + if (NotificationHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (((BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (CurrentNotify == NotificationHandle) { + // + // Remove the notification function from NotifyList and free resources + // + RemoveEntryList (&CurrentNotify->NotifyEntry); + + Status = EFI_SUCCESS; + goto Exit; + } + } + + // + // Can not find the specified Notification Handle + // + Status = EFI_INVALID_PARAMETER; + +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + The user Entry Point for module BiosKeyboard. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeBiosKeyboard( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gBiosKeyboardDriverBinding, + ImageHandle, + &gBiosKeyboardComponentName, + &gBiosKeyboardComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h new file mode 100644 index 0000000000..a27d2e1b23 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h @@ -0,0 +1,743 @@ +/** @file + +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 _BIOS_KEYBOARD_H_ +#define _BIOS_KEYBOARD_H_ + + +#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 gBiosKeyboardDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2; + + +#include + +// +// BISO Keyboard Defines +// +#define CHAR_SCANCODE 0xe0 +#define CHAR_ESC 0x1b + +#define KEYBOARD_8042_DATA_REGISTER 0x60 +#define KEYBOARD_8042_STATUS_REGISTER 0x64 +#define KEYBOARD_8042_COMMAND_REGISTER 0x64 + +#define KEYBOARD_TIMEOUT 65536 // 0.07s +#define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s +#define KEYBOARD_BAT_TIMEOUT 4000000 // 4s +#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s +// KEYBOARD COMMAND BYTE -- read by writing command KBC_CMDREG_VIA64_CMDBYTE_R to 64H, then read from 60H +// write by wrting command KBC_CMDREG_VIA64_CMDBYTE_W to 64H, then write to 60H +// 7: Reserved +// 6: PC/XT translation mode convert +// 5: Disable Auxiliary device interface +// 4: Disable keyboard interface +// 3: Reserved +// 2: System Flag: selftest successful +// 1: Enable Auxiliary device interrupt +// 0: Enable Keyboard interrupt ) +// +#define KB_CMMBYTE_KSCAN2UNI_COV (0x1 << 6) +#define KB_CMMBYTE_DISABLE_AUX (0x1 << 5) +#define KB_CMMBYTE_DISABLE_KB (0x1 << 4) +#define KB_CMMBYTE_SLFTEST_SUCC (0x1 << 2) +#define KB_CMMBYTE_ENABLE_AUXINT (0x1 << 1) +#define KB_CMMBYTE_ENABLE_KBINT (0x1 << 0) + +// +// KEYBOARD CONTROLLER STATUS REGISTER - read from 64h +// 7: Parity error +// 6: General time out +// 5: Output buffer holds data for AUX +// 4: Keyboard is not locked +// 3: Command written via 64h / Data written via 60h +// 2: KBC self-test successful / Power-on reset +// 1: Input buffer holds CPU data / empty +// 0: Output buffer holds keyboard data / empty +// +#define KBC_STSREG_VIA64_PARE (0x1 << 7) +#define KBC_STSREG_VIA64_TIM (0x1 << 6) +#define KBC_STSREG_VIA64_AUXB (0x1 << 5) +#define KBC_STSREG_VIA64_KEYL (0x1 << 4) +#define KBC_STSREG_VIA64_C_D (0x1 << 3) +#define KBC_STSREG_VIA64_SYSF (0x1 << 2) +#define KBC_STSREG_VIA64_INPB (0x1 << 1) +#define KBC_STSREG_VIA64_OUTB (0x1 << 0) + +// +// COMMANDs of KEYBOARD CONTROLLER COMMAND REGISTER - write to 64h +// +#define KBC_CMDREG_VIA64_CMDBYTE_R 0x20 +#define KBC_CMDREG_VIA64_CMDBYTE_W 0x60 +#define KBC_CMDREG_VIA64_AUX_DISABLE 0xA7 +#define KBC_CMDREG_VIA64_AUX_ENABLE 0xA8 +#define KBC_CMDREG_VIA64_KBC_SLFTEST 0xAA +#define KBC_CMDREG_VIA64_KB_CKECK 0xAB +#define KBC_CMDREG_VIA64_KB_DISABLE 0xAD +#define KBC_CMDREG_VIA64_KB_ENABLE 0xAE +#define KBC_CMDREG_VIA64_INTP_LOW_R 0xC0 +#define KBC_CMDREG_VIA64_INTP_HIGH_R 0xC2 +#define KBC_CMDREG_VIA64_OUTP_R 0xD0 +#define KBC_CMDREG_VIA64_OUTP_W 0xD1 +#define KBC_CMDREG_VIA64_OUTB_KB_W 0xD2 +#define KBC_CMDREG_VIA64_OUTB_AUX_W 0xD3 +#define KBC_CMDREG_VIA64_AUX_W 0xD4 + +// +// echos of KEYBOARD CONTROLLER COMMAND - read from 60h +// +#define KBC_CMDECHO_KBCSLFTEST_OK 0x55 +#define KBC_CMDECHO_KBCHECK_OK 0x00 +#define KBC_CMDECHO_ACK 0xFA +#define KBC_CMDECHO_BATTEST_OK 0xAA +#define KBC_CMDECHO_BATTEST_FAILE 0xFC + +// +// OUTPUT PORT COMMANDs - write port by writing KBC_CMDREG_VIA64_OUTP_W via 64H, then write the command to 60H +// drive data and clock of KB to high for at least 500us for BAT needs +// +#define KBC_OUTPORT_DCHIGH_BAT 0xC0 +// +// scan code set type +// +#define KBC_INPBUF_VIA60_SCODESET1 0x01 +#define KBC_INPBUF_VIA60_SCODESET2 0x02 +#define KBC_INPBUF_VIA60_SCODESET3 0x03 + +// +// COMMANDs written to INPUT BUFFER - write to 60h +// +#define KBC_INPBUF_VIA60_KBECHO 0xEE +#define KBC_INPBUF_VIA60_KBSCODE 0xF0 +#define KBC_INPBUF_VIA60_KBTYPE 0xF2 +#define KBC_INPBUF_VIA60_KBDELAY 0xF3 +#define KBC_INPBUF_VIA60_KBEN 0xF4 +#define KBC_INPBUF_VIA60_KBSTDDIS 0xF5 +#define KBC_INPBUF_VIA60_KBSTDEN 0xF6 +#define KBC_INPBUF_VIA60_KBRESEND 0xFE +#define KBC_INPBUF_VIA60_KBRESET 0xFF + +// +// 0040h:0017h - KEYBOARD - STATUS FLAGS 1 +// 7 INSert active +// 6 Caps Lock active +// 5 Num Lock active +// 4 Scroll Lock active +// 3 either Alt pressed +// 2 either Ctrl pressed +// 1 Left Shift pressed +// 0 Right Shift pressed +// +// 0040h:0018h - KEYBOARD - STATUS FLAGS 2 +// 7: insert key is depressed +// 6: caps-lock key is depressed (does not work well) +// 5: num-lock key is depressed (does not work well) +// 4: scroll lock key is depressed (does not work well) +// 3: suspend key has been toggled (does not work well) +// 2: system key is pressed and held (does not work well) +// 1: left ALT key is pressed +// 0: left CTRL key is pressed +// +#define KB_INSERT_BIT (0x1 << 7) +#define KB_CAPS_LOCK_BIT (0x1 << 6) +#define KB_NUM_LOCK_BIT (0x1 << 5) +#define KB_SCROLL_LOCK_BIT (0x1 << 4) +#define KB_ALT_PRESSED (0x1 << 3) +#define KB_CTRL_PRESSED (0x1 << 2) +#define KB_LEFT_SHIFT_PRESSED (0x1 << 1) +#define KB_RIGHT_SHIFT_PRESSED (0x1 << 0) + +#define KB_SUSPEND_PRESSED (0x1 << 3) +#define KB_SYSREQ_PRESSED (0x1 << 2) +#define KB_LEFT_ALT_PRESSED (0x1 << 1) +#define KB_LEFT_CTRL_PRESSED (0x1 << 0) + +// +// BIOS Keyboard Device Structure +// +#define BIOS_KEYBOARD_DEV_SIGNATURE SIGNATURE_32 ('B', 'K', 'B', 'D') +#define BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('c', 'b', 'k', 'h') + +typedef struct _BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY { + UINTN Signature; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + LIST_ENTRY NotifyEntry; +} BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY; + +#define QUEUE_MAX_COUNT 32 +typedef struct { + UINTN Front; + UINTN Rear; + EFI_KEY_DATA Buffer[QUEUE_MAX_COUNT]; +} SIMPLE_QUEUE; + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_ISA_IO_PROTOCOL *IsaIo; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInputEx; + UINT16 DataRegisterAddress; + UINT16 StatusRegisterAddress; + UINT16 CommandRegisterAddress; + BOOLEAN ExtendedKeyboard; + + // + // Buffer storing EFI_KEY_DATA + // + SIMPLE_QUEUE Queue; + + // + // Notification Function List + // + LIST_ENTRY NotifyList; + EFI_EVENT TimerEvent; + +} BIOS_KEYBOARD_DEV; + +#define BIOS_KEYBOARD_DEV_FROM_THIS(a) CR (a, BIOS_KEYBOARD_DEV, SimpleTextIn, BIOS_KEYBOARD_DEV_SIGNATURE) +#define TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS(a) \ + CR (a, \ + BIOS_KEYBOARD_DEV, \ + SimpleTextInputEx, \ + BIOS_KEYBOARD_DEV_SIGNATURE \ + ) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding; + +// +// Driver Binding Protocol functions +// + +/** + Check whether the driver supports this device. + + @param This The Udriver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The driver supports this controller. + @retval other This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Starts the device with this driver. + + @param This The driver binding instance. + @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 The controller is controlled by the driver. + @retval Other This controller cannot be started. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop the device handled by this driver. + + @param This The driver binding protocol. + @param Controller The controller to release. + @param NumberOfChildren The number of handles in ChildHandleBuffer. + @param ChildHandleBuffer The array of child handle. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + @retval Others Fail to uninstall protocols attached on the device. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + 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 +BiosKeyboardComponentNameGetDriverName ( + 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 +BiosKeyboardComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// Simple Text Input Protocol functions +// +/** + Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations. + + @param This Pointer of simple text Protocol. + @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip. + + @retval EFI_SUCCESS The command byte is written successfully. + @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Read out the scan code of the key that has just been stroked. + + @param This Pointer of simple text Protocol. + @param Key Pointer for store the key that read out. + + @retval EFI_SUCCESS The key is read out successfully. + @retval other The key reading failed. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +// +// Private worker functions +// +/** + Waiting on the keyboard event, if there's any key pressed by the user, signal the event + + @param Event The event that be siganlled when any key has been stroked. + @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL. + +**/ +VOID +EFIAPI +BiosKeyboardWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Check key buffer to get the key stroke status. + + @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL. + + @retval EFI_SUCCESS A key is being pressed now. + @retval Other No key is now pressed. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardCheckForKey ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This + ); + +/** + Convert unicode combined with scan code of key to the counterpart of EFIScancode of it. + + @param KeyChar Unicode of key. + @param ScanCode Scan code of key. + + @return The value of EFI Scancode for the key. + @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key. + +**/ +UINT16 +ConvertToEFIScanCode ( + IN CHAR16 KeyChar, + IN UINT16 ScanCode + ); + +/** + Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command + If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device + should not be in system. + + @param BiosKeyboardPrivate Keyboard Private Data Struture + + @retval TRUE Keyboard in System. + @retval FALSE Keyboard not in System. + +**/ +BOOLEAN +CheckKeyboardConnect ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate + ); + +/** + Timer event handler: read a series of key stroke from 8042 + and put them into memory key buffer. + It is registered as running under TPL_NOTIFY + + @param Event The timer event + @param Context A BIOS_KEYBOARD_DEV pointer + +**/ +VOID +EFIAPI +BiosKeyboardTimerHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + 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 +BiosKeyboardResetEx ( + 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 +BiosKeyboardReadKeyStrokeEx ( + 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 +BiosKeyboardSetState ( + 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 NotifyHandle is NULL. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardRegisterKeyNotify ( + 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. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ); + +/** + Wait for a specific value to be presented in + Data register of Keyboard Controller by keyboard and then read it, + used in keyboard commands ack + + @param BiosKeyboardPrivate Keyboard instance pointer. + @param Value The value to be waited for + @param WaitForValueTimeOut The limit of microseconds for timeout + + @retval EFI_SUCCESS The command byte is written successfully. + @retval EFI_TIMEOUT Timeout occurred during writing. + +**/ +EFI_STATUS +KeyboardWaitForValue ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + IN UINT8 Value, + IN UINTN WaitForValueTimeOut + ); + +/** + Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state. + + @param BiosKeyboardPrivate Keyboard instance pointer. + @param Data Data byte to write. + + @retval EFI_SUCCESS The data byte is written successfully. + @retval EFI_TIMEOUT Timeout occurred during writing. + +**/ +EFI_STATUS +KeyboardWrite ( + IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, + IN UINT8 Data + ); + +/** + Free keyboard notify list. + + @param ListHead The list head + + @retval EFI_SUCCESS Free the notify list successfully + @retval EFI_INVALID_PARAMETER ListHead is invalid. + +**/ +EFI_STATUS +BiosKeyboardFreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ); + +/** + Check if key is registered. + + @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 + ); + +/** + Waiting on the keyboard event, if there's any key pressed by the user, signal the event + + @param Event The event that be siganlled when any key has been stroked. + @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. + +**/ +VOID +EFIAPI +BiosKeyboardWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c new file mode 100644 index 0000000000..45fa7a21f8 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c @@ -0,0 +1,183 @@ +/** @file + +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 "BiosKeyboard.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName = { + BiosKeyboardComponentNameGetDriverName, + BiosKeyboardComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosKeyboardComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosKeyboardComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosKeyboardDriverNameTable[] = { + { + "eng;en", + L"BIOS[INT16] Keyboard Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mBiosKeyboardDriverNameTable, + DriverName, + (BOOLEAN)(This == &gBiosKeyboardComponentName) + ); +} + +/** + 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 +BiosKeyboardComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h new file mode 100644 index 0000000000..0218ef865c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h @@ -0,0 +1,153 @@ +/** @file + +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 _BIOS_KEYBOARD_COMPONENT_NAME_H_ +#define _BIOS_KEYBOARD_COMPONENT_NAME_H_ + + +extern EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2; + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosKeyboardComponentNameGetDriverName ( + 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 +BiosKeyboardComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf new file mode 100644 index 0000000000..a453480aa9 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf @@ -0,0 +1,77 @@ +## @file +# Ps2 Keyboard driver. +# +# Ps2 Keyboard driver by using Legacy Bios protocol service and IsaIo protocol +# service. This dirver uses legacy INT16 to get the key stroke status. +# +# 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 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 = KeyboardDxe + MODULE_UNI_FILE = KeyboardDxe.uni + FILE_GUID = 5479662B-6AE4-49e8-A6BD-6DE4B625811F + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeBiosKeyboard + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gBiosKeyboardDriverBinding +# COMPONENT_NAME = gBiosKeyboardComponentName +# + +[Sources] + ComponentName.c + ComponentName.h + BiosKeyboard.c + BiosKeyboard.h + + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +[LibraryClasses] + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + ReportStatusCodeLib + BaseMemoryLib + UefiLib + DebugLib + BaseLib + PcdLib + +[Protocols] + gEfiIsaIoProtocolGuid ## TO_START + gEfiSimpleTextInProtocolGuid ## BY_START + gEfiSimpleTextInputExProtocolGuid ## BY_START + gEfiLegacyBiosProtocolGuid ## CONSUMES + gEfiPs2PolicyProtocolGuid ## SOMETIMES_CONSUMES + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|FALSE ## CONSUMES + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection ## SOMETIMES_CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + KeyboardDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni new file mode 100644 index 0000000000..f86542d37f Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni new file mode 100644 index 0000000000..38f08d5138 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c new file mode 100644 index 0000000000..7af2dedd5d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c @@ -0,0 +1,3522 @@ +/** @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 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 "BiosSnp16.h" + + +/// +/// EFI Driver Binding Protocol Instance +/// +EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = { + BiosSnp16DriverBindingSupported, + BiosSnp16DriverBindingStart, + BiosSnp16DriverBindingStop, + 0x3, + NULL, + NULL +}; + +/// +/// This boolean is used to determine if we should release the cached vector during an error condition. +/// +BOOLEAN mCachedInt1A = FALSE; + +// +// Private worker functions; +// + +/** + Start the UNDI interface. + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + @param Ax PCI address of Undi device. + + @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. + @retval Others Status of start 16 bit UNDI ROM. +**/ +EFI_STATUS +Undi16SimpleNetworkStartUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + UINT16 Ax + ); + +/** + Start the UNDI interface + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + + @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. + @retval Others Status of start 16 bit UNDI ROM. +**/ +EFI_STATUS +Undi16SimpleNetworkStopUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice + ); + +/** + Stop the UNDI interface + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + + @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM. + @retval Others Status of stop 16 bit UNDI ROM. +**/ +EFI_STATUS +Undi16SimpleNetworkCleanupUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice + ); + +/** + Get runtime information for Undi network interface + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_SUCCESS Sucess operation. + @retval Others Fail to get runtime information for Undi network interface. +**/ +EFI_STATUS +Undi16SimpleNetworkGetInformation ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ); + +/** + Get NIC type + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_SUCCESS Sucess operation. + @retval Others Fail to get NIC type. +**/ +EFI_STATUS +Undi16SimpleNetworkGetNicType ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ); + +/** + Get NDIS information + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_SUCCESS Sucess operation. + @retval Others Fail to get NDIS information. +**/ +EFI_STATUS +Undi16SimpleNetworkGetNdisInfo ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ); + +/** + Signal handlers for ExitBootServices event. + + Clean up any Real-mode UNDI residue from the system + + @param Event ExitBootServices event + @param Context +**/ +VOID +EFIAPI +Undi16SimpleNetworkEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Loads the undi driver. + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + + @retval EFI_SUCCESS - Successfully loads undi driver. + @retval EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure. +**/ +EFI_STATUS +Undi16SimpleNetworkLoadUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice + ); + +/** + Unload 16 bit UNDI Option ROM from memory + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + + @return EFI_STATUS +**/ +EFI_STATUS +Undi16SimpleNetworkUnloadUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice + ); + +/** + Entry point for EFI drivers. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @return EFI_STATUS Return status from EfiLibInstallAllDriverProtocols. +**/ +EFI_STATUS +EFIAPI +BiosSnp16DriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gBiosSnp16DriverBinding, + ImageHandle, + &gBiosSnp16ComponentName, + &gBiosSnp16ComponentName2 + ); +} + +// +// EFI Driver Binding Protocol Functions +// +/** + Tests to see if this driver supports a given controller. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The driver supports given controller. + @retval EFI_UNSUPPORT The driver doesn't support given controller. + @retval Other Other errors prevent driver finishing to test + if the driver supports given controller. +**/ +EFI_STATUS +EFIAPI +BiosSnp16DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // See if this is a PCI Network Controller by looking at the Command register and + // Class Code Register + // + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = EFI_UNSUPPORTED; + if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) { + Status = EFI_SUCCESS; + } + +Done: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Starts the Snp device controller + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS - The device was started. + @retval EFI_DEVICE_ERROR - The device could not be started due to a device error. + @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +BiosSnp16DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + EFI_DEV_PATH Node; + UINTN Index; + UINTN Index2; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + UINTN Flags; + UINT64 Supports; + + SimpleNetworkDevice = NULL; + PciIo = NULL; + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } + + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Check to see if there is a legacy option ROM image associated with this PCI device + // + Status = LegacyBios->CheckPciRom ( + LegacyBios, + Controller, + NULL, + NULL, + &Flags + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Post the legacy option ROM if it is available. + // + Status = LegacyBios->InstallPciRom ( + LegacyBios, + Controller, + NULL, + &Flags, + NULL, + NULL, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Allocate memory for this SimpleNetwork device instance + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_SIMPLE_NETWORK_DEV), + (VOID **) &SimpleNetworkDevice + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV)); + + // + // Initialize the SimpleNetwork device instance + // + SimpleNetworkDevice->Signature = EFI_SIMPLE_NETWORK_DEV_SIGNATURE; + SimpleNetworkDevice->LegacyBios = LegacyBios; + SimpleNetworkDevice->BaseDevicePath = DevicePath; + SimpleNetworkDevice->PciIo = PciIo; + + // + // Initialize the Nii Protocol + // + SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; + SimpleNetworkDevice->Nii.Type = EfiNetworkInterfaceUndi; + + CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4); + + // + // Load 16 bit UNDI Option ROM into Memory + // + Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI. Status = %r\n", Status)); + goto Done; + } + + SimpleNetworkDevice->UndiLoaded = TRUE; + + // + // Call PXENV_START_UNDI - Initilizes the UNID interface for use. + // + PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); + Status = Undi16SimpleNetworkStartUndi ( + SimpleNetworkDevice, + (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function)) + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi. Status = %r\n", Status)); + goto Done; + } + // + // Initialize the Simple Network Protocol + // + DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n")); + + SimpleNetworkDevice->SimpleNetwork.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; + SimpleNetworkDevice->SimpleNetwork.Start = Undi16SimpleNetworkStart; + SimpleNetworkDevice->SimpleNetwork.Stop = Undi16SimpleNetworkStop; + SimpleNetworkDevice->SimpleNetwork.Initialize = Undi16SimpleNetworkInitialize; + SimpleNetworkDevice->SimpleNetwork.Reset = Undi16SimpleNetworkReset; + SimpleNetworkDevice->SimpleNetwork.Shutdown = Undi16SimpleNetworkShutdown; + SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters; + SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress; + SimpleNetworkDevice->SimpleNetwork.Statistics = Undi16SimpleNetworkStatistics; + SimpleNetworkDevice->SimpleNetwork.MCastIpToMac = Undi16SimpleNetworkMCastIpToMac; + SimpleNetworkDevice->SimpleNetwork.NvData = Undi16SimpleNetworkNvData; + SimpleNetworkDevice->SimpleNetwork.GetStatus = Undi16SimpleNetworkGetStatus; + SimpleNetworkDevice->SimpleNetwork.Transmit = Undi16SimpleNetworkTransmit; + SimpleNetworkDevice->SimpleNetwork.Receive = Undi16SimpleNetworkReceive; + SimpleNetworkDevice->SimpleNetwork.Mode = &(SimpleNetworkDevice->SimpleNetworkMode); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + Undi16SimpleNetworkWaitForPacket, + &SimpleNetworkDevice->SimpleNetwork, + &SimpleNetworkDevice->SimpleNetwork.WaitForPacket + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR : Could not create event. Status = %r\n", Status)); + goto Done; + } + // + // Create an event to be signalled when ExitBootServices occurs in order + // to clean up nicely + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + Undi16SimpleNetworkEvent, + NULL, + &gEfiEventExitBootServicesGuid, + &SimpleNetworkDevice->EfiBootEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR : Could not create event. Status = %r\n", Status)); + goto Done; + } + + // + // Create an event to be signalled when Legacy Boot occurs to clean up the IVT + // + Status = EfiCreateEventLegacyBootEx( + TPL_NOTIFY, + Undi16SimpleNetworkEvent, + NULL, + &SimpleNetworkDevice->LegacyBootEvent + ); + + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR,"ERROR : Could not create event. Status = %r\n",Status)); + goto Done; + } + + // + // Initialize the SimpleNetwork Mode Information + // + DEBUG ((DEBUG_NET, "Initialize Mode Information\n")); + + SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped; + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize = 14; + SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE; + SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported = TRUE; + SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | + EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS | + EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR; + + // + // Initialize the SimpleNetwork Private Information + // + DEBUG ((DEBUG_NET, "Initialize Private Information\n")); + + Status = BiosSnp16AllocatePagesBelowOneMb ( + sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1, + (VOID **) &SimpleNetworkDevice->Xmit + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = BiosSnp16AllocatePagesBelowOneMb ( + 1, + &SimpleNetworkDevice->TxRealModeMediaHeader + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = BiosSnp16AllocatePagesBelowOneMb ( + 1, + &SimpleNetworkDevice->TxRealModeDataBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = BiosSnp16AllocatePagesBelowOneMb ( + 1, + &SimpleNetworkDevice->TxDestAddr + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + SimpleNetworkDevice->Xmit->XmitOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f); + + SimpleNetworkDevice->Xmit->XmitSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4); + + SimpleNetworkDevice->Xmit->DataBlkCount = 1; + + SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType = 1; + SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte = 0; + + SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f); + + SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4); + + SimpleNetworkDevice->TxBufferFifo.First = 0; + SimpleNetworkDevice->TxBufferFifo.Last = 0; + + // + // Start() the SimpleNetwork device + // + DEBUG ((DEBUG_NET, "Start()\n")); + + Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // GetInformation() the SimpleNetwork device + // + DEBUG ((DEBUG_NET, "GetInformation()\n")); + + Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Build the device path for the child device + // + ZeroMem (&Node, sizeof (Node)); + Node.DevPath.Type = MESSAGING_DEVICE_PATH; + Node.DevPath.SubType = MSG_MAC_ADDR_DP; + SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH)); + CopyMem ( + &Node.MacAddr.MacAddress, + &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, + sizeof (EFI_MAC_ADDRESS) + ); + SimpleNetworkDevice->DevicePath = AppendDevicePathNode ( + SimpleNetworkDevice->BaseDevicePath, + &Node.DevPath + ); + + // + // GetNicType() the SimpleNetwork device + // + DEBUG ((DEBUG_NET, "GetNicType()\n")); + + Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // GetNdisInfo() the SimpleNetwork device + // + DEBUG ((DEBUG_NET, "GetNdisInfo()\n")); + + Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Stop() the SimpleNetwork device + // + DEBUG ((DEBUG_NET, "Stop()\n")); + + Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Print Mode information + // + DEBUG ((DEBUG_NET, "Mode->State = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State)); + DEBUG ((DEBUG_NET, "Mode->HwAddressSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize)); + DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable)); + DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported)); + DEBUG ((DEBUG_NET, "Mode->NvRamSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize)); + DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize)); + DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting)); + DEBUG ((DEBUG_NET, "Mode->IfType = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType)); + DEBUG ((DEBUG_NET, "Mode->MCastFilterCount = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount)); + for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) { + DEBUG ((DEBUG_NET, " Filter[%02d] = ", Index)); + for (Index2 = 0; Index2 < 16; Index2++) { + DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2])); + } + + DEBUG ((DEBUG_NET, "\n")); + } + + DEBUG ((DEBUG_NET, "CurrentAddress = ")); + for (Index2 = 0; Index2 < 16; Index2++) { + DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2])); + } + + DEBUG ((DEBUG_NET, "\n")); + + DEBUG ((DEBUG_NET, "BroadcastAddress = ")); + for (Index2 = 0; Index2 < 16; Index2++) { + DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2])); + } + + DEBUG ((DEBUG_NET, "\n")); + + DEBUG ((DEBUG_NET, "PermanentAddress = ")); + for (Index2 = 0; Index2 < 16; Index2++) { + DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2])); + } + + DEBUG ((DEBUG_NET, "\n")); + + // + // The network device was started, information collected, and stopped. + // Install protocol interfaces for the SimpleNetwork device. + // + DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n")); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &SimpleNetworkDevice->Handle, + &gEfiSimpleNetworkProtocolGuid, + &SimpleNetworkDevice->SimpleNetwork, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + &SimpleNetworkDevice->Nii, + &gEfiDevicePathProtocolGuid, + SimpleNetworkDevice->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Open PCI I/O from the newly created child handle + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + SimpleNetworkDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + + DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n")); + +Done: + if (EFI_ERROR (Status)) { + if (SimpleNetworkDevice != NULL) { + + Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork); + // + // CLOSE + SHUTDOWN + // + Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice); + // + // CLEANUP + // + Undi16SimpleNetworkStopUndi (SimpleNetworkDevice); + // + // STOP + // + if (SimpleNetworkDevice->UndiLoaded) { + Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice); + } + + if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) { + gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket); + } + + if (SimpleNetworkDevice->LegacyBootEvent != NULL) { + gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent); + } + + if (SimpleNetworkDevice->EfiBootEvent != NULL) { + gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent); + } + + if (SimpleNetworkDevice->Xmit != NULL) { + gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit, + sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1 + ); + } + + if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1); + } + + if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1); + } + + if (SimpleNetworkDevice->TxDestAddr != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1); + } + + gBS->FreePool (SimpleNetworkDevice); + + // + // Only restore the vector if it was cached. + // + if (mCachedInt1A) { + RestoreCachedVectorAddress (0x1A); + mCachedInt1A = FALSE; + } + } + + if (PciIo != NULL) { + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, + Supports, + NULL + ); + } + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + if (Status != EFI_OUT_OF_RESOURCES) { + Status = EFI_DEVICE_ERROR; + } + } + return Status; +} + +/** + Stops the device by given device controller. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param ChildHandleBuffer An array of child handles to be freed. May be NULL if + NumberOfChildren is 0. + + @retval EFI_SUCCESS - The device was stopped. + @retval EFI_DEVICE_ERROR - The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +BiosSnp16DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 Supports; + + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, + Supports, + NULL + ); + } + } + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + return Status; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &SimpleNetwork, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + SimpleNetworkDevice->Handle, + &gEfiSimpleNetworkProtocolGuid, + &SimpleNetworkDevice->SimpleNetwork, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + &SimpleNetworkDevice->Nii, + &gEfiDevicePathProtocolGuid, + SimpleNetworkDevice->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + + Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork); + // + // CLOSE + SHUTDOWN + // + Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice); + // + // CLEANUP + // + Undi16SimpleNetworkStopUndi (SimpleNetworkDevice); + // + // STOP + // + if (SimpleNetworkDevice->UndiLoaded) { + Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice); + } + + if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) { + gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket); + } + + if (SimpleNetworkDevice->LegacyBootEvent != NULL) { + gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent); + } + + if (SimpleNetworkDevice->EfiBootEvent != NULL) { + gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent); + } + + if (SimpleNetworkDevice->Xmit != NULL) { + gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit, + sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1 + ); + } + + if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1); + } + + if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1); + } + + if (SimpleNetworkDevice->TxDestAddr != NULL) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1); + } + + gBS->FreePool (SimpleNetworkDevice); + } + + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +// +// FIFO Support Functions +// +/** + Judge whether transmit FIFO is full. + + @param Fifo Point to trasmit FIFO structure. + + @return BOOLEAN whether transmit FIFO is full. +**/ +BOOLEAN +SimpleNetworkTransmitFifoFull ( + EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo + ) +{ + if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) { + return TRUE; + } + + return FALSE; +} + +/** + Judge whether transmit FIFO is empty. + + @param Fifo Point to trasmit FIFO structure. + + @return BOOLEAN whether transmit FIFO is empty. +**/ +BOOLEAN +SimpleNetworkTransmitFifoEmpty ( + EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo + ) +{ + if (Fifo->Last == Fifo->First) { + return TRUE; + } + + return FALSE; +} + + +/** + Add data into transmit buffer. + + @param Fifo Point to trasmit FIFO structure. + @param Data The data point want to be added. + + @retval EFI_OUT_OF_RESOURCES FIFO is full + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +SimpleNetworkTransmitFifoAdd ( + EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo, + VOID *Data + ) +{ + if (SimpleNetworkTransmitFifoFull (Fifo)) { + return EFI_OUT_OF_RESOURCES; + } + + Fifo->Data[Fifo->Last] = Data; + Fifo->Last = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE; + return EFI_SUCCESS; +} + +/** + Get a data and remove it from network transmit FIFO. + + @param Fifo Point to trasmit FIFO structure. + @param Data On return, point to the data point want to be got and removed. + + @retval EFI_OUT_OF_RESOURCES network transmit buffer is empty. + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +SimpleNetworkTransmitFifoRemove ( + EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo, + VOID **Data + ) +{ + if (SimpleNetworkTransmitFifoEmpty (Fifo)) { + return EFI_OUT_OF_RESOURCES; + } + + *Data = Fifo->Data[Fifo->First]; + Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE; + return EFI_SUCCESS; +} + +/** + Get recive filter setting according to EFI mask value. + + @param ReceiveFilterSetting filter setting EFI mask value. + + @return UINT16 Undi filter setting value. +**/ +UINT16 +Undi16GetPacketFilterSetting ( + UINTN ReceiveFilterSetting + ) +{ + UINT16 PktFilter; + + PktFilter = 0; + if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) { + PktFilter |= FLTR_DIRECTED; + } + + if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { + PktFilter |= FLTR_DIRECTED; + } + + if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) { + PktFilter |= FLTR_BRDCST; + } + + if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) { + PktFilter |= FLTR_PRMSCS; + } + + if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) { + PktFilter |= FLTR_PRMSCS; + // + // @bug : Do not know if this is right???? + // + } + // + // @bug : What is FLTR_SRC_RTG? + // + return PktFilter; +} + +/** + Get filter setting from multi cast buffer . + + @param Mode Point to mode structure. + @param McastBuffer The multi cast buffer + @param HwAddressSize Size of filter value. + +**/ +VOID +Undi16GetMCastFilters ( + IN EFI_SIMPLE_NETWORK_MODE *Mode, + IN OUT PXENV_UNDI_MCAST_ADDR_T *McastBuffer, + IN UINTN HwAddressSize + ) +{ + UINTN Index; + + // + // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR? + // + McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount; + for (Index = 0; Index < MAXNUM_MCADDR; Index++) { + if (Index < McastBuffer->MCastAddrCount) { + CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize); + } else { + ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize); + } + } +} +// +// Load 16 bit UNDI Option ROM into memory +// +/** + Loads the undi driver. + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + + @retval EFI_SUCCESS - Successfully loads undi driver. + @retval EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure. +**/ +EFI_STATUS +Undi16SimpleNetworkLoadUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN RomAddress; + PCI_EXPANSION_ROM_HEADER *PciExpansionRomHeader; + PCI_DATA_STRUCTURE *PciDataStructure; + PCI_TYPE00 Pci; + + if (!mCachedInt1A) { + Status = CacheVectorAddress (0x1A); + if (!EFI_ERROR (Status)) { + mCachedInt1A = TRUE; + } + } + + PciIo = SimpleNetworkDevice->PciIo; + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + + for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) { + + PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress; + + if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + continue; + } + + DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress)); + + // + // If the pointer to the PCI Data Structure is invalid, no further images can be located. + // The PCI Data Structure must be DWORD aligned. + // + if (PciExpansionRomHeader->PcirOffset == 0 || + (PciExpansionRomHeader->PcirOffset & 3) != 0 || + RomAddress + PciExpansionRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > 0x100000) { + break; + } + + PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset); + + if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + continue; + } + + DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure)); + + if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) { + continue; + } + + DEBUG ( + (DEBUG_INIT, + "PCI device with matchinng VendorId and DeviceId (%d,%d)\n", + (UINTN) PciDataStructure->VendorId, + (UINTN) PciDataStructure->DeviceId) + ); + + Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress); + + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // Free resources allocated in LaunchBaseCode + // + Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice); + } + + return EFI_NOT_FOUND; +} + +/** + Unload 16 bit UNDI Option ROM from memory + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + + @return EFI_STATUS +**/ +EFI_STATUS +Undi16SimpleNetworkUnloadUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice + ) +{ + if (SimpleNetworkDevice->UndiLoaderTable != NULL) { + ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT); + gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable, + SimpleNetworkDevice->UndiLoaderTablePages + ); + } + + if (SimpleNetworkDevice->DestinationDataSegment != NULL) { + ZeroMem ( + SimpleNetworkDevice->DestinationDataSegment, + SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT + ); + gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment, + SimpleNetworkDevice->DestinationDataSegmentPages + ); + } + + if (SimpleNetworkDevice->DestinationStackSegment != NULL) { + ZeroMem ( + SimpleNetworkDevice->DestinationStackSegment, + SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT + ); + gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment, + SimpleNetworkDevice->DestinationStackSegmentPages + ); + } + + if (SimpleNetworkDevice->DestinationCodeSegment != NULL) { + ZeroMem ( + SimpleNetworkDevice->DestinationCodeSegment, + SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT + ); + gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment, + SimpleNetworkDevice->DestinationCodeSegmentPages + ); + } + + return EFI_SUCCESS; +} + +/** + Start the UNDI interface. + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + @param Ax PCI address of Undi device. + + @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. + @retval Others Status of start 16 bit UNDI ROM. +**/ +EFI_STATUS +Undi16SimpleNetworkStartUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + UINT16 Ax + ) +{ + EFI_STATUS Status; + PXENV_START_UNDI_T Start; + + // + // Call 16 bit UNDI ROM to start the network interface + // + // + // @bug : What is this state supposed to be??? + // + Start.Status = INIT_PXE_STATUS; + Start.Ax = Ax; + Start.Bx = 0x0000; + Start.Dx = 0x0000; + Start.Di = 0x0000; + Start.Es = 0x0000; + + Status = PxeStartUndi (SimpleNetworkDevice, &Start); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Start.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + return Status; +} + + +/** + Stop the UNDI interface + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + + @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM. + @retval Others Status of stop 16 bit UNDI ROM. +**/ +EFI_STATUS +Undi16SimpleNetworkStopUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice + ) +{ + EFI_STATUS Status; + PXENV_STOP_UNDI_T Stop; + + // + // Call 16 bit UNDI ROM to start the network interface + // + Stop.Status = INIT_PXE_STATUS; + + Status = PxeUndiStop (SimpleNetworkDevice, &Stop); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Stop.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + Cleanup Unid network interface + + @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. + + @retval EFI_DEVICE_ERROR Fail to cleanup 16 bit UNDI ROM. + @retval Others Status of cleanup 16 bit UNDI ROM. +**/ +EFI_STATUS +Undi16SimpleNetworkCleanupUndi ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice + ) +{ + EFI_STATUS Status; + PXENV_UNDI_CLEANUP_T Cleanup; + + // + // Call 16 bit UNDI ROM to cleanup the network interface + // + Cleanup.Status = INIT_PXE_STATUS; + + Status = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Cleanup.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + Get runtime information for Undi network interface + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_SUCCESS Sucess operation. + @retval Others Fail to get runtime information for Undi network interface. +**/ +EFI_STATUS +Undi16SimpleNetworkGetInformation ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + UINTN Index; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkStarted: + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + default: + return EFI_DEVICE_ERROR; + } + // + // Call 16 bit UNDI ROM to start the network interface + // + ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T)); + + SimpleNetworkDevice->GetInformation.Status = INIT_PXE_STATUS; + + Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((DEBUG_NET, " GetInformation.Status = %d\n", SimpleNetworkDevice->GetInformation.Status)); + DEBUG ((DEBUG_NET, " GetInformation.BaseIo = %d\n", SimpleNetworkDevice->GetInformation.BaseIo)); + DEBUG ((DEBUG_NET, " GetInformation.IntNumber = %d\n", SimpleNetworkDevice->GetInformation.IntNumber)); + DEBUG ((DEBUG_NET, " GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit)); + DEBUG ((DEBUG_NET, " GetInformation.HwType = %d\n", SimpleNetworkDevice->GetInformation.HwType)); + DEBUG ((DEBUG_NET, " GetInformation.HwAddrLen = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen)); + DEBUG ((DEBUG_NET, " GetInformation.ROMAddress = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress)); + DEBUG ((DEBUG_NET, " GetInformation.RxBufCt = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt)); + DEBUG ((DEBUG_NET, " GetInformation.TxBufCt = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt)); + + DEBUG ((DEBUG_NET, " GetInformation.CurNodeAddr =")); + for (Index = 0; Index < 16; Index++) { + DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index])); + } + + DEBUG ((DEBUG_NET, "\n")); + + DEBUG ((DEBUG_NET, " GetInformation.PermNodeAddr =")); + for (Index = 0; Index < 16; Index++) { + DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index])); + } + + DEBUG ((DEBUG_NET, "\n")); + + // + // Check the status code from the 16 bit UNDI ROM + // + if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // The information has been retrieved. Fill in Mode data. + // + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize = SimpleNetworkDevice->GetInformation.HwAddrLen; + + SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize = SimpleNetworkDevice->GetInformation.MaxTranUnit; + + SimpleNetworkDevice->SimpleNetworkMode.IfType = (UINT8) SimpleNetworkDevice->GetInformation.HwType; + + ZeroMem ( + &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, + sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress + ); + + CopyMem ( + &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, + &SimpleNetworkDevice->GetInformation.CurrentNodeAddress, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + ZeroMem ( + &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress, + sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress + ); + + CopyMem ( + &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress, + &SimpleNetworkDevice->GetInformation.PermNodeAddress, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + // + // hard code broadcast address - not avail in PXE2.1 + // + ZeroMem ( + &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress, + sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress + ); + + SetMem ( + &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize, + 0xff + ); + + return Status; +} + +/** + Get NIC type + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_SUCCESS Sucess operation. + @retval Others Fail to get NIC type. +**/ +EFI_STATUS +Undi16SimpleNetworkGetNicType ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + + ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T)); + + SimpleNetworkDevice->GetNicType.Status = INIT_PXE_STATUS; + + Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType); + + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((DEBUG_NET, " GetNicType.Status = %d\n", SimpleNetworkDevice->GetNicType.Status)); + DEBUG ((DEBUG_NET, " GetNicType.NicType = %d\n", SimpleNetworkDevice->GetNicType.NicType)); + // + // Check the status code from the 16 bit UNDI ROM + // + if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // The information has been retrieved. Fill in Mode data. + // + return Status; +} + +/** + Get NDIS information + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_SUCCESS Sucess operation. + @retval Others Fail to get NDIS information. +**/ +EFI_STATUS +Undi16SimpleNetworkGetNdisInfo ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + + ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T)); + + SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS; + + Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo); + + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((DEBUG_NET, " GetNdisInfo.Status = %d\n", SimpleNetworkDevice->GetNdisInfo.Status)); + DEBUG ((DEBUG_NET, " GetNdisInfo.IfaceType = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType)); + DEBUG ((DEBUG_NET, " GetNdisInfo.LinkSpeed = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed)); + DEBUG ((DEBUG_NET, " GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags)); + + // + // Check the status code from the 16 bit UNDI ROM + // + if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // The information has been retrieved. Fill in Mode data. + // + return Status; +} + +/** + Call Undi ROM 16bit ISR() to check interrupt cause. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param FrameLength The length of frame buffer. + @param FrameHeaderLength The length of frame buffer's header if has. + @param Frame The frame buffer to process network interrupt. + @param ProtType The type network transmit protocol + @param PktType The type of package. + + @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM's ISR, or status is invalid. + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +Undi16SimpleNetworkIsr ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + IN UINTN *FrameLength, + IN UINTN *FrameHeaderLength, OPTIONAL + IN UINT8 *Frame, OPTIONAL + IN UINT8 *ProtType, OPTIONAL + IN UINT8 *PktType OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + BOOLEAN FrameReceived; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + + FrameReceived = FALSE; + + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + + DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid)); + + if (!SimpleNetworkDevice->IsrValid) { + // + // Call 16 bit UNDI ROM to open the network interface + // + ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T)); + SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS; + SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START; + + DEBUG ((DEBUG_NET, "Isr() START\n")); + + Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // There have been no events on this UNDI interface, so return EFI_NOT_READY + // + if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) { + return EFI_SUCCESS; + } + // + // There is data to process, so call until all events processed. + // + ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T)); + SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS; + SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS; + + DEBUG ((DEBUG_NET, "Isr() PROCESS\n")); + + Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr); + if (EFI_ERROR (Status)) { + return Status; + } + + SimpleNetworkDevice->IsrValid = TRUE; + } + // + // Call UNDI GET_NEXT until DONE + // + while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) { + // + // Check the status code from the 16 bit UNDI ROM + // + if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // UNDI is busy. Caller will have to call again. + // This should never happen with a polled mode driver. + // + if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) { + DEBUG ((DEBUG_NET, " BUSY\n")); + return EFI_SUCCESS; + } + // + // Check for invalud UNDI FuncFlag + // + if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE && + SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT + ) { + DEBUG ((DEBUG_NET, " Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag)); + return EFI_DEVICE_ERROR; + } + // + // Check for Transmit Event + // + if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) { + DEBUG ((DEBUG_NET, " TRANSMIT\n")); + SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; + } + // + // Check for Receive Event + // + else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) { + // + // note - this code will hang on a receive interrupt in a GetStatus loop + // + DEBUG ((DEBUG_NET, " RECEIVE\n")); + SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + + DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength = %d\n", SimpleNetworkDevice->Isr.BufferLength)); + DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength = %d\n", SimpleNetworkDevice->Isr.FrameLength)); + DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength)); + DEBUG ( + ( + DEBUG_NET, "SimpleNetworkDevice->Isr.Frame = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel, + SimpleNetworkDevice->Isr.FrameOffset + ) + ); + DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength)); + DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength)); + + if (FrameReceived) { + return EFI_SUCCESS; + } + + if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) { + DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL *FrameLength = %08x\n", *FrameLength)); + *FrameLength = SimpleNetworkDevice->Isr.FrameLength; + return EFI_BUFFER_TOO_SMALL; + } + + *FrameLength = SimpleNetworkDevice->Isr.FrameLength; + if (FrameHeaderLength != NULL) { + *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength; + } + + if (ProtType != NULL) { + *ProtType = SimpleNetworkDevice->Isr.ProtType; + } + + if (PktType != NULL) { + *PktType = SimpleNetworkDevice->Isr.PktType; + } + + CopyMem ( + Frame, + (VOID *)(UINTN) ((SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset), + SimpleNetworkDevice->Isr.BufferLength + ); + Frame = Frame + SimpleNetworkDevice->Isr.BufferLength; + if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) { + FrameReceived = TRUE; + } + } + // + // There is data to process, so call until all events processed. + // + ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T)); + SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS; + SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; + + DEBUG ((DEBUG_NET, "Isr() GET NEXT\n")); + + Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + // if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) { + // return EFI_DEVICE_ERROR; + // } + // + } + + SimpleNetworkDevice->IsrValid = FALSE; + return EFI_SUCCESS; +} +// +// /////////////////////////////////////////////////////////////////////////////////////// +// Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs +///////////////////////////////////////////////////////////////////////////////////////// +// +// Start() +// +/** + Call 16 bit UNDI ROM to start the network interface + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_DEVICE_ERROR Network interface has not be initialized. + @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. + @retval EFI_SUCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkStart ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_STARTUP_T Startup; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkStopped: + break; + + case EfiSimpleNetworkStarted: + case EfiSimpleNetworkInitialized: + return EFI_ALREADY_STARTED; + + default: + return EFI_DEVICE_ERROR; + } + // + // Call 16 bit UNDI ROM to start the network interface + // + Startup.Status = INIT_PXE_STATUS; + + Status = PxeUndiStartup (SimpleNetworkDevice, &Startup); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Startup.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // The UNDI interface has been started, so update the State. + // + SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted; + + // + // + // + SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0; + SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = 0; + + return Status; +} +// +// Stop() +// +/** + Call 16 bit UNDI ROM to stop the network interface + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_DEVICE_ERROR Network interface has not be initialized. + @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. + @retval EFI_SUCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkStop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkStarted: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkInitialized: + default: + return EFI_DEVICE_ERROR; + } + + SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped; + + return Status; +} + +// +// Initialize() +// +/** + Initialize network interface + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param ExtraRxBufferSize The size of extra request receive buffer. + @param ExtraTxBufferSize The size of extra request transmit buffer. + + @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. + @retval EFI_SUCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkInitialize ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_INITIALIZE_T Initialize; + PXENV_UNDI_OPEN_T Open; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + break; + + case EfiSimpleNetworkInitialized: + default: + return EFI_DEVICE_ERROR; + } + // + // Call 16 bit UNDI ROM to start the network interface + // + Initialize.Status = INIT_PXE_STATUS; + Initialize.ProtocolIni = 0; + + Status = PxeUndiInitialize (SimpleNetworkDevice, &Initialize); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status)); + + if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) { + Status = EFI_NO_MEDIA; + } + + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Initialize.Status != PXENV_STATUS_SUCCESS) { + DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status)); + return EFI_DEVICE_ERROR; + } + // + // Call 16 bit UNDI ROM to open the network interface + // + Open.Status = INIT_PXE_STATUS; + Open.OpenFlag = 0; + Open.PktFilter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting); + Undi16GetMCastFilters ( + &SimpleNetworkDevice->SimpleNetworkMode, + &Open.McastBuffer, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + Status = PxeUndiOpen (SimpleNetworkDevice, &Open); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status)); + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Open.Status != PXENV_STATUS_SUCCESS) { + DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status)); + return EFI_DEVICE_ERROR; + } + // + // The UNDI interface has been initialized, so update the State. + // + SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized; + + // + // If initialize succeeds, then assume that media is present. + // + SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE; + + // + // Reset the recycled transmit buffer FIFO + // + SimpleNetworkDevice->TxBufferFifo.First = 0; + SimpleNetworkDevice->TxBufferFifo.Last = 0; + SimpleNetworkDevice->IsrValid = FALSE; + + return Status; +} +// +// Reset() +// +/** + Reset network interface. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param ExtendedVerification Need extended verfication. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkReset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_RESET_T Reset; + UINT16 Rx_filter; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + + Reset.Status = INIT_PXE_STATUS; + + Rx_filter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting); + + Undi16GetMCastFilters ( + &SimpleNetworkDevice->SimpleNetworkMode, + &Reset.R_Mcast_Buf, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Reset.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // Reset the recycled transmit buffer FIFO + // + SimpleNetworkDevice->TxBufferFifo.First = 0; + SimpleNetworkDevice->TxBufferFifo.Last = 0; + SimpleNetworkDevice->IsrValid = FALSE; + + return Status; +} +// +// Shutdown() +// +/** + Shutdown network interface. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkShutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_CLOSE_T Close; + PXENV_UNDI_SHUTDOWN_T Shutdown; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + + SimpleNetworkDevice->IsrValid = FALSE; + + // + // Call 16 bit UNDI ROM to start the network interface + // + Close.Status = INIT_PXE_STATUS; + + Status = PxeUndiClose (SimpleNetworkDevice, &Close); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Close.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // Call 16 bit UNDI ROM to open the network interface + // + Shutdown.Status = INIT_PXE_STATUS; + + Status = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Shutdown.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // The UNDI interface has been initialized, so update the State. + // + SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted; + + // + // If shutdown succeeds, then assume that media is not present. + // + SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE; + + // + // Reset the recycled transmit buffer FIFO + // + SimpleNetworkDevice->TxBufferFifo.First = 0; + SimpleNetworkDevice->TxBufferFifo.Last = 0; + + // + // A short delay. Without this an initialize immediately following + // a shutdown will cause some versions of UNDI-16 to stop operating. + // + gBS->Stall (250000); + + return Status; +} +// +// ReceiveFilters() +// +/** + Reset network interface. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param Enable Enable mask value + @param Disable Disable mask value + @param ResetMCastFilter Whether reset multi cast filter or not + @param MCastFilterCnt Count of mutli cast filter for different MAC address + @param MCastFilter Buffer for mustli cast filter for different MAC address. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkReceiveFilters ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN Index; + UINT32 NewFilter; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_CLOSE_T Close; + PXENV_UNDI_OPEN_T Open; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + // + // First deal with possible filter setting changes + // + if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) { + return EFI_SUCCESS; + } + + NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable; + + if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { + if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) { + return EFI_INVALID_PARAMETER; + } + } + // + // Call 16 bit UNDI ROM to close the network interface + // + Close.Status = INIT_PXE_STATUS; + + Status = PxeUndiClose (SimpleNetworkDevice, &Close); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Close.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // Call 16 bit UNDI ROM to open the network interface + // + // + // Reset the recycled transmit buffer FIFO + // + SimpleNetworkDevice->TxBufferFifo.First = 0; + SimpleNetworkDevice->TxBufferFifo.Last = 0; + + // + // Call 16 bit UNDI ROM to open the network interface + // + ZeroMem (&Open, sizeof Open); + + Open.Status = INIT_PXE_STATUS; + Open.PktFilter = Undi16GetPacketFilterSetting (NewFilter); + + if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { + // + // Copy the MAC addresses into the UNDI open parameter structure + // + Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt; + for (Index = 0; Index < MCastFilterCnt; ++Index) { + CopyMem ( + Open.McastBuffer.MCastAddr[Index], + &MCastFilter[Index], + sizeof Open.McastBuffer.MCastAddr[Index] + ); + } + } else if (!ResetMCastFilter) { + for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) { + CopyMem ( + Open.McastBuffer.MCastAddr[Index], + &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index], + sizeof Open.McastBuffer.MCastAddr[Index] + ); + } + } + + Status = PxeUndiOpen (SimpleNetworkDevice, &Open); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (Open.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + SimpleNetworkDevice->IsrValid = FALSE; + SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter; + + if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { + SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt; + for (Index = 0; Index < MCastFilterCnt; ++Index) { + CopyMem ( + &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index], + &MCastFilter[Index], + sizeof (EFI_MAC_ADDRESS) + ); + } + } + // + // Read back multicast addresses. + // + return EFI_SUCCESS; +} +// +// StationAddress() +// +/** + Set new MAC address. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param Reset Whether reset station MAC address to permenent address + @param New A pointer to New address + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkStationAddress ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS * New OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr; + // + // EFI_DEVICE_PATH_PROTOCOL *OldDevicePath; + // + PXENV_UNDI_CLOSE_T Close; + PXENV_UNDI_OPEN_T Open; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + // + // Call 16 bit UNDI ROM to open the network interface + // + SetStationAddr.Status = INIT_PXE_STATUS; + + if (Reset) { + // + // If we are reseting the Station Address to the permanent address, and the + // Station Address is not programmable, then just return EFI_SUCCESS. + // + if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) { + return EFI_SUCCESS; + } + // + // If the address is already the permanent address, then just return success. + // + if (CompareMem ( + &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, + &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ) == 0) { + return EFI_SUCCESS; + } + // + // Copy the adapters permanent address to the new station address + // + CopyMem ( + &SetStationAddr.StationAddress, + &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + } else { + // + // If we are setting the Station Address, and the + // Station Address is not programmable, return invalid parameter. + // + if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) { + return EFI_INVALID_PARAMETER; + } + // + // If the address is already the new address, then just return success. + // + if (CompareMem ( + &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, + New, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ) == 0) { + return EFI_SUCCESS; + } + // + // Copy New to the new station address + // + CopyMem ( + &SetStationAddr.StationAddress, + New, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + } + // + // Call 16 bit UNDI ROM to stop the network interface + // + Close.Status = INIT_PXE_STATUS; + + PxeUndiClose (SimpleNetworkDevice, &Close); + + // + // Call 16-bit UNDI ROM to set the station address + // + SetStationAddr.Status = PXENV_STATUS_SUCCESS; + + Status = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr); + + // + // Call 16-bit UNDI ROM to start the network interface + // + Open.Status = PXENV_STATUS_SUCCESS; + Open.OpenFlag = 0; + Open.PktFilter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting); + Undi16GetMCastFilters ( + &SimpleNetworkDevice->SimpleNetworkMode, + &Open.McastBuffer, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + PxeUndiOpen (SimpleNetworkDevice, &Open); + + // + // Check status from station address change + // + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CopyMem ( + &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, + &SetStationAddr.StationAddress, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + +#if 0 /* The device path is based on the permanent address not the current address. */ + // + // The station address was changed, so update the device path with the new MAC address. + // + OldDevicePath = SimpleNetworkDevice->DevicePath; + SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath); + SimpleNetworkAppendMacAddressDevicePath ( + &SimpleNetworkDevice->DevicePath, + &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress + ); + + Status = LibReinstallProtocolInterfaces ( + SimpleNetworkDevice->Handle, + &DevicePathProtocol, + OldDevicePath, + SimpleNetworkDevice->DevicePath, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n")); + DEBUG ((DEBUG_ERROR, " Status = %r\n", Status)); + } + + FreePool (OldDevicePath); +#endif /* 0 */ + + return Status; +} +// +// Statistics() +// +/** + Resets or collects the statistics on a network interface. + + @param This Protocol instance pointer. + @param Reset Set to TRUE to reset the statistics for the network interface. + @param StatisticsSize On input the size, in bytes, of StatisticsTable. On + output the size, in bytes, of the resulting table of + statistics. + @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that + contains the statistics. + + @retval EFI_SUCCESS The statistics were collected from the network interface. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkStatistics ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics; + PXENV_UNDI_GET_STATISTICS_T GetStatistics; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + + if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // If Reset is TRUE, then clear all the statistics. + // + if (Reset) { + + DEBUG ((DEBUG_NET, " RESET Statistics\n")); + + // + // Call 16 bit UNDI ROM to open the network interface + // + ClearStatistics.Status = INIT_PXE_STATUS; + + Status = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + DEBUG ((DEBUG_NET, " RESET Statistics Complete")); + } + + if (StatisticsSize != NULL) { + EFI_NETWORK_STATISTICS LocalStatisticsTable; + + DEBUG ((DEBUG_NET, " GET Statistics\n")); + + // + // If the size if valid, then see if the table is valid + // + if (StatisticsTable == NULL) { + DEBUG ((DEBUG_NET, " StatisticsTable is NULL\n")); + return EFI_INVALID_PARAMETER; + } + // + // Call 16 bit UNDI ROM to open the network interface + // + GetStatistics.Status = INIT_PXE_STATUS; + GetStatistics.XmtGoodFrames = 0; + GetStatistics.RcvGoodFrames = 0; + GetStatistics.RcvCRCErrors = 0; + GetStatistics.RcvResourceErrors = 0; + + Status = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (GetStatistics.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // Fill in the Statistics Table with the collected values. + // + SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff); + + LocalStatisticsTable.TxGoodFrames = GetStatistics.XmtGoodFrames; + LocalStatisticsTable.RxGoodFrames = GetStatistics.RcvGoodFrames; + LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors; + LocalStatisticsTable.RxDroppedFrames = GetStatistics.RcvResourceErrors; + + CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize); + + DEBUG ( + (DEBUG_NET, + " Statistics Collected : Size=%d Buf=%08x\n", + *StatisticsSize, + StatisticsTable) + ); + + DEBUG ((DEBUG_NET, " GET Statistics Complete")); + + if (*StatisticsSize < sizeof LocalStatisticsTable) { + DEBUG ((DEBUG_NET, " BUFFER TOO SMALL\n")); + Status = EFI_BUFFER_TOO_SMALL; + } + + *StatisticsSize = sizeof LocalStatisticsTable; + + return Status; + + } + + return EFI_SUCCESS; +} +// +// MCastIpToMac() +// +/** + Translate IP address to MAC address. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param IPv6 IPv6 or IPv4 + @param IP A pointer to given Ip address. + @param MAC On return, translated MAC address. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_INVALID_PARAMETER Invalid IP address. + @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address. + @retval EFI_UNSUPPORTED Do not support IPv6 + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkMCastIpToMac ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr; + + if (This == NULL || IP == NULL || MAC == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + // + // 16 bit UNDI Option ROMS do not support IPv6. Check for IPv6 usage. + // + if (IPv6) { + return EFI_UNSUPPORTED; + } + // + // Call 16 bit UNDI ROM to open the network interface + // + GetMcastAddr.Status = INIT_PXE_STATUS; + CopyMem (&GetMcastAddr.InetAddr, IP, 4); + + Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + // + // Copy the MAC address from the returned data structure. + // + CopyMem ( + MAC, + &GetMcastAddr.MediaAddr, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + return Status; +} +// +// NvData() +// +/** + Performs read and write operations on the NVRAM device attached to a + network interface. + + @param This The protocol instance pointer. + @param ReadWrite TRUE for read operations, FALSE for write operations. + @param Offset Byte offset in the NVRAM device at which to start the read or + write operation. This must be a multiple of NvRamAccessSize and + less than NvRamSize. + @param BufferSize The number of bytes to read or write from the NVRAM device. + This must also be a multiple of NvramAccessSize. + @param Buffer A pointer to the data buffer. + + @retval EFI_SUCCESS The NVRAM access was performed. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkNvData ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ) +{ + return EFI_UNSUPPORTED; +} +// +// GetStatus() +// +/** + Reads the current interrupt status and recycled transmit buffer status from + a network interface. + + @param This The protocol instance pointer. + @param InterruptStatus A pointer to the bit mask of the currently active interrupts + If this is NULL, the interrupt status will not be read from + the device. If this is not NULL, the interrupt status will + be read from the device. When the interrupt status is read, + it will also be cleared. Clearing the transmit interrupt + does not empty the recycled transmit buffer array. + @param TxBuf Recycled transmit buffer address. The network interface will + not transmit if its internal recycled transmit buffer array + is full. Reading the transmit buffer does not clear the + transmit interrupt. If this is NULL, then the transmit buffer + status will not be read. If there are no transmit buffers to + recycle and TxBuf is not NULL, * TxBuf will be set to NULL. + + @retval EFI_SUCCESS The status of the network interface was retrieved. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkGetStatus ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + UINTN FrameLength; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + + if (InterruptStatus == NULL && TxBuf == NULL) { + return EFI_INVALID_PARAMETER; + } + + FrameLength = 0; + Status = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL); + + if (Status != EFI_BUFFER_TOO_SMALL) { + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // See if the caller wants interrupt info. + // + if (InterruptStatus != NULL) { + *InterruptStatus = SimpleNetworkDevice->InterruptStatus; + SimpleNetworkDevice->InterruptStatus = 0; + } + // + // See if the caller wants transmit buffer status info. + // + if (TxBuf != NULL) { + *TxBuf = 0; + SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf); + } + + return EFI_SUCCESS; +} + +/** + Places a packet in the transmit queue of a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then it + must be equal to This->Mode->MediaHeaderSize and the DestAddr + and Protocol parameters must not be NULL. + @param BufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param Buffer A pointer to the packet (media header followed by data) to be + transmitted. This parameter cannot be NULL. If HeaderSize is zero, + then the media header in Buffer must already be filled in by the + caller. If HeaderSize is non-zero, then the media header will be + filled in by the Transmit() function. + @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter + is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then + This->Mode->CurrentAddress is used for the source HW MAC address. + @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this + parameter is ignored. + @param Protocol The type of header to build. If HeaderSize is zero, then this + parameter is ignored. See RFC 1700, section "Ether Types", for + examples. + + @retval EFI_SUCCESS The packet was placed on the transmit queue. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkTransmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *Protocol OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + PXENV_UNDI_TRANSMIT_T XmitInfo; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) { + return EFI_BUFFER_TOO_SMALL; + } + + if (HeaderSize != 0) { + if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) { + return EFI_INVALID_PARAMETER; + } + + if (DestAddr == NULL || Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (DestAddr != NULL) { + CopyMem ( + Buffer, + DestAddr, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + } + + if (SrcAddr == NULL) { + SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress; + } + + CopyMem ( + (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize, + SrcAddr, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + if (Protocol != NULL) { + *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF)); + } + } + // + // See if the recycled transmit buffer FIFO is full. + // If it is full, then we can not transmit until the caller calls GetStatus() to pull + // off recycled transmit buffers. + // + if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) { + return EFI_NOT_READY; + } + // + // Output debug trace message. + // + DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r ")); + + // + // Initialize UNDI WRITE parameter structure. + // + XmitInfo.Status = INIT_PXE_STATUS; + XmitInfo.Protocol = P_UNKNOWN; + XmitInfo.XmitFlag = XMT_DESTADDR; + XmitInfo.DestAddrOffset = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f); + XmitInfo.DestAddrSegment = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4); + XmitInfo.TBDOffset = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f); + XmitInfo.TBDSegment = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4); + XmitInfo.Reserved[0] = 0; + XmitInfo.Reserved[1] = 0; + + CopyMem ( + SimpleNetworkDevice->TxDestAddr, + Buffer, + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize + ); + + CopyMem ( + SimpleNetworkDevice->TxRealModeMediaHeader, + Buffer, + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize + ); + + SimpleNetworkDevice->Xmit->ImmedLength = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize; + + SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength); + + CopyMem ( + SimpleNetworkDevice->TxRealModeDataBuffer, + (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize, + SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen + ); + + // + // Make API call to UNDI TRANSMIT + // + XmitInfo.Status = 0; + + Status = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the status code from the 16 bit UNDI ROM + // + switch (XmitInfo.Status) { + case PXENV_STATUS_OUT_OF_RESOURCES: + return EFI_NOT_READY; + + case PXENV_STATUS_SUCCESS: + break; + + default: + return EFI_DEVICE_ERROR; + } + // + // Add address of Buffer to the recycled transmit buffer FIFO + // + SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer); + + return EFI_SUCCESS; +} + +/** + Receives a packet from a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header received on the network + interface. If this parameter is NULL, then the media header size + will not be returned. + @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in + bytes, of the packet that was received on the network interface. + @param Buffer A pointer to the data buffer to receive both the media header and + the data. + @param SrcAddr The source HW MAC address. If this parameter is NULL, the + HW MAC source address will not be extracted from the media + header. + @param DestAddr The destination HW MAC address. If this parameter is NULL, + the HW MAC destination address will not be extracted from the + media header. + @param Protocol The media header type. If this parameter is NULL, then the + protocol will not be extracted from the media header. See + RFC 1700 section "Ether Types" for examples. + + @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has + been updated to the number of bytes received. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit + request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkReceive ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + UINTN MediaAddrSize; + UINT8 ProtType; + + if (This == NULL || BufferSize == NULL || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + + Status = Undi16SimpleNetworkIsr ( + This, + BufferSize, + HeaderSize, + Buffer, + &ProtType, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) { + return EFI_NOT_READY; + + } + + SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + + MediaAddrSize = This->Mode->HwAddressSize; + + if (SrcAddr != NULL) { + CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize); + } + + if (DestAddr != NULL) { + CopyMem (DestAddr, Buffer, MediaAddrSize); + } + + if (Protocol != NULL) { + *((UINT8 *) Protocol) = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1); + *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize)); + } + + DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d HeaderSize = %d\n", *BufferSize, *HeaderSize)); + + return Status; + +} +// +// WaitForPacket() +// +/** + wait for a packet to be received. + + @param Event Event used with WaitForEvent() to wait for a packet to be received. + @param Context Event Context + +**/ +VOID +EFIAPI +Undi16SimpleNetworkWaitForPacket ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Someone is waiting on the receive packet event, if there's + // a packet pending, signal the event + // + if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) { + gBS->SignalEvent (Event); + } +} +// +// CheckForPacket() +// +/** + Check whether packet is ready for receive. + + @param This The protocol instance pointer. + + @retval EFI_SUCCESS Receive data is ready. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit + request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. +**/ +EFI_STATUS +Undi16SimpleNetworkCheckForPacket ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; + UINTN FrameLength; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (SimpleNetworkDevice == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Verify that the current state of the adapter is valid for this call. + // + switch (SimpleNetworkDevice->SimpleNetworkMode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + default: + return EFI_DEVICE_ERROR; + } + + FrameLength = 0; + Status = Undi16SimpleNetworkIsr ( + This, + &FrameLength, + NULL, + NULL, + NULL, + NULL + ); + + if (Status != EFI_BUFFER_TOO_SMALL) { + if (EFI_ERROR (Status)) { + return Status; + } + } + + return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY; +} + +/** + Signal handlers for ExitBootServices event. + + Clean up any Real-mode UNDI residue from the system + + @param Event ExitBootServices event + @param Context +**/ +VOID +EFIAPI +Undi16SimpleNetworkEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // NOTE: This is not the only way to effect this cleanup. The prescribed mechanism + // would be to perform an UNDI STOP command. This strategam has been attempted + // but results in problems making some of the EFI core services from TPL_CALLBACK. + // This issue needs to be resolved, but the other alternative has been to perform + // the unchain logic explicitly, as done below. + // + RestoreCachedVectorAddress (0x1A); +} + +/** + Allocate buffer below 1M for real mode. + + @param NumPages The number pages want to be allocated. + @param Buffer On return, allocated buffer. + + @return Status of allocating pages. +**/ +EFI_STATUS +BiosSnp16AllocatePagesBelowOneMb ( + UINTN NumPages, + VOID **Buffer + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + PhysicalAddress = 0x000fffff; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiRuntimeServicesData, + NumPages, + &PhysicalAddress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *Buffer = (VOID *) (UINTN) PhysicalAddress; + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h new file mode 100644 index 0000000000..b29059f685 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h @@ -0,0 +1,1655 @@ +/** @file + +Copyright (c) 1999 - 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 _BIOS_SNP_16_H_ +#define _BIOS_SNP_16_H_ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "Pxe.h" + +// +// BIOS Simple Network Protocol Device Structure +// +#define EFI_SIMPLE_NETWORK_DEV_SIGNATURE SIGNATURE_32 ('s', 'n', '1', '6') + +#define INIT_PXE_STATUS 0xabcd + +#define EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE 64 + +typedef struct { + UINT32 First; + UINT32 Last; + VOID * Data[EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE]; +} EFI_SIMPLE_NETWORK_DEV_FIFO; + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; + EFI_SIMPLE_NETWORK_MODE SimpleNetworkMode; + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL Nii; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + // + // Local Data for Simple Network Protocol interface goes here + // + BOOLEAN UndiLoaded; + EFI_EVENT EfiBootEvent; + EFI_EVENT LegacyBootEvent; + UINT16 PxeEntrySegment; + UINT16 PxeEntryOffset; + EFI_SIMPLE_NETWORK_DEV_FIFO TxBufferFifo; + EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath; + PXE_T *Pxe; ///< Pointer to !PXE structure + PXENV_UNDI_GET_INFORMATION_T GetInformation; ///< Data from GET INFORMATION + PXENV_UNDI_GET_NIC_TYPE_T GetNicType; ///< Data from GET NIC TYPE + PXENV_UNDI_GET_NDIS_INFO_T GetNdisInfo; ///< Data from GET NDIS INFO + BOOLEAN IsrValid; ///< TRUE if Isr contains valid data + PXENV_UNDI_ISR_T Isr; ///< Data from ISR + PXENV_UNDI_TBD_T *Xmit; // + VOID *TxRealModeMediaHeader; ///< < 1 MB Size = 0x100 + VOID *TxRealModeDataBuffer; ///< < 1 MB Size = GetInformation.MaxTranUnit + VOID *TxDestAddr; ///< < 1 MB Size = 16 + UINT8 InterruptStatus; ///< returned/cleared by GetStatus, set in ISR + UINTN UndiLoaderTablePages; + UINTN DestinationDataSegmentPages; + UINTN DestinationStackSegmentPages; + UINTN DestinationCodeSegmentPages; + VOID *UndiLoaderTable; + VOID *DestinationDataSegment; + VOID *DestinationStackSegment; + VOID *DestinationCodeSegment; +} EFI_SIMPLE_NETWORK_DEV; + +#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) \ + CR (a, \ + EFI_SIMPLE_NETWORK_DEV, \ + SimpleNetwork, \ + EFI_SIMPLE_NETWORK_DEV_SIGNATURE \ + ) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2; + + +// +// Driver Binding Protocol functions +// +/** + Tests to see if this driver supports a given controller. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The driver supports given controller. + @retval EFI_UNSUPPORT The driver doesn't support given controller. + @retval Other Other errors prevent driver finishing to test + if the driver supports given controller. +**/ +EFI_STATUS +EFIAPI +BiosSnp16DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +/** + Starts the Snp device controller + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS - The device was started. + @retval EFI_DEVICE_ERROR - The device could not be started due to a device error. + @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +BiosSnp16DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +/** + Stops the device by given device controller. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param Controller The handle of the controller to test. + @param NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param ChildHandleBuffer An array of child handles to be freed. May be NULL if + NumberOfChildren is 0. + + @retval EFI_SUCCESS - The device was stopped. + @retval EFI_DEVICE_ERROR - The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +BiosSnp16DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + +// +// Simple Network Protocol functions +// +/** + Call 16 bit UNDI ROM to start the network interface + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_DEVICE_ERROR Network interface has not be initialized. + @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. + @retval EFI_SUCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkStart ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +; + +/** + Call 16 bit UNDI ROM to stop the network interface + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_DEVICE_ERROR Network interface has not be initialized. + @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. + @retval EFI_SUCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkStop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +; + +/** + Initialize network interface + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param ExtraRxBufferSize The size of extra request receive buffer. + @param ExtraTxBufferSize The size of extra request transmit buffer. + + @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. + @retval EFI_SUCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkInitialize ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL + ) +; + +/** + Reset network interface. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param ExtendedVerification Need extended verfication. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkReset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +/** + Shutdown network interface. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkShutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +; + +/** + Reset network interface. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param Enable Enable mask value + @param Disable Disable mask value + @param ResetMCastFilter Whether reset multi cast filter or not + @param MCastFilterCnt Count of mutli cast filter for different MAC address + @param MCastFilter Buffer for mustli cast filter for different MAC address. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkReceiveFilters ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL + ) +; + +/** + Set new MAC address. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param Reset Whether reset station MAC address to permenent address + @param New A pointer to New address + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkStationAddress ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS * New OPTIONAL + ) +; + +/** + Collect statistics. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param Reset Whether cleanup old statistics data. + @param StatisticsSize The buffer of statistics table. + @param StatisticsTable A pointer to statistics buffer. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkStatistics ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL + ) +; + +/** + Translate IP address to MAC address. + + @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. + @param IPv6 IPv6 or IPv4 + @param IP A pointer to given Ip address. + @param MAC On return, translated MAC address. + + @retval EFI_INVALID_PARAMETER Invalid This paramter. + @retval EFI_INVALID_PARAMETER Invalid IP address. + @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address. + @retval EFI_UNSUPPORTED Do not support IPv6 + @retval EFI_DEVICE_ERROR Network device has not been initialized. + @retval EFI_NOT_STARTED Network device has been stopped. + @retval EFI_DEVICE_ERROR Invalid status for network device + @retval EFI_SUCCESS Success operation. +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkMCastIpToMac ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ) +; + +/** + Performs read and write operations on the NVRAM device attached to a + network interface. + + @param This The protocol instance pointer. + @param ReadWrite TRUE for read operations, FALSE for write operations. + @param Offset Byte offset in the NVRAM device at which to start the read or + write operation. This must be a multiple of NvRamAccessSize and + less than NvRamSize. + @param BufferSize The number of bytes to read or write from the NVRAM device. + This must also be a multiple of NvramAccessSize. + @param Buffer A pointer to the data buffer. + + @retval EFI_SUCCESS The NVRAM access was performed. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkNvData ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN Write, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ) +; + +/** + Reads the current interrupt status and recycled transmit buffer status from + a network interface. + + @param This The protocol instance pointer. + @param InterruptStatus A pointer to the bit mask of the currently active interrupts + If this is NULL, the interrupt status will not be read from + the device. If this is not NULL, the interrupt status will + be read from the device. When the interrupt status is read, + it will also be cleared. Clearing the transmit interrupt + does not empty the recycled transmit buffer array. + @param TxBuf Recycled transmit buffer address. The network interface will + not transmit if its internal recycled transmit buffer array + is full. Reading the transmit buffer does not clear the + transmit interrupt. If this is NULL, then the transmit buffer + status will not be read. If there are no transmit buffers to + recycle and TxBuf is not NULL, * TxBuf will be set to NULL. + + @retval EFI_SUCCESS The status of the network interface was retrieved. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkGetStatus ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * This, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL + ) +; + +/** + Places a packet in the transmit queue of a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then it + must be equal to This->Mode->MediaHeaderSize and the DestAddr + and Protocol parameters must not be NULL. + @param BufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param Buffer A pointer to the packet (media header followed by data) to be + transmitted. This parameter cannot be NULL. If HeaderSize is zero, + then the media header in Buffer must already be filled in by the + caller. If HeaderSize is non-zero, then the media header will be + filled in by the Transmit() function. + @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter + is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then + This->Mode->CurrentAddress is used for the source HW MAC address. + @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this + parameter is ignored. + @param Protocol The type of header to build. If HeaderSize is zero, then this + parameter is ignored. See RFC 1700, section "Ether Types", for + examples. + + @retval EFI_SUCCESS The packet was placed on the transmit queue. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkTransmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *Protocol OPTIONAL + ) +; + +/** + Receives a packet from a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header received on the network + interface. If this parameter is NULL, then the media header size + will not be returned. + @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in + bytes, of the packet that was received on the network interface. + @param Buffer A pointer to the data buffer to receive both the media header and + the data. + @param SrcAddr The source HW MAC address. If this parameter is NULL, the + HW MAC source address will not be extracted from the media + header. + @param DestAddr The destination HW MAC address. If this parameter is NULL, + the HW MAC destination address will not be extracted from the + media header. + @param Protocol The media header type. If this parameter is NULL, then the + protocol will not be extracted from the media header. See + RFC 1700 section "Ether Types" for examples. + + @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has + been updated to the number of bytes received. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit + request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EFIAPI +Undi16SimpleNetworkReceive ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL + ) +; + +/** + wait for a packet to be received. + + @param Event Event used with WaitForEvent() to wait for a packet to be received. + @param Context Event Context + +**/ +VOID +EFIAPI +Undi16SimpleNetworkWaitForPacket ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +/** + Check whether packet is ready for receive. + + @param This The protocol instance pointer. + + @retval EFI_SUCCESS Receive data is ready. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit + request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. +**/ +EFI_STATUS +Undi16SimpleNetworkCheckForPacket ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +; + +/** + Cache Interrupt verctor address converted from IVT number. + + @param VectorNumber IVT number + + @retval EFI_SUCCESS Success to operation. +**/ +EFI_STATUS +CacheVectorAddress ( + UINT8 VectorNumber + ) +; + +/** + Get interrupt vector address according to IVT number. + + @param VectorNumber Given IVT number + + @return cached interrupt vector address. +**/ +EFI_STATUS +RestoreCachedVectorAddress ( + UINT8 VectorNumber + ) +; + +/** + If available, launch the BaseCode from a NIC option ROM. + This should install the !PXE and PXENV+ structures in memory for + subsequent use. + + + @param SimpleNetworkDevice Simple network device instance + @param RomAddress The ROM base address for NIC rom. + + @retval EFI_NOT_FOUND The check sum does not match + @retval EFI_NOT_FOUND Rom ID offset is wrong + @retval EFI_NOT_FOUND No Rom ID structure is found +**/ +EFI_STATUS +LaunchBaseCode ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + UINTN RomAddress + ) +; + +/** + PXE + START UNDI + Op-Code: PXENV_START_UNDI (0000h) + Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is + responsible for saving the information it needs to communicate with the hardware. + This service is also responsible for hooking the Int 1Ah service routine + Note: This API service must be called only once during UNDI Option ROM boot. + The UNDI driver is responsible for saving this information and using it every time + PXENV_UNDI_STARTUP is called. + Service cannot be used in protected mode. + typedef struct { + PXENV_STATUS Status; + UINT16 AX; + UINT16 BX; + UINT16 DX; + UINT16 DI; + UINT16 ES; + } PXENV_START_UNDI_T; + Set before calling API service + AX, BX, DX, DI, ES: BIOS initialization parameter registers. These + fields should contain the same information passed to the option ROM + initialization routine by the Host System BIOS. Information about the + contents of these registers can be found in the [PnP], [PCI] and + [BBS] specifications. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeStartUndi ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_START_UNDI_T *PxeUndiTable + ) +; + +/** + PXE + UNDI STARTUP + Op-Code: PXENV_UNDI_STARTUP (0001h) + Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the + caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper + operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used + to complete this initialization. The rest of the UNDI APIs will not be available until this call has + been completed. + Note: PXENV_UNDI_STARTUP must not be called again without first calling + PXENV_UNDI_SHUTDOWN. + PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for + chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and + PXENV_STOP_UNDI API calls. + This service cannot be used in protected mode. + typedef struct + { + PXENV_STATUS Status; + } PXENV_UNDI_STARTUP_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiStartup ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable + ) +; + +/** + PXE + UNDI CLEANUP + Op-Code: PXENV_UNDI_CLEANUP (0002h) + Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field + in the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be + made just before unloading the Universal NIC Driver. The rest of the API will not be available + after this call executes. + This service cannot be used in protected mode. + typedef struct { + PXENX_STATUS Status; + } PXENV_UNDI_CLEANUP_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiCleanup ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable + ) +; + +/** + PXE + UNDI INITIALIZE + Op-Code: PXENV_UNDI_INITIALIZE (0003h) + Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the + caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call resets the adapter and programs it with default parameters. The default parameters used + are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the + receive and transmit units of the network adapter to readily receive or transmit packets. The + application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network. + This call must be made by an application to establish an interface to the network adapter driver. + Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for + the Protocol field in the parameter structure. + typedef struct { + PXENV_STATUS Status; + ADDR32 ProtocolIni; + UINT8 reserved[8]; + } PXENV_UNDI_INITIALIZE_T; + Set before calling API service + ProtocolIni: Physical address of a memory copy of the driver + module from the protocol.ini file obtained from the protocol manager + driver (refer to the NDIS 2.0 specification). This parameter is + supported for the universal NDIS driver to pass the information + contained in the protocol.ini file to the NIC driver for any specific + configuration of the NIC. (Note that the module identification in the + protocol.ini file was done by NDIS.) This value can be NULL for any + other application interfacing to the universal NIC driver + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance. + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiInitialize ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable + ) +; + +/** + Wrapper routine for reset adapter. + + PXE + UNDI RESET ADAPTER + Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h) + Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized + by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to + Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the + network. This routine cannot be used to replace Initialize or Shutdown calls. + typedef struct { + PXENV_STATUS Status; + PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; + } PXENV_UNDI_RESET_T; + + #define MAXNUM_MCADDR 8 + + typedef struct { + UINT16 MCastAddrCount; + MAC_ADDR McastAddr[MAXNUM_MCADDR]; + } PXENV_UNDI_MCAST_ADDRESS_t; + + Set before calling API service + R_Mcast_Buf: This is a structure of MCastAddrCount and + McastAddr. + MCastAddrCount: Number of multicast MAC addresses in the + buffer. + McastAddr: List of up to MAXNUM_MCADDR multicast MAC + addresses. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance. + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + @param RxFilter Filter setting mask value for PXE recive . + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiResetNic ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_RESET_T *PxeUndiTable, + IN UINT16 RxFilter + ) +; + +/** + PXE + UNDI SHUTDOWN + Op-Code: PXENV_UNDI_SHUTDOWN (0005h) + Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call resets the network adapter and leaves it in a safe state for another driver to program it. + Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the + Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again. + typedef struct + { + PXENV_STATUS Status; + } PXENV_UNDI_SHUTDOWN_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiShutdown ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable + ) +; + +/** + PXE + UNDI OPEN + Op-Code: PXENV_UNDI_OPEN (0006h) + Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call activates the adapter network connection and sets the adapter ready to accept packets + for transmit and receive. + typedef struct { + PXENV_STATUS Status; + UINT16 OpenFlag; + UINT16 PktFilter; + #define FLTR_DIRECTED 0x0001 + #define FLTR_BRDCST 0x0002 + #define FLTR_PRMSCS 0x0004 + #define FLTR_SRC_RTG 0x0008 + PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; + } PXENV_UNDI_OPEN_T; + Set before calling API service + OpenFlag: This is an adapter specific input parameter. This is + supported for the universal NDIS 2.0 driver to pass in the open flags + provided by the protocol driver. (See the NDIS 2.0 specification.) + This can be zero. + PktFilter: Filter for receiving packets. This can be one, or more, of + the FLTR_xxx constants. Multiple values are arithmetically or-ed + together. + directed packets are packets that may come to your MAC address + or the multicast MAC address. + R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h). + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiOpen ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable + ) +; + +/** + PXE + UNDI CLOSE + Op-Code: PXENV_UNDI_CLOSE (0007h) + Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or + received until the network adapter is open again. + typedef struct { + PXENV_STATUS Status; + } PXENV_UNDI_CLOSE_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiClose ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable + ) +; + +/** + PXE + UNDI TRANSMIT PACKET + Op-Code: PXENV_UNDI_TRANSMIT (0008h) + Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that + has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. + The status code must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call transmits a buffer to the network. The media header + for the packet can be filled by the calling protocol, but it might not be. + The network adapter driver will fill it if required by the values in the + parameter block. The packet is buffered for transmission provided there is + an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no + buffer is available the function returns PXENV_EXIT_FAILURE with a status + code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is + implementation-dependent. An interrupt is generated on completion of the + transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is + permitted in the context of a transmit complete interrupt. + + typedef struct { + PXENV_STATUS Status; + UINT8 Protocol; + #define P_UNKNOWN 0 + #define P_IP 1 + #define P_ARP 2 + #define P_RARP 3 + UINT8 XmitFlag; + #define XMT_DESTADDR 0x0000 + #define XMT_BROADCAST 0x0001 + SEGOFF16 DestAddr; + SEGOFF16 TBD; + UINT32 Reserved[2]; + } t_PXENV_UNDI_TRANSMIT; + + #define MAX_DATA_BLKS 8 + + typedef struct { + UINT16 ImmedLength; + SEGOFF16 Xmit; + UINT16 DataBlkCount; + struct DataBlk { + UINT8 TDPtrType; + UINT8 TDRsvdByte; + UINT16 TDDataLen; + SEGOFF16 TDDataPtr; + } DataBlock[MAX_DATA_BLKS]; + } PXENV_UNDI_TBD_T + + Set before calling API service + Protocol: This is the protocol of the upper layer that is calling UNDI + TRANSMIT call. If the upper layer has filled the media header, this + field must be P_UNKNOWN. + XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a + pointer to the destination media address in the field DestAddr. If + XMT_BROADCAST, the NIC driver fills the broadcast address for the + destination. + TBD: Segment:Offset address of the transmit buffer descriptor. + ImmedLength: Length of the immediate transmit buffer: Xmit. + Xmit: Segment:Offset of the immediate transmit buffer. + DataBlkCount: Number of blocks in this transmit buffer. + TDPtrType: + 0 => 32-bit physical address in TDDataPtr (not supported in this + version of PXE) + 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit + protected mode pointer + TDRsvdByte: Reserved must be zero. + TDDatalen: Data block length in bytes. + TDDataPtr: Segment:Offset of the transmit block. + DataBlock: Array of transmit data blocks. + Returned from API service + Status: See the PXENV_STATUS_xxx constants + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiTransmit ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable + ) +; + +/** + PXE + UNDI SET MULTICAST ADDRESS + Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h) + Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call changes the current list of multicast addresses to the input list and resets the network + adapter to accept it. If the number of multicast addresses is zero, multicast is disabled. + typedef struct { + PXENV_STATUS Status; + PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; + } PXENV_UNDI_SET_MCAST_ADDR_T; + Set before calling API service + R_Mcast_Buf: See description in the UNDI RESET ADAPTER + (0004h) API. + Returned from API service + Status: See the PXENV_STATUS_xxx constants + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiSetMcastAddr ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable + ) +; + +/** + PXE + UNDI SET STATION ADDRESS + Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah) + Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call sets the MAC address to be the input value and is called before opening the network + adapter. Later, the open call uses this variable as a temporary MAC address to program the + adapter individual address registers. + typedef struct { + PXENV_STATUS Status; + MAC_ADDR StationAddress; + } PXENV_UNDI_SET_STATION_ADDR_T; + Set before calling API service + StationAddress: Temporary MAC address to be used for + transmit and receive. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiSetStationAddr ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable + ) +; + +/** + PXE + UNDI SET PACKET FILTER + Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh) + Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with + the open call. + typedef struct { + PXENV_STATUS Status; + UINT8 filter; + } PXENV_UNDI_SET_PACKET_FILTER_T; + Set before calling API service + Filter: See the receive filter values in the UNDI OPEN + (0006h) API description. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiSetPacketFilter ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable + ) +; + +/** + PXE + UNDI GET INFORMATION + Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch) + Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call copies the network adapter variables, including the MAC address, into the input buffer. + Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and + PXENV_UNDI_STARTUP have been issued. All other fields must be valid after + PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been + called. + typedef struct { + PXENV_STATUS Status; + UINT16 BaseIo; + UINT16 IntNumber; + UINT16 MaxTranUnit; + UINT16 HwType; + #define ETHER_TYPE 1 + #define EXP_ETHER_TYPE 2 + #define IEEE_TYPE 6 + #define ARCNET_TYPE 7 + UINT16 HwAddrLen; + MAC_ADDR CurrentNodeAddress; + MAC_ADDR PermNodeAddress; + SEGSEL ROMAddress; + UINT16 RxBufCt; + UINT16 TxBufCt; + } PXENV_UNDI_GET_INFORMATION_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + BaseIO: Adapter base I/O address. + IntNumber: Adapter IRQ number. + MaxTranUnit: Adapter maximum transmit unit. + HWType: Type of protocol at the hardware level. + HWAddrLen: Length of the hardware address. + CurrentNodeAddress: Current hardware address. + PermNodeAddress: Permanent hardware address. + ROMAddress: Real mode ROM segment address. + RxBufCnt: Receive queue length. + TxBufCnt: Transmit queue length. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetInformation ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable + ) +; + +/** + PXE + UNDI GET STATISTICS + Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh) + Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized + by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call reads statistical information from the network adapter, and returns. + typedef struct { + PXENV_STATUS Status; + UINT32 XmtGoodFrames; + UINT32 RcvGoodFrames; + UINT32 RcvCRCErrors; + UINT32 RcvResourceErrors; + } PXENV_UNDI_GET_STATISTICS_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + XmtGoodFrames: Number of successful transmissions. + RcvGoodFrames: Number of good frames received. + RcvCRCErrors: Number of frames received with CRC + error. + RcvResourceErrors: Number of frames discarded + because receive queue was full. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetStatistics ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable + ) +; + +/** + PXE + UNDI CLEAR STATISTICS + Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh) + Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call clears the statistical information from the network adapter. + typedef struct { + PXENV_STATUS Status; + } PXENV_UNDI_CLEAR_STATISTICS_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiClearStatistics ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable + ) +; + +/** + PXE + UNDI INITIATE DIAGS + Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh) + Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run + hardware diagnostics and to update its status information. + typedef struct { + PXENV_STATUS Status; + } PXENV_UNDI_INITIATE_DIAGS_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiInitiateDiags ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable + ) +; + +/** + PXE + UNDI FORCE INTERRUPT + Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h) + Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the + network adapter driver usually queues the packet and calls the application's callback receive + routine with a pointer to the packet received. Then, the callback routine either can copy the packet + to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied, + the network adapter driver does not remove it from the input queue. When the application wants to + copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive + interrupt. + typedef struct { + PXENV_STATUS Status; + } PXENV_UNDI_FORCE_INTERRUPT_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiForceInterrupt ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable + ) +; + +/** + PXE + UNDI GET MULTICAST ADDRESS + Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h) + Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized + by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call converts the given IP multicast address to a hardware multicast address. + typedef struct { + PXENV_STATUS Status; + IP4 InetAddr; + MAC_ADDR MediaAddr; + } PXENV_UNDI_GET_MCAST_ADDR_T; + Set before calling API service + InetAddr: IP multicast address. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + MediaAddr: MAC multicast address. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetMcastAddr ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable + ) +; + +/** + PXE + UNDI GET NIC TYPE + Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h) + Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE_T parameter structure that has been initialized by + the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the + NIC information. + Description: This call, if successful, provides the NIC-specific information necessary to identify the network + adapter that is used to boot the system. + Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if + the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific + information can be obtained from the DHCPDISCOVER packet itself. + PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called + before the information provided is valid. + typedef { + PXENV_STATUS Status; + UINT8 NicType; + #define PCI_NIC 2 + #define PnP_NIC 3 + #define CardBus_NIC 4 + Union { + Struct { + UINT16 Vendor_ID; + UINT16 Dev_ID; + UINT8 Base_Class; + UINT8 Sub_Class; + UINT8 Prog_Intf; + UINT8 Rev; + UINT16 BusDevFunc; + UINT16 SubVendor_ID; + UINT16 SubDevice_ID; + } pci, cardbus; + struct { + UINT32 EISA_Dev_ID; + UINT8 Base_Class; + UINT8 Sub_Class; + UINT8 Prog_Intf; + UINT16 CardSelNum; + } pnp; + } info; + } PXENV_UNDI_GET_NIC_TYPE_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + NICType: Type of NIC information stored in the parameter + structure. + Info: Information about the fields in this union can be found + in the [PnP] and [PCI] specifications + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetNicType ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable + ) +; + +/** + PXE + UNDI GET IFACE INFO + Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h) + Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized + by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the + interface specific information. + Description: This call, if successful, provides the network interface specific information such as the interface + type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the + universal drivers such as NDIS or Miniport to communicate to the upper protocol modules. + Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the + universal driver to translate/convert this information into a format that is required in its specification + or to suit the expectation of the upper level protocol modules. + PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called + before the information provided is valid. + typedef struct { + PXENV_STATUS Status + UINT8 IfaceType[16]; + UINT32 LinkSpeed; + UINT32 ServiceFlags; + UINT32 Reserved[4]; + } PXENV_UNDI_GET_NDIS_INFO_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + IfaceType: Name of MAC type in ASCIIZ format. This is + used by the universal NDIS driver to specify its driver type + to the protocol driver. + LinkSpeed: Defined in the NDIS 2.0 specification. + ServiceFlags: Defined in the NDIS 2.0 specification. + Reserved: Must be zero. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetNdisInfo ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable + ) +; + +/** + PXE + UNDI ISR + Op-Code: PXENV_UNDI_ISR (0014h) + Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in + the parameter block indicates the operation to be performed for the call. This field is filled with the + status of that operation on return. + Note: Interrupt Service Routine Operation: + In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the + application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR + API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing + (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT). + When the Network Interface HW generates an interrupt the protocol driver interrupt service + routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then + calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for + the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface + level and read any status values required to further process the interrupt. UNDI must return as + quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or + PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the + interrupt was generated by this particular Network Interface or not. + If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was + not generated by our NIC, and interrupt processing is complete. + If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start + a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is + now complete. + The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to + PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and + return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the + first buffer pointer of that frame in the parameter block. + The protocol driver calls UNDI repeatedly with the FuncFlag equal to + PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received + frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l + remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous + buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter + block. Otherwise it must return the first buffer in the next frame. + If there is no received frame pending to be processed, UNDI processes the transmit completes and + if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the + NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag. + IMPORTANT: It is possible for the protocol driver to be interrupted again while in the + strategy routine when the UNDI re-enables interrupts. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiIsr ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_ISR_T *PxeUndiTable + ) +; + +/** + PXE + STOP UNDI + Op-Code: PXENV_STOP_UNDI (0015h) + Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This routine is responsible for unhooking the Int 1Ah service routine. + Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid + status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from + base memory. Also, UNDI must not be removed from base memory if BC is not removed from base + memory. + Service cannot be used in protected mode. + typedef struct { + PXENV_STATUS Status; + } PXENV_STOP_UNDI_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiStop ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_STOP_UNDI_T *PxeUndiTable + ) +; + +/** + PXE + UNDI GET STATE + Op-Code: PXENV_UNDI_GET_STATE (0015h) + Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state + constants + Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call + sequences + typedef struct { + #define PXE_UNDI_GET_STATE_STARTED 1 + #define PXE_UNDI_GET_STATE_INITIALIZED 2 + #define PXE_UNDI_GET_STATE_OPENED 3 + PXENV_STATUS Status; + UINT8 UNDIstate; + } PXENV_UNDI_GET_STATE_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + State: See definitions of the state constants. + Note. UNDI implementation is responsible for maintaining + internal state machine. + UNDI ISR + Op-Code: PXENV_UNDI_ISR (0014h) + Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in + the parameter block indicates the operation to be performed for the call. This field is filled with the + status of that operation on return. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetState ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable + ) +; + +/** + Effect the Far Call into the PXE Layer + + Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API + services will not work, unless there are three 16-bit parameters pushed onto the stack. + push DS ;Far pointer to parameter structure + push offset pxe_data_call_struct ;is pushed onto stack. + push Index ;UINT16 is pushed onto stack. + call dword ptr (s_PXE ptr es:[di]).EntryPointSP + add sp, 6 ;Caller cleans up stack. + + @param SimpleNetworkDevice Device instance for simple network + @param Table Point to parameter/retun value table for legacy far call + @param TableSize The size of paramter/return value table + @param CallIndex The index of legacy call. + + @return EFI_STATUS +**/ +EFI_STATUS +MakePxeCall ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT VOID *Table, + IN UINTN TableSize, + IN UINT16 CallIndex + ) +; + +/** + Allocate buffer below 1M for real mode. + + @param NumPages The number pages want to be allocated. + @param Buffer On return, allocated buffer. + + @return Status of allocating pages. +**/ +EFI_STATUS +BiosSnp16AllocatePagesBelowOneMb ( + UINTN NumPages, + VOID **Buffer + ) +; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni new file mode 100644 index 0000000000..7bfc6abbc4 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni new file mode 100644 index 0000000000..273cbec3a0 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c new file mode 100644 index 0000000000..488c597517 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c @@ -0,0 +1,309 @@ +/** @file + +Copyright (c) 1999 - 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 "BiosSnp16.h" + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosSnp16ComponentNameGetDriverName ( + 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 +BiosSnp16ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName = { + BiosSnp16ComponentNameGetDriverName, + BiosSnp16ComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosSnp16ComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosSnp16ComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosSnp16DriverNameTable[] = { + { + "eng;en", + L"BIOS[UNDI] Simple Network Protocol Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosSnp16ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mBiosSnp16DriverNameTable, + DriverName, + (BOOLEAN)(This == &gBiosSnp16ComponentName) + ); +} + +/** + 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 +BiosSnp16ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c new file mode 100644 index 0000000000..243048c551 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c @@ -0,0 +1,962 @@ +/** @file + Helper Routines that use a PXE-enabled NIC option ROM. + +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 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 "BiosSnp16.h" + +#define TO_SEGMENT(x) ((UINT16) (RShiftU64 ((UINT32)(UINTN) (x), 4) & 0xF000)) +#define TO_OFFSET(x) ((UINT16) ((UINT32)(UINTN) (x) & 0xFFFF)) +#define PARAGRAPH_SIZE 0x10 +#define IVT_BASE 0x00000000 + +#pragma pack(1) +typedef struct { + UINT16 Signature; ///< 0xaa55 + UINT8 ROMlength; ///< size of this ROM in 512 byte blocks + UINT8 InitEntryPoint[4]; ///< a jump to the initialization routine + UINT8 Reserved[0xf]; ///< various + UINT16 PxeRomIdOffset; ///< offset of UNDI, $BC$, or BUSD ROM ID structure + UINT16 PcirHeaderOffset; ///< offset of PCI Expansion Header + UINT16 PnpHeaderOffset; ///< offset of Plug and Play Expansion Header +} OPTION_ROM_HEADER; +#pragma pack() + +UINT32 CachedVectorAddress[0x100]; + +/** + Cache Interrupt verctor address converted from IVT number. + + @param VectorNumber IVT number + + @retval EFI_SUCCESS Success to operation. +**/ +EFI_STATUS +CacheVectorAddress ( + UINT8 VectorNumber + ) +{ + UINT32 *Address; + + Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4); + CachedVectorAddress[VectorNumber] = *Address; + return EFI_SUCCESS; +} + +/** + Get interrupt vector address according to IVT number. + + @param VectorNumber Given IVT number + + @return cached interrupt vector address. +**/ +EFI_STATUS +RestoreCachedVectorAddress ( + UINT8 VectorNumber + ) +{ + UINT32 *Address; + + Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4); + *Address = CachedVectorAddress[VectorNumber]; + return EFI_SUCCESS; +} + +/** + Print Undi loader table. + + @param UndiLoaderStructure Point to Undi Loader table structure. + +**/ +VOID +Print_Undi_Loader_Table ( + VOID *UndiLoaderStructure + ) +{ + UNDI_LOADER_T *DisplayPointer; + + DisplayPointer = (UNDI_LOADER_T *) UndiLoaderStructure; + + DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n")); + DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) UndiLoaderStructure)); + + DEBUG ((DEBUG_NET, "\n\rStatus = 0x%X\n\r", DisplayPointer->Status)); + DEBUG ((DEBUG_NET, "\t_AX_= 0x%X\n\r", DisplayPointer->Ax)); + DEBUG ((DEBUG_NET, "\t_BX_= 0x%X\n\r", DisplayPointer->Bx)); + DEBUG ((DEBUG_NET, "\t_DX_= 0x%X\n\r", DisplayPointer->Dx)); + DEBUG ((DEBUG_NET, "\t_DI_= 0x%X\n\r", DisplayPointer->Di)); + DEBUG ((DEBUG_NET, "\t_ES_= 0x%X\n\r", DisplayPointer->Es)); + DEBUG ((DEBUG_NET, "\tUNDI_DS= 0x%X\n\r", DisplayPointer->Undi_Ds)); + DEBUG ((DEBUG_NET, "\tUNDI_CS= 0x%X\n\r", DisplayPointer->Undi_Cs)); + DEBUG ((DEBUG_NET, "\tPXEptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Segment)); + DEBUG ((DEBUG_NET, "\tPXEptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Offset)); + DEBUG ((DEBUG_NET, "\tPXENVptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Segment)); + DEBUG ((DEBUG_NET, "\tPXENVptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Offset)); +} + +/** + Simple table dumper. The ROMID table is necessary in order to effect + the "Early UNDI" trick. Herein, the UNDI layer can be loaded in the + pre-boot phase without having to download a Network Boot Program + across the wire. It is required in the implementation in that we + are not using PXE. + + @param RomIDStructure Point to RomID structure. + +**/ +VOID +Print_ROMID_Table ( + IN VOID *RomIDStructure + ) +{ + UNDI_ROMID_T *DisplayPointer; + + DisplayPointer = (UNDI_ROMID_T *) RomIDStructure; + + DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n")); + DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) RomIDStructure)); + + DEBUG ( + (DEBUG_NET, + "\n\rROMID %c%c%c%c\n\r", + DisplayPointer->Signature[0], + DisplayPointer->Signature[1], + DisplayPointer->Signature[2], + DisplayPointer->Signature[3]) + ); + + DEBUG ( + (DEBUG_NET, + "Length of this structure in bytes = 0x%X\n\r", + DisplayPointer->StructLength) + ); + DEBUG ( + (DEBUG_NET, + "Use to make byte checksum of this structure == zero is = 0x%X\n\r", + DisplayPointer->StructCksum) + ); + DEBUG ( + (DEBUG_NET, + "Structure format revision number= 0x%X\n\r", + DisplayPointer->StructRev) + ); + DEBUG ( + (DEBUG_NET, + "API Revision number = 0x%X 0x%X 0x%X\n\r", + DisplayPointer->UNDI_Rev[0], + DisplayPointer->UNDI_Rev[1], + DisplayPointer->UNDI_Rev[2]) + ); + DEBUG ( + (DEBUG_NET, + "Offset of UNDI loader routine in the option ROM image= 0x%X\n\r", + DisplayPointer->UNDI_Loader) + ); + DEBUG ((DEBUG_NET, "From the data above, the absolute entry point of the UNDI loader is\n\r")); + DEBUG ( + (DEBUG_NET, + "\tat address 0x%X\n\r", + (UINT32) (DisplayPointer->UNDI_Loader + ((UINT32) (UINTN)(DisplayPointer - 0x20) & 0xFFFF0))) + ); + DEBUG ((DEBUG_NET, "Minimum stack segment size, in bytes,\n\r")); + DEBUG ( + (DEBUG_NET, + "needed to load and run the UNDI= 0x%X \n\r", + DisplayPointer->StackSize) + ); + DEBUG ( + (DEBUG_NET, + "UNDI runtime code and data = 0x%X\n\r", + DisplayPointer->DataSize) + ); + DEBUG ( + (DEBUG_NET, + "Segment size = 0x%X\n\r", + DisplayPointer->CodeSize) + ); + DEBUG ( + (DEBUG_NET, + "\n\rBus Type = %c%c%c%c\n\r", + DisplayPointer->BusType[0], + DisplayPointer->BusType[1], + DisplayPointer->BusType[2], + DisplayPointer->BusType[3]) + ); +} + +/** + Print PXE table. + + @param PxeTable Point to PXE table structure + +**/ +VOID +Print_PXE_Table ( + IN VOID* PxeTable + ) +{ + PXE_T *DisplayPointer; + UINTN Index; + UINT8 *Dptr; + + DisplayPointer = (PXE_T *) PxeTable; + Dptr = (UINT8 *) PxeTable; + + DEBUG ((DEBUG_NET, "This is the PXE table at address 0x%X\n\r", PxeTable)); + + DEBUG ((DEBUG_NET, "A dump of the 0x%X bytes is:\n\r", sizeof (PXE_T))); + + for (Index = 0; Index < sizeof (PXE_T); Index++) { + if ((Index % 0x10) == 0) { + DEBUG ((DEBUG_NET, "\t\n\r")); + } + + DEBUG ((DEBUG_NET, " 0x%X ", *Dptr++)); + } + + DEBUG ((DEBUG_NET, "\n\r")); + DEBUG ( + (DEBUG_NET, + "\n\rPXE %c%c%c%c%c%c\n\r", + DisplayPointer->Signature[0], + DisplayPointer->Signature[1], + DisplayPointer->Signature[2], + DisplayPointer->Signature[3]) + ); + DEBUG ( + (DEBUG_NET, + "Length of this structure in bytes = 0x%X\n\r", + DisplayPointer->StructLength) + ); + DEBUG ( + (DEBUG_NET, + "Use to make byte checksum of this structure == zero is = 0x%X\n\r", + DisplayPointer->StructCksum) + ); + DEBUG ( + (DEBUG_NET, + "Structure format revision number = 0x%X\n\r", + DisplayPointer->StructRev) + ); + DEBUG ( + (DEBUG_NET, + "Must be zero, is equal to 0x%X\n\r", + DisplayPointer->Reserved1) + ); + DEBUG ( + (DEBUG_NET, + "Far pointer to UNDI ROMID = 0x%X\n\r", + (UINT32) (DisplayPointer->Undi.Segment << 0x4 | DisplayPointer->Undi.Offset)) + ); + DEBUG ( + (DEBUG_NET, + "Far pointer to base-code ROMID = 0x%X\n\r", + (UINT32) ((DisplayPointer->Base.Segment << 0x04) | DisplayPointer->Base.Offset)) + ); + DEBUG ((DEBUG_NET, "16bit stack segment API entry point. This will be seg:off in \n\r")); + DEBUG ( + (DEBUG_NET, + "real mode and sel:off in 16:16 protected mode = 0x%X:0x%X\n\r", + DisplayPointer->EntryPointSP.Segment, + DisplayPointer->EntryPointSP.Offset) + ); + + DEBUG ((DEBUG_NET, "\n\tNOTE to the implementer\n\tThis is the entry to use for call-ins\n\r")); + + DEBUG ((DEBUG_NET, "32bit stack Segment API entry point. This will be sel:off. \n\r")); + DEBUG ( + (DEBUG_NET, + "In real mode, sel == 0 = 0x%X:0x%X\n\r", + DisplayPointer->EntryPointESP.Segment, + DisplayPointer->EntryPointESP.Offset) + ); + DEBUG ( + (DEBUG_NET, + "Reserved2 value, must be zero, is equal to 0x%X\n\r", + DisplayPointer->Reserved2) + ); + DEBUG ( + (DEBUG_NET, + "Number of segment descriptors in this structur = 0x%X\n\r", + (UINT8) DisplayPointer->SegDescCnt) + ); + DEBUG ( + (DEBUG_NET, + "First segment descriptor in GDT assigned to PXE = 0x%X\n\r", + (UINT16) DisplayPointer->FirstSelector) + ); + DEBUG ( + (DEBUG_NET, + "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", + (UINT16) DisplayPointer->Stack.Seg_Addr, + (UINT32) DisplayPointer->Stack.Phy_Addr, + (UINT16) DisplayPointer->Stack.Seg_Size) + ); + DEBUG ( + (DEBUG_NET, + "The UNDIData is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", + (UINT16) DisplayPointer->UNDIData.Seg_Addr, + (UINT32) DisplayPointer->UNDIData.Phy_Addr, + (UINT16) DisplayPointer->UNDIData.Seg_Size) + ); + DEBUG ( + (DEBUG_NET, + "The UNDICodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", + (UINT16) DisplayPointer->UNDICode.Seg_Addr, + (UINT32) DisplayPointer->UNDICode.Phy_Addr, + (UINT16) DisplayPointer->UNDICode.Seg_Size) + ); + DEBUG ( + (DEBUG_NET, + "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", + (UINT16) DisplayPointer->UNDICodeWrite.Seg_Addr, + (UINT32) DisplayPointer->UNDICodeWrite.Phy_Addr, + (UINT16) DisplayPointer->UNDICodeWrite.Seg_Size) + ); + DEBUG ( + (DEBUG_NET, + "The BC_Data is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", + (UINT16) DisplayPointer->BC_Data.Seg_Addr, + (UINT32) DisplayPointer->BC_Data.Phy_Addr, + (UINT16) DisplayPointer->BC_Data.Seg_Size) + ); + DEBUG ( + (DEBUG_NET, + "The BC_Code is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", + (UINT16) DisplayPointer->BC_Code.Seg_Addr, + (UINT32) DisplayPointer->BC_Code.Phy_Addr, + (UINT16) DisplayPointer->BC_Code.Seg_Size) + ); + DEBUG ( + (DEBUG_NET, + "The BC_CodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", + (UINT16) DisplayPointer->BC_CodeWrite.Seg_Addr, + (UINT32) DisplayPointer->BC_CodeWrite.Phy_Addr, + (UINT16) DisplayPointer->BC_CodeWrite.Seg_Size) + ); +} + +/** + Print PXENV table. + + @param PxenvTable Point to PXENV + +**/ +VOID +Print_PXENV_Table ( + IN VOID *PxenvTable + ) +{ + PXENV_T *DisplayPointer; + + DisplayPointer = (PXENV_T *) PxenvTable; + + DEBUG ( + (DEBUG_NET, + "\n\rPXENV+ %c%c%c%c%c%c\n\r", + DisplayPointer->Signature[0], + DisplayPointer->Signature[1], + DisplayPointer->Signature[2], + DisplayPointer->Signature[3], + DisplayPointer->Signature[4], + DisplayPointer->Signature[5]) + ); + + DEBUG ( + (DEBUG_NET, + "PXE version number. \n\r\tLSB is minor version. \n\r\tMSB is major version = 0x%X\n\r", + DisplayPointer->Version) + ); + DEBUG ( + (DEBUG_NET, + "Length of PXE-2.0 Entry Point structure in bytes = 0x%X\n\r", + DisplayPointer->StructLength) + ); + DEBUG ((DEBUG_NET, "Used to make structure checksum equal zero is now = 0x%X\n\r", DisplayPointer->StructCksum)); + DEBUG ((DEBUG_NET, "Real mode API entry point segment:Offset. = 0x%X\n\r", DisplayPointer->RMEntry)); + DEBUG ((DEBUG_NET, "Protected mode API entry point = 0x%X\n\r", DisplayPointer->PMEntryOff)); + DEBUG ((DEBUG_NET, " segment:Offset. This will always be zero. \n\r")); + DEBUG ((DEBUG_NET, "Protected mode API calls = 0x%X\n\r", DisplayPointer->PMEntrySeg)); + DEBUG ((DEBUG_NET, "Real mode stack segment = 0x%X\n\r", DisplayPointer->StackSeg)); + DEBUG ((DEBUG_NET, "Stack segment size in bytes = 0x%X\n\r", DisplayPointer->StackSize)); + DEBUG ((DEBUG_NET, "Real mode base-code code segment = 0x%X\n\r", DisplayPointer->BaseCodeSeg)); + DEBUG ((DEBUG_NET, "Base-code code segment size = 0x%X\n\r", DisplayPointer->BaseCodeSize)); + DEBUG ((DEBUG_NET, "Real mode base-code data segment = 0x%X\n\r", DisplayPointer->BaseDataSeg)); + DEBUG ((DEBUG_NET, "Base-code data segment size = 0x%X\n\r", DisplayPointer->BaseDataSize)); + + DEBUG ( + (DEBUG_NET, + "UNDI code segment size in bytes = 0x%X\n\r", + DisplayPointer->UNDICodeSize) + ); + DEBUG ( + (DEBUG_NET, + "Real mode segment:Offset pointer \n\r\tto PXE Runtime ID structure, address = 0x%X\n\r", + DisplayPointer->RuntimePtr) + ); + DEBUG ( + ( + DEBUG_NET, + "From above, we have a linear address of 0x%X\n\r", + (UINT32) + ( + ((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF) + + (((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF0000) >> 12) + ) + ) + ); +} + + +#define OPTION_ROM_PTR ((OPTION_ROM_HEADER *) RomAddress) + +/** + If available, launch the BaseCode from a NIC option ROM. + This should install the !PXE and PXENV+ structures in memory for + subsequent use. + + + @param SimpleNetworkDevice Simple network device instance + @param RomAddress The ROM base address for NIC rom. + + @retval EFI_NOT_FOUND The check sum does not match + @retval EFI_NOT_FOUND Rom ID offset is wrong + @retval EFI_NOT_FOUND No Rom ID structure is found +**/ +EFI_STATUS +LaunchBaseCode ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + UINTN RomAddress + ) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET InOutRegs; + UNDI_ROMID_T *RomIdTableAddress; + UNDI_LOADER_T *UndiLoaderTable; + UINT16 Segment; + UINT16 *StackPointer; + VOID *Buffer; + UINTN Size; + PXE_T *Pxe; + UINT32 RomLength; + UINTN PciSegment; + UINTN Bus; + UINTN Device; + UINTN Function; + BOOLEAN ThunkFailed; + + DEBUG ((DEBUG_NET, "\n\r\n\rCheck for the UNDI ROMID Signature\n\r")); + + // + // paranoia - check structures for validity + // + RomLength = OPTION_ROM_PTR->ROMlength << 9; + if (CalculateSum8 ((UINT8 *) RomAddress, RomLength) != 0) { + DEBUG ((DEBUG_ERROR, "ROM Header Checksum Error\n\r")); + return EFI_NOT_FOUND; + } + + RomIdTableAddress = (UNDI_ROMID_T *) (RomAddress + OPTION_ROM_PTR->PxeRomIdOffset); + + if ((UINTN) (OPTION_ROM_PTR->PxeRomIdOffset + RomIdTableAddress->StructLength) > RomLength) { + DEBUG ((DEBUG_ERROR, "ROM ID Offset Error\n\r")); + return EFI_NOT_FOUND; + } + // + // see if this is a header for an UNDI ROM ID structure (vs. a $BC$ or BUSD type) + // + if (CompareMem (RomIdTableAddress->Signature, UNDI_ROMID_SIG, sizeof RomIdTableAddress->Signature) != 0) { + DEBUG ((DEBUG_ERROR, "No ROM ID Structure found....\n\r")); + return EFI_NOT_FOUND; + // + // its not - keep looking + // + } + + if (CalculateSum8 ((UINT8 *) RomIdTableAddress, RomIdTableAddress->StructLength) != 0) { + DEBUG ((DEBUG_ERROR, "ROM ID Checksum Error\n\r")); + return EFI_NOT_FOUND; + } + + Print_ROMID_Table (RomIdTableAddress); + + DEBUG ( + (DEBUG_NET, + "The ROM ID is located at 0x%X\n\r", + RomIdTableAddress) + ); + + DEBUG ( + (DEBUG_NET, + "With an UNDI Loader located at 0x%X\n\r", + RomAddress + RomIdTableAddress->UNDI_Loader) + ); + + // + // found an UNDI ROM ID structure + // + SimpleNetworkDevice->Nii.ImageAddr = RomAddress; + SimpleNetworkDevice->Nii.ImageSize = RomLength; + SimpleNetworkDevice->Nii.MajorVer = RomIdTableAddress->UNDI_Rev[2]; + SimpleNetworkDevice->Nii.MinorVer = RomIdTableAddress->UNDI_Rev[1]; + + DEBUG ((DEBUG_NET, "Allocate area for the UNDI_LOADER_T structure\n\r")); + // + // Allocate 1 page below 1MB to put real mode thunk code in + // + // Undi Loader Table is a PXE Specification prescribed data structure + // that is used to transfer information into and out of the Undi layer. + // Note how it must be located below 1 MB. + // + SimpleNetworkDevice->UndiLoaderTablePages = EFI_SIZE_TO_PAGES (PARAGRAPH_SIZE + sizeof (UNDI_LOADER_T)); + Status = BiosSnp16AllocatePagesBelowOneMb ( + SimpleNetworkDevice->UndiLoaderTablePages, + &SimpleNetworkDevice->UndiLoaderTable + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); + return EFI_OUT_OF_RESOURCES; + } + + UndiLoaderTable = SimpleNetworkDevice->UndiLoaderTable; + + DEBUG ((DEBUG_NET, "Allocate area for the real-mode stack whose sole purpose\n\r")); + DEBUG ((DEBUG_NET, "in life right now is to store a SEG:OFFSET combo pair that\n\r")); + DEBUG ((DEBUG_NET, "points to an Undi_Loader_t table structure\n\r")); + + Size = 0x100; + Status = gBS->AllocatePool (EfiLoaderData, Size, &Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Now we want to put a pointer to the Under Loader Table in our MemPage + // Buffer. This will be the argument stack for the call into the Undi Loader + // + StackPointer = (UINT16 *) Buffer; + *StackPointer++ = TO_OFFSET (UndiLoaderTable); + // + // push the OFFSET + // + *StackPointer++ = TO_SEGMENT (UndiLoaderTable); + // + // push the SEGMENT + // + StackPointer = (UINT16 *) Buffer; + // + // reset the stack pointer + // + DEBUG ( + (DEBUG_NET, + "After the fixups, the stack pointer is 0x%X\n\r", + (UINT64)(UINTN) StackPointer) + ); + + // + // Allocate memory for the Deployed UNDI. + // The UNDI is essentially telling us how much space it needs, and + // it is up to the EFI driver to allocate sufficient, boot-time + // persistent resources for the call + // + SimpleNetworkDevice->DestinationDataSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->DataSize); + Status = BiosSnp16AllocatePagesBelowOneMb ( + SimpleNetworkDevice->DestinationDataSegmentPages, + &SimpleNetworkDevice->DestinationDataSegment + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); + return Status; + } + + UndiLoaderTable->Undi_Ds = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationDataSegment >> 4); + + // + // Allocate memory for the Deployed UNDI stack + // The UNDI is essentially telling us how much space it needs, and + // it is up to the EFI driver to allocate sufficient, boot-time + // persistent resources for the call + // + SimpleNetworkDevice->DestinationStackSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->StackSize); + Status = BiosSnp16AllocatePagesBelowOneMb ( + SimpleNetworkDevice->DestinationStackSegmentPages, + &SimpleNetworkDevice->DestinationStackSegment + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); + return Status; + } + // + // Allocate memory for the Deployed UNDI. + // The UNDI is essentially telling us how much space it needs, and + // it is up to the EFI driver to allocate sufficient, boot-time + // persistent resources for the call + // + SimpleNetworkDevice->DestinationCodeSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->CodeSize); + Status = BiosSnp16AllocatePagesBelowOneMb ( + SimpleNetworkDevice->DestinationCodeSegmentPages, + &SimpleNetworkDevice->DestinationCodeSegment + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); + return Status; + } + + UndiLoaderTable->Undi_Cs = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationCodeSegment >> 4); + + // + // these are in the Input and Output Parameter to be sent to the UNDI Loader code + // + UndiLoaderTable->Status = 0xAA55; + // + // -------------------- Changed by Michael_Huang@3Com.com ----------------- + // UndiLoaderTable->_AX is AX value when UNDI ROM is initialized by BIOS, it is the PCI bus device + // function of the NIC. Please refer to PXE Spec for detail info. + // old code is: + // UndiLoaderTable->Ax = 0x0; + // ----------------------------------------------------------------------- + // + SimpleNetworkDevice->PciIo->GetLocation ( + SimpleNetworkDevice->PciIo, + &PciSegment, + &Bus, + &Device, + &Function + ); + UndiLoaderTable->Ax = (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function)); + UndiLoaderTable->Bx = 0x0; + UndiLoaderTable->Dx = 0x0; + UndiLoaderTable->Di = 0x0; + UndiLoaderTable->Es = 0x0; + + // + // set these OUT values to zero in order to ensure that + // uninitialized memory is not mistaken for display data + // + UndiLoaderTable->PXEptr.Offset = 0; + UndiLoaderTable->PXEptr.Segment = 0; + UndiLoaderTable->PXENVptr.Segment = 0; + UndiLoaderTable->PXENVptr.Offset = 0; + + DEBUG ( + (DEBUG_INIT, + "The NIC is located at Bus 0x%X, Device 0x%X, Function 0x%X\n\r", + Bus, + Device, + Function) + ); + + // + // These are the values that set up the ACTUAL IA32 machine state, whether in + // Real16 in EFI32 or the IVE for IA64 + // register values are unused except for CS:IP and SS:SP + // + InOutRegs.X.AX = 0; + InOutRegs.X.BX = 0; + InOutRegs.X.CX = 0; + InOutRegs.X.DX = 0; + InOutRegs.X.SI = 0; + InOutRegs.X.DI = 0; + InOutRegs.X.BP = 0; + InOutRegs.X.DS = 0; + InOutRegs.X.ES = 0; + // + // just to be clean + // + DEBUG ((DEBUG_NET, "The way this game works is that the SS:SP +4 should point\n\r")); + DEBUG ((DEBUG_NET, "to the contents of the UndiLoaderTable\n\r")); + DEBUG ( + (DEBUG_NET, + "The Undi Loader Table is at address = 0x%X\n\r", + (UINT32)(UINTN) UndiLoaderTable) + ); + DEBUG ( + (DEBUG_NET, + "The segment and offsets are 0x%X and 0x%X, resp\n", + TO_SEGMENT (UndiLoaderTable), + TO_OFFSET (UndiLoaderTable)) + ); + + DEBUG ( + (DEBUG_NET, + "The Linear Address of the UNDI Loader entry is 0x%X\n", + RomAddress + RomIdTableAddress->UNDI_Loader) + ); + + DEBUG ( + (DEBUG_NET, + "The Address offset of the UNDI Loader entry is 0x%X\n", + RomIdTableAddress->UNDI_Loader) + ); + + DEBUG ((DEBUG_NET, "Before the call, we have...\n\r")); + Print_Undi_Loader_Table (UndiLoaderTable); + + Segment = ((UINT16) (RShiftU64 (RomAddress, 4) & 0xFFFF)); + DEBUG ((DEBUG_NET, "The Segment of the call is 0x%X\n\r", Segment)); + + // + // make the call into the UNDI Code + // + DEBUG ((DEBUG_INIT, "Make the call into the UNDI code now\n\r")); + + DEBUG ((DEBUG_NET, "\nThe 20-BIt address of the Call, and the location \n\r")); + DEBUG ((DEBUG_NET, "\twhere we should be able to set a breakpoint is \n\r")); + DEBUG ( + (DEBUG_NET, + "\t\t0x%X, from SEG:OFF 0x%X:0x%X\n\r\n\r", + Segment * 0x10 + RomIdTableAddress->UNDI_Loader, + Segment, + RomIdTableAddress->UNDI_Loader) + ); + + ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 ( + SimpleNetworkDevice->LegacyBios, + Segment, // Input segment + (UINT16) RomIdTableAddress->UNDI_Loader, // Offset + &InOutRegs, // Ptr to Regs + Buffer, // Reference to Stack + Size // Size of the Stack + ); + if (ThunkFailed) { + return EFI_ABORTED; + } + + DEBUG ( + (DEBUG_NET, + "The return code UndiLoaderTable->Status is = 0x%X\n\r", + UndiLoaderTable->Status) + ); + DEBUG ( + (DEBUG_NET, + "This error code should match eax, which is = 0x%X\n\r", + InOutRegs.X.AX) + ); + + if ((UndiLoaderTable->Status != 0) || (InOutRegs.X.AX != PXENV_EXIT_SUCCESS)) { + DEBUG ((DEBUG_NET, "LaunchBaseCode exits with error, RomAddress = 0x%X\n\r", RomAddress)); + return EFI_ABORTED; + } + + DEBUG ((DEBUG_NET, "Now returned from the UNDI code\n\r")); + + DEBUG ((DEBUG_NET, "After the call, we have...\n\r")); + Print_Undi_Loader_Table (UndiLoaderTable); + + DEBUG ((DEBUG_NET, "Display the PXENV+ and !PXE tables exported by NIC\n\r")); + Print_PXENV_Table ((VOID *)(UINTN)((UndiLoaderTable->PXENVptr.Segment << 4) | UndiLoaderTable->PXENVptr.Offset)); + Print_PXE_Table ((VOID *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset)); + + Pxe = (PXE_T *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset); + SimpleNetworkDevice->Nii.Id = (UINT64)(UINTN) Pxe; + + gBS->FreePool (Buffer); + + // + // paranoia - make sure a valid !PXE structure + // + if (CompareMem (Pxe->Signature, PXE_SIG, sizeof Pxe->Signature) != 0) { + DEBUG ((DEBUG_ERROR, "!PXE Structure not found....\n\r")); + return EFI_NOT_FOUND; + // + // its not - keep looking + // + } + + if (CalculateSum8 ((UINT8 *) Pxe, Pxe->StructLength) != 0) { + DEBUG ((DEBUG_ERROR, "!PXE Checksum Error\n\r")); + return EFI_NOT_FOUND; + } + + if (Pxe->StructLength < (UINT8 *) &Pxe->FirstSelector - (UINT8 *) Pxe->Signature) { + DEBUG ((DEBUG_ERROR, "!PXE Length Error\n\r")); + return EFI_NOT_FOUND; + } + + if ((((UINTN) Pxe->Undi.Segment) << 4) + Pxe->Undi.Offset != (UINTN) RomIdTableAddress) { + DEBUG ((DEBUG_ERROR, "!PXE RomId Address Error\n\r")); + return EFI_NOT_FOUND; + } + // + // This is the magic to bind the global PXE interface + // This dirtiness is for non-protocol shrouded access + // + SimpleNetworkDevice->PxeEntrySegment = Pxe->EntryPointSP.Segment; + + if (SimpleNetworkDevice->PxeEntrySegment == 0) { + DEBUG ((DEBUG_ERROR, "!PXE EntryPointSP segment Error\n\r")); + return EFI_NOT_FOUND; + } + + SimpleNetworkDevice->PxeEntryOffset = Pxe->EntryPointSP.Offset; + + DEBUG ( + ( + DEBUG_NET, "The entry point is 0x%X:0x%X\n\r", SimpleNetworkDevice->PxeEntrySegment, SimpleNetworkDevice-> + PxeEntryOffset + ) + ); + + return EFI_SUCCESS; +} + +/** + Effect the Far Call into the PXE Layer + + Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API + services will not work, unless there are three 16-bit parameters pushed onto the stack. + push DS ;Far pointer to parameter structure + push offset pxe_data_call_struct ;is pushed onto stack. + push Index ;UINT16 is pushed onto stack. + call dword ptr (s_PXE ptr es:[di]).EntryPointSP + add sp, 6 ;Caller cleans up stack. + + @param SimpleNetworkDevice Device instance for simple network + @param Table Point to parameter/retun value table for legacy far call + @param TableSize The size of paramter/return value table + @param CallIndex The index of legacy call. + + @return EFI_STATUS +**/ +EFI_STATUS +MakePxeCall ( + EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT VOID *Table, + IN UINTN TableSize, + IN UINT16 CallIndex + ) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET InOutRegs; + UINT16 *BPtr; + VOID *Buffer; + UINTN Size; + VOID *MemPageAddress; + UINTN Index; + BOOLEAN ThunkFailed; + + DEBUG ((DEBUG_NET, "MakePxeCall(CallIndex = %02x, Table = %X, TableSize = %d)\n", CallIndex, Table, TableSize)); + + if (SimpleNetworkDevice->PxeEntrySegment == 0 && SimpleNetworkDevice->PxeEntryOffset == 0) { + return EFI_DEVICE_ERROR; + } + + Status = EFI_SUCCESS; + + // + // Allocate a transient data structure for the argument table + // This table needs to have the input XXX_t structure copied into here. + // The PXE UNDI can only grab this table when it's below one-MB, and + // this implementation will not try to push this table on the stack + // (although this is a possible optimization path since EFI always allocates + // 4K as a minimum page size...............) + // + Status = BiosSnp16AllocatePagesBelowOneMb ( + TableSize / EFI_PAGE_SIZE + 1, + &MemPageAddress + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); + return Status; + } + // + // Copy the > 1MB pool table to a sub-1MB buffer + // + CopyMem (MemPageAddress, Table, TableSize); + + // + // Allocate space for IA-32 register context + // + ZeroMem (&InOutRegs, sizeof (InOutRegs)); + InOutRegs.X.ES = SimpleNetworkDevice->PxeEntrySegment; + InOutRegs.X.DI = SimpleNetworkDevice->PxeEntryOffset; + + // + // The game here is to build the stack which will subsequently + // get copied down below 1 MB by the FarCall primitive. + // This is now our working stack + // + Size = 6; + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + Size, + &Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + BPtr = (UINT16 *) Buffer; + *BPtr++ = CallIndex; + // + // SP + 2 + // + *BPtr++ = TO_OFFSET (MemPageAddress); + *BPtr++ = TO_SEGMENT (MemPageAddress); + + DEBUG ((DEBUG_NET, "State before FarCall86\n")); + DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer)); + BPtr = (UINT16 *) Buffer; + DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2))); + DEBUG ((DEBUG_NET, " MemPage = ")); + for (Index = 0; Index < TableSize; Index++) { + DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index))); + } + + DEBUG ((DEBUG_NET, "\n")); + + ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 ( + SimpleNetworkDevice->LegacyBios, + SimpleNetworkDevice->PxeEntrySegment, // Input segment + SimpleNetworkDevice->PxeEntryOffset, + &InOutRegs, // Ptr to Regs + Buffer, // Reference to Stack + 6 // Size of the Stack + ); + if (ThunkFailed) { + return EFI_ABORTED; + } + + DEBUG ((DEBUG_NET, "State after FarCall86\n")); + DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer)); + BPtr = (UINT16 *) Buffer; + DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2))); + DEBUG ((DEBUG_NET, " MemPage = ")); + for (Index = 0; Index < TableSize; Index++) { + DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index))); + } + + DEBUG ((DEBUG_NET, "\n")); + + // + // Copy the sub 1MB table to > 1MB table + // + CopyMem (Table, MemPageAddress, TableSize); + + // + // For PXE UNDI call, AX contains the return status. + // Convert the PXE UNDI Status to EFI_STATUS type + // + if (InOutRegs.X.AX == PXENV_EXIT_SUCCESS) { + Status = EFI_SUCCESS; + } else { + Status = EFI_DEVICE_ERROR; + } + // + // Clean up house + // + gBS->FreePool (Buffer); + gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) MemPageAddress, TableSize / EFI_PAGE_SIZE + 1); + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h new file mode 100644 index 0000000000..54503a840f --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h @@ -0,0 +1,613 @@ +/** @file + These are PXE Specification 2.1-compliant data structures and defines. + + This file relies upon the existence of a PXE-compliant ROM + in memory, as defined by the Preboot Execution Environment + Specification (PXE), Version 2.1, located at + + http://developer.intel.com/ial/wfm/wfmspecs.htm + +Copyright (c) 1999 - 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 _PXEDEF_H_ +#define _PXEDEF_H_ + +#pragma pack(1) + +// +// PXE structure signatures +// +#define BC_ROMID_SIG "$BC$" +#define UNDI_ROMID_SIG "UNDI" +#define BUSD_ROMID_SIG "BUSD" + +#define PXE_SIG "!PXE" +#define PXENV_SIG "PXENV+" + +#define BC_ROMID_REV 0x00 +#define UNDI_ROMID_REV 0x00 +#define BUSD_ROMID_REV 0x00 + +#define PXE_REV 0x00 +#define PXENV_REV 0x0201 + +#define PXENV_PTR SIGNATURE_32 ('P', 'X', 'E', 'N') +#define PXE_PTR SIGNATURE_32 ('!', 'P', 'X', 'E') +#define UNDI_ROMID_SIG_PTR SIGNATURE_32 ('U', 'N', 'D', 'I') + +typedef UINT16 SEGSEL; // Real mode segment or protected mode selector. +typedef UINT16 OFF16; // Unsigned 16bit offset. +typedef UINT32 ADDR32; + +// +// Bus types +// +#define PXENV_BUS_ISA 0 +#define PXENV_BUS_EISA 1 +#define PXENV_BUS_MCA 2 +#define PXENV_BUS_PCI 3 +#define PXENV_BUS_VESA 4 +#define PXENV_BUS_PCMCIA 5 + +// +// +// Result codes returned in AX by a PXENV API service. +// +#define PXENV_EXIT_SUCCESS 0x0000 +#define PXENV_EXIT_FAILURE 0x0001 + +// +// Status codes returned in the status word of PXENV API parameter structures. +// +// Generic API errors - these do not match up with the M0x or E0x messages +// that are reported by the loader. +// +#define PXENV_STATUS_SUCCESS 0x00 +#define PXENV_STATUS_FAILURE 0x01 +#define PXENV_STATUS_BAD_FUNC 0x02 +#define PXENV_STATUS_UNSUPPORTED 0x03 +#define PXENV_STATUS_KEEP_UNDI 0x04 +#define PXENV_STATUS_KEEP_ALL 0x05 +#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 + +typedef enum { + PxeEnvStatus_Success, + PxeEnvStatus_Failure, + PxeEnvStatus_BadFunc, + PxeEnvStatus_Unsupported, + PxeEnvStatus_KeepUndi, + PxeEnvStatus_KeepAll +} EFI_PXE_STATUS; + +/* Driver errors (0x60 to 0x6F) */ + +// These errors are for UNDI compatible NIC drivers. +#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 +#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 +#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 +#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 +#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 +#define PXENV_STATUS_UNDI_BAD_MAC_ADDR 0x67 +#define PXENV_STATUS_UNDI_BAD_EEPROM_CKSUM 0x68 +#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 +#define PXENV_STATUS_UNDI_INVALID_STATE 0x6A +#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B +#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C + +typedef struct { + UINT16 Seg_Addr; + UINT32 Phy_Addr; + UINT16 Seg_Size; +} NEWSEGDESC_T; + +typedef struct { + OFF16 Offset; + SEGSEL Segment; +} SEGOFF16; + +typedef struct { + UINT8 Signature[4]; ///< Structure signature is not NULL terminated. + UINT8 StructLength; ///< Length of this structure in bytes. + UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero. + UINT8 StructRev; ///< Structure format revision number. + UINT8 UNDI_Rev[3]; ///< API revision number stored in Intel order. + // + // Revision 2.1.0 == 0x00, 0x01, 0x02 + // + UINT16 UNDI_Loader; ///< Offset of UNDI loader routine in the option ROM image. + UINT16 StackSize; ///< Minimum stack segment size, in bytes, needed to load and run the UNDI. + UINT16 DataSize; ///< UNDI runtime code and data + UINT16 CodeSize; ///< segment sizes. + UINT8 BusType[4]; ///< 'ISAR', 'EISA', 'PCIR', 'PCCR' +} UNDI_ROMID_T; + +typedef struct { + UINT8 Signature[4]; ///< Structure signature is not NULL terminated. + UINT8 StructLength; ///< Length of this structure in bytes. + UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero. + UINT8 StructRev; ///< Structure format revision number. + UINT8 BC_Rev[3]; ///< API revision number stored in Intel order. + // + // Revision 2.1.0 == 0x00, 0x01, 0x02 + // + UINT16 BC_Loader; ///< Offset of base-code loader routine in the option ROM image. + UINT16 StackSize; ///< Minimum stack segment size (bytes) needed to load/run base-code. + UINT16 DataSize; ///< Base-code runtime code and data + UINT16 CodeSize; ///< segment sizes. +} BC_ROMID_T; + +typedef struct { + UINT8 Signature[4]; ///< Structure signature is not NULL terminated. + UINT8 StructLength; ///< Length of this structure in bytes. + UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero. + UINT8 StructRev; ///< Structure format revision number. + UINT8 Reserved1; ///< must be zero + /// + /// UNDI_ROMID_T __FAR *UNDI;// Far pointer to UNDI ROMID + /// + SEGOFF16 Undi; + + /// + /// BC_ROMID_T __FAR *Base; // Far pointer to base-code ROMID + /// + SEGOFF16 Base; + + /// + /// UINT16 (__FAR __CDECL *EntryPointSP)(UINT16 func, VOID __FAR *param); + /// 16bit stack segment API entry point. This will be seg:off in + /// real mode and sel:off in 16:16 protected mode. + /// + SEGOFF16 EntryPointSP; + + /// + /// UINT16 (__FAR __CDECL *EntryPointESP)(UINT16 func, VOID __FAR *param); + /// 32bit stack segment API entry point. This will be sel:off. + /// In real mode, sel == 0 + /// + SEGOFF16 EntryPointESP; + /// + /// UINT16 (__FAR __CDECL *StatusCallout)(UINT16 param); + /// Address of DHCP/TFTP status callout routine. + /// + SEGOFF16 StatusCallout; + UINT8 Reserved2; ///< must be zero + UINT8 SegDescCnt; ///< Number of segment descriptors in this structure. + UINT16 FirstSelector; ///< First segment descriptor in GDT assigned to PXE. + NEWSEGDESC_T Stack; + NEWSEGDESC_T UNDIData; + NEWSEGDESC_T UNDICode; + NEWSEGDESC_T UNDICodeWrite; + NEWSEGDESC_T BC_Data; + NEWSEGDESC_T BC_Code; + NEWSEGDESC_T BC_CodeWrite; +} PXE_T; + +typedef struct { + CHAR8 Signature[6]; ///< "PXENV+" + UINT16 Version; ///< PXE version number. LSB is minor version. MSB is major version. + UINT8 StructLength; ///< Length of PXE-2.0 Entry Point structure in bytes. + UINT8 StructCksum; ///< Used to make structure checksum equal zero. + UINT32 RMEntry; ///< Real mode API entry point segment:offset. + UINT32 PMEntryOff; ///< Protected mode API entry point + UINT16 PMEntrySeg; ///< segment:offset. This will always be zero. Protected mode API calls + ///< must be made through the API entry points in the PXE Runtime ID structure. + + UINT16 StackSeg; ///< Real mode stack segment. + UINT16 StackSize; ///< Stack segment size in bytes. + UINT16 BaseCodeSeg; ///< Real mode base-code code segment. + UINT16 BaseCodeSize; ///< Base-code code segment size + UINT16 BaseDataSeg; ///< Real mode base-code data segment. + UINT16 BaseDataSize; ///< Base-code data segment size + UINT16 UNDIDataSeg; ///< Real mode UNDI data segment. + UINT16 UNDIDataSize; ///< UNDI data segment size in bytes. + UINT16 UNDICodeSeg; ///< Real mode UNDI code segment. + UINT16 UNDICodeSize; ///< UNDI code segment size in bytes. + PXE_T *RuntimePtr; ///< Real mode segment:offset pointer to PXE Runtime ID structure. +} PXENV_T; + +typedef struct { + OUT UINT16 Status; + IN OUT UINT16 Ax; + IN OUT UINT16 Bx; + IN OUT UINT16 Dx; + IN OUT UINT16 Di; + IN OUT UINT16 Es; + IN OUT UINT16 Undi_Ds; + IN OUT UINT16 Undi_Cs; + OUT SEGOFF16 PXEptr; + OUT SEGOFF16 PXENVptr; +} UNDI_LOADER_T; + +// +// Put in some UNDI-specific arguments +// +#define PXENV_START_UNDI 0x0000 +#define PXENV_UNDI_STARTUP 0x0001 +#define PXENV_UNDI_CLEANUP 0x0002 +#define PXENV_UNDI_INITIALIZE 0x0003 +#define PXENV_UNDI_RESET_NIC 0x0004 +#define PXENV_UNDI_SHUTDOWN 0x0005 +#define PXENV_UNDI_OPEN 0x0006 +#define PXENV_UNDI_CLOSE 0x0007 +#define PXENV_UNDI_TRANSMIT 0x0008 +#define PXENV_UNDI_SET_MCAST_ADDR 0x0009 +#define PXENV_UNDI_SET_STATION_ADDR 0x000A +#define PXENV_UNDI_SET_PACKET_FILTER 0x000B +#define PXENV_UNDI_GET_INFORMATION 0x000C +#define PXENV_UNDI_GET_STATISTICS 0x000D +#define PXENV_UNDI_CLEAR_STATISTICS 0x000E +#define PXENV_UNDI_INITIATE_DIAGS 0x000F +#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 +#define PXENV_UNDI_GET_MCAST_ADDR 0x0011 +#define PXENV_UNDI_GET_NIC_TYPE 0x0012 +#define PXENV_UNDI_GET_NDIS_INFO 0x0013 +#define PXENV_UNDI_ISR 0x0014 +#define PXENV_STOP_UNDI 0x0015 +#define PXENV_UNDI_GET_STATE 0x0016 + +#define ADDR_LEN 16 +#define MAXNUM_MCADDR 8 +#define IPLEN 4 ///< length of an IP address +#define XMT_DESTADDR 0x0000 ///< destination address given +#define XMT_BROADCAST 0x0001 ///< use broadcast address + +typedef struct { + UINT16 MCastAddrCount; ///< In: Number of multi-cast + + /* addresses. */ + UINT8 MCastAddr[MAXNUM_MCADDR][ADDR_LEN]; /* In: */ + + /* list of multi-cast addresses. */ + + /* Each address can take up to */ + + /* ADDR_LEN bytes and a maximum */ + + /* of MAXNUM_MCADDR address can */ + + /* be provided*/ +} PXENV_UNDI_MCAST_ADDR_T; + +/* Definitions of TFTP API parameter structures. + */ +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + IN UINT16 Ax; ///< In: These register fields must be + IN UINT16 Bx; ///< filled in with the same data + IN UINT16 Dx; ///< that was passed to the MLID + IN UINT16 Di; ///< option ROM boot code by the + IN UINT16 Es; ///< system BIOS. +} PXENV_START_UNDI_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx +} PXENV_UNDI_STARTUP_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx +} PXENV_UNDI_CLEANUP_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + + /// + /// This is an input parameter and is a 32-bit physical address of + /// a memory copy of the driver module in the protocol.ini file + /// obtained from the Protocol Manager driver(refer to NDIS 2.0 + /// specifications). This parameter is basically supported for + /// the universal NDIS driver to pass the information contained in + /// protocol.ini file to the NIC driver for any specific + /// configuration of the NIC. (Note that the module + /// identification in the protocol.ini file was done by NDIS + /// itself.) This value can be NULL for for any other application + /// interfacing to the Universal NIC Driver. + /// + IN UINT32 ProtocolIni; + UINT8 Reserved[8]; +} PXENV_UNDI_INITIALIZE_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + IN PXENV_UNDI_MCAST_ADDR_T R_Mcast_Buf; ///< multicast address list + /* see note below */ +} PXENV_UNDI_RESET_T; + +/*++ + Note: The NIC driver does not remember the multicast + addresses provided in any call. So the application must + provide the multicast address list with all the calls that + reset the receive unit of the adapter. + --*/ +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx +} PXENV_UNDI_SHUTDOWN_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + + /// + /// This is an input parameter and is adapter specific. This is + /// supported for Universal NDIS 2.0 driver to pass down the Open + /// flags provided by the protocol driver (See NDIS 2.0 + /// specifications). This can be zero. + /// + IN UINT16 OpenFlag; ///< In: See description below + IN UINT16 PktFilter; ///< In: Filter for receiving + + /* packet. It takes the following */ + + /* values, multiple values can be */ + + /* ORed together. */ +#define FLTR_DIRECTED 0x0001 ///< directed/multicast +#define FLTR_BRDCST 0x0002 ///< broadcast packets +#define FLTR_PRMSCS 0x0004 ///< any packet on LAN +#define FLTR_SRC_RTG 0x0008 ///< source routing packet + IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; /* In: */ + /* See t_PXENV_UNDI_MCAST_ADDR. */ +} PXENV_UNDI_OPEN_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx +} PXENV_UNDI_CLOSE_T; + +#define MAX_DATA_BLKS 8 + +typedef struct { + IN UINT16 ImmedLength; ///< In: Data buffer length in + + /* bytes. */ + UINT16 XmitOffset; ///< 16-bit segment & offset of the + UINT16 XmitSegment; ///< immediate data buffer. + UINT16 DataBlkCount; ///< In: Number of data blocks. + struct DataBlk { + UINT8 TDPtrType; ///< 0 => 32 bit Phys pointer in TDDataPtr, not supported in this version of LSA + ///< 1 => seg:offser in TDDataPtr which can be a real mode or 16-bit protected mode pointer + UINT8 TDRsvdByte; ///< Reserved, must be zero. + UINT16 TDDataLen; ///< Data block length in bytes. + UINT16 TDDataPtrOffset; ///< Far pointer to data buffer. + UINT16 TDDataPtrSegment; ///< Far pointer to data buffer. + } DataBlock[MAX_DATA_BLKS]; +} +PXENV_UNDI_TBD_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + + /// + /// This is the protocol of the upper layer that is calling + /// NICTransmit call. If the upper layer has filled the media + /// header this field must be 0. + /// + IN UINT8 Protocol; +#define P_UNKNOWN 0 +#define P_IP 1 +#define P_ARP 2 +#define P_RARP 3 + + /// + /// If this flag is 0, the NIC driver expects a pointer to the + /// destination media address in the field DestMediaAddr. If 1, + /// the NIC driver fills the broadcast address for the + /// destination. + /// + IN UINT8 XmitFlag; +#define XMT_DESTADDR 0x0000 ///< destination address given +#define XMT_BROADCAST 0x0001 ///< use broadcast address + + /// + /// This is a pointer to the hardware address of the destination + /// media. It can be null if the destination is not known in + /// which case the XmitFlag contains 1 for broadcast. Destination + /// media address must be obtained by the upper level protocol + /// (with Address Resolution Protocol) and NIC driver does not do + /// any address resolution. + /// + IN UINT16 DestAddrOffset; ///< 16-bit segment & offset of the + IN UINT16 DestAddrSegment; ///< destination media address + + + IN UINT16 TBDOffset; ///< 16-bit segment & offset of the + IN UINT16 TBDSegment; ///< transmit buffer descriptor of type + + /// XmitBufferDesc + IN UINT32 Reserved[2]; +} PXENV_UNDI_TRANSMIT_T; + + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; ///< In: +} PXENV_UNDI_SET_MCAST_ADDR_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + IN UINT8 StationAddress[ADDR_LEN]; ///< new address to be set +} PXENV_UNDI_SET_STATION_ADDR_T; + +typedef struct s_PXENV_UNDI_SET_PACKET_FILTER { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + IN UINT8 Filter; ///< In: Receive filter value. +} PXENV_UNDI_SET_PACKET_FILTER_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + OUT UINT16 BaseIo; ///< Out: Adapter's Base IO + OUT UINT16 IntNumber; ///< Out: IRQ number + OUT UINT16 MaxTranUnit; ///< Out: MTU + OUT UINT16 HwType; ///< Out: type of protocol at hardware level + +#define ETHER_TYPE 1 +#define EXP_ETHER_TYPE 2 +#define IEEE_TYPE 6 +#define ARCNET_TYPE 7 + /*++ + other numbers can be obtained from rfc1010 for "Assigned + Numbers". This number may not be validated by the application + and hence adding new numbers to the list should be fine at any + time. + --*/ + OUT UINT16 HwAddrLen; ///< Out: actual length of hardware address + OUT UINT8 CurrentNodeAddress[ADDR_LEN]; ///< Out: Current hardware address + OUT UINT8 PermNodeAddress[ADDR_LEN]; ///< Out: Permanent hardware address + OUT UINT16 ROMAddress; ///< Out: ROM address + OUT UINT16 RxBufCt; ///< Out: receive Queue length + OUT UINT16 TxBufCt; ///< Out: Transmit Queue length +} PXENV_UNDI_GET_INFORMATION_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + OUT UINT32 XmtGoodFrames; ///< Out: No. of good transmissions + OUT UINT32 RcvGoodFrames; ///< Out: No. of good frames received + OUT UINT32 RcvCRCErrors; ///< Out: No. of frames with CRC error + OUT UINT32 RcvResourceErrors; ///< Out: no. of frames discarded + /* Out: receive Queue full */ +} PXENV_UNDI_GET_STATISTICS_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx +} PXENV_UNDI_CLEAR_STATISTICS_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx +} PXENV_UNDI_INITIATE_DIAGS_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx +} PXENV_UNDI_FORCE_INTERRUPT_T; + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + IN UINT32 InetAddr; ///< In: IP Multicast Address + OUT UINT8 MediaAddr[ADDR_LEN]; ///< Out: corresponding hardware + /* multicast address */ +} PXENV_UNDI_GET_MCAST_ADDR_T; + +typedef struct { + OUT UINT16 Vendor_ID; ///< OUT: + OUT UINT16 Dev_ID; ///< OUT: + OUT UINT8 Base_Class; ///< OUT: + OUT UINT8 Sub_Class; ///< OUT: + OUT UINT8 Prog_Intf; ///< OUT: program interface + OUT UINT8 Rev; ///< OUT: Revision number + OUT UINT16 BusDevFunc; ///< OUT: Bus, Device & Function numbers + OUT UINT16 SubVendor_ID; ///< OUT: + OUT UINT16 SubDevice_ID; ///< OUT: +} PCI_INFO_T; + +typedef struct { + OUT UINT32 EISA_Dev_ID; ///< Out: + OUT UINT8 Base_Class; ///< OUT: + OUT UINT8 Sub_Class; ///< OUT: + OUT UINT8 Prog_Intf; ///< OUT: program interface + OUT UINT16 CardSelNum; ///< OUT: Card Selector Number + OUT UINT8 Reserved; ///< to make it 10 bytes +} PNP_INFO_T; + + +typedef union { + PCI_INFO_T Pci; + PNP_INFO_T Pnp; +} PCI_PNP_INFO_T; + +typedef struct { + OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx + OUT UINT8 NicType; ///< OUT: 2=PCI, 3=PnP + PCI_PNP_INFO_T PciPnpInfo; +} PXENV_UNDI_GET_NIC_TYPE_T; + +typedef struct { + OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx + OUT UINT8 IfaceType[16]; ///< OUT: Type name of MAC, AsciiZ + + /* format. This is used by the */ + + /* Universal NDIS Driver to fill */ + + /* the driver type in it's MAC */ + + /* Service specific */ + + /* characteristic table */ + OUT UINT32 LinkSpeed; ///< OUT: + OUT UINT32 ServiceFlags; ///< OUT: as defined in NDIS Spec 2.0X + OUT UINT32 Reserved[4]; ///< OUT: will be filled with 0s till defined +} PXENV_UNDI_GET_NDIS_INFO_T; + +typedef struct { + OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx + IN OUT UINT16 FuncFlag; ///< In: PXENV_UNDI_ISR_IN_xxx + + /* Out: PXENV_UNDI_ISR_OUT_xxx */ + OUT UINT16 BufferLength; + OUT UINT16 FrameLength; + OUT UINT16 FrameHeaderLength; + OUT UINT16 FrameOffset; + OUT UINT16 FrameSegSel; + OUT UINT8 ProtType; + OUT UINT8 PktType; +} PXENV_UNDI_ISR_T; + +#define PXENV_UNDI_ISR_IN_START 1 /* This function must be first */ + +/* when an interrupt is received. */ + +/* It will tell us if the intr */ + +/* was generated by our device. */ +#define PXENV_UNDI_ISR_IN_PROCESS 2 /* Call to start processing one of */ + +/* our interrupts. */ +#define PXENV_UNDI_ISR_IN_GET_NEXT 3 /* Call to start/continue receiving */ + +/* data from receive buffer(s). */ + +/*++ + + Possible responses from PXENV_UNDI_ISR_IN_START + + --*/ +#define PXENV_UNDI_ISR_OUT_OURS 0 ///< This is our interrupt. Deal with it. +#define PXENV_UNDI_ISR_OUT_NOT_OURS 1 ///< This is not our interrupt. + +/*++ + + Possible responses from PXENV_UNDI_ISR_IN_PROCESS and + PXENV_UNDI_ISR_IN_PROCESS + +--*/ +#define PXENV_UNDI_ISR_OUT_DONE 0 ///< We are done processing this interrupt. +#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 ///< We completed a transmit interrupt. +#define PXENV_UNDI_ISR_OUT_RECEIVE 3 ///< Get data from receive buffer. + +#define PXENV_UNDI_ISR_OUT_BUSY 4 /* ? */ + +typedef struct { + UINT16 Status; ///< Out: PXENV_STATUS_xxx +} PXENV_STOP_UNDI_T; + +#define PXENV_UNDI_STARTED 1 ///< not even initialized +#define PXENV_UNDI_INITIALIZED 2 ///< initialized and closed (not opened) +#define PXENV_UNDI_OPENED 3 ///< initialized & opened + +typedef struct { + OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx + UINT16 UNDI_State; +} PXENV_UNDI_GET_STATE_T; + +#pragma pack() + +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c new file mode 100644 index 0000000000..d35fc3f430 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c @@ -0,0 +1,1254 @@ +/** @file + Wrapper routines that use a PXE-enabled NIC option ROM to + supply internal routines for an EFI SNI (Simple Network + Interface) Protocol. + + This file relies upon the existence of a PXE-compliant ROM + in memory, as defined by the Preboot Execution Environment + Specification (PXE), Version 2.1, located at + + http://developer.intel.com/ial/wfm/wfmspecs.htm + +Copyright (c) 1999 - 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 "BiosSnp16.h" + +/** + PXE + START UNDI + Op-Code: PXENV_START_UNDI (0000h) + Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is + responsible for saving the information it needs to communicate with the hardware. + This service is also responsible for hooking the Int 1Ah service routine + Note: This API service must be called only once during UNDI Option ROM boot. + The UNDI driver is responsible for saving this information and using it every time + PXENV_UNDI_STARTUP is called. + Service cannot be used in protected mode. + typedef struct { + PXENV_STATUS Status; + UINT16 AX; + UINT16 BX; + UINT16 DX; + UINT16 DI; + UINT16 ES; + } PXENV_START_UNDI_T; + Set before calling API service + AX, BX, DX, DI, ES: BIOS initialization parameter registers. These + fields should contain the same information passed to the option ROM + initialization routine by the Host System BIOS. Information about the + contents of these registers can be found in the [PnP], [PCI] and + [BBS] specifications. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeStartUndi ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_START_UNDI_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_START_UNDI_T), + PXENV_START_UNDI + ); +} + +/** + PXE + UNDI STARTUP + Op-Code: PXENV_UNDI_STARTUP (0001h) + Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the + caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper + operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used + to complete this initialization. The rest of the UNDI APIs will not be available until this call has + been completed. + Note: PXENV_UNDI_STARTUP must not be called again without first calling + PXENV_UNDI_SHUTDOWN. + PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for + chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and + PXENV_STOP_UNDI API calls. + This service cannot be used in protected mode. + typedef struct + { + PXENV_STATUS Status; + } PXENV_UNDI_STARTUP_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiStartup ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_STARTUP_T), + PXENV_UNDI_STARTUP + ); +} + +/** + PXE + UNDI CLEANUP + Op-Code: PXENV_UNDI_CLEANUP (0002h) + Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field + in the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be + made just before unloading the Universal NIC Driver. The rest of the API will not be available + after this call executes. + This service cannot be used in protected mode. + typedef struct { + PXENX_STATUS Status; + } PXENV_UNDI_CLEANUP_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiCleanup ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_CLEANUP_T), + PXENV_UNDI_CLEANUP + ); +} + +/** + PXE + UNDI INITIALIZE + Op-Code: PXENV_UNDI_INITIALIZE (0003h) + Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the + caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call resets the adapter and programs it with default parameters. The default parameters used + are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the + receive and transmit units of the network adapter to readily receive or transmit packets. The + application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network. + This call must be made by an application to establish an interface to the network adapter driver. + Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for + the Protocol field in the parameter structure. + typedef struct { + PXENV_STATUS Status; + ADDR32 ProtocolIni; + UINT8 reserved[8]; + } PXENV_UNDI_INITIALIZE_T; + Set before calling API service + ProtocolIni: Physical address of a memory copy of the driver + module from the protocol.ini file obtained from the protocol manager + driver (refer to the NDIS 2.0 specification). This parameter is + supported for the universal NDIS driver to pass the information + contained in the protocol.ini file to the NIC driver for any specific + configuration of the NIC. (Note that the module identification in the + protocol.ini file was done by NDIS.) This value can be NULL for any + other application interfacing to the universal NIC driver + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiInitialize ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_INITIALIZE_T), + PXENV_UNDI_INITIALIZE + ); +} + +/** + Wrapper routine for reset adapter. + + PXE + UNDI RESET ADAPTER + Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h) + Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized + by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to + Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the + network. This routine cannot be used to replace Initialize or Shutdown calls. + typedef struct { + PXENV_STATUS Status; + PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; + } PXENV_UNDI_RESET_T; + + #define MAXNUM_MCADDR 8 + + typedef struct { + UINT16 MCastAddrCount; + MAC_ADDR McastAddr[MAXNUM_MCADDR]; + } PXENV_UNDI_MCAST_ADDRESS_t; + + Set before calling API service + R_Mcast_Buf: This is a structure of MCastAddrCount and + McastAddr. + MCastAddrCount: Number of multicast MAC addresses in the + buffer. + McastAddr: List of up to MAXNUM_MCADDR multicast MAC + addresses. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance. + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + @param RxFilter Filter setting mask value for PXE recive . + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiResetNic ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_RESET_T *PxeUndiTable, + IN UINT16 RxFilter + ) +{ + PXENV_UNDI_OPEN_T Open; + PXENV_UNDI_CLOSE_T Close; + UINTN Status; + + Status = MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_RESET_T), + PXENV_UNDI_RESET_NIC + ); + if (!EFI_ERROR(Status)) { + return Status; + } + + Close.Status = PXENV_STATUS_SUCCESS; + + Status = MakePxeCall ( + SimpleNetworkDevice, + &Close, + sizeof (Close), + PXENV_UNDI_CLOSE + ); + if (EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } + + Status = MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_RESET_T), + PXENV_UNDI_RESET_NIC + ); + if (EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } + + Open.Status = PXENV_STATUS_SUCCESS; + Open.OpenFlag = 0; + Open.PktFilter = RxFilter; + CopyMem ( + &Open.McastBuffer, + &PxeUndiTable->R_Mcast_Buf, + sizeof (PXENV_UNDI_MCAST_ADDR_T) + ); + + + Status = MakePxeCall ( + SimpleNetworkDevice, + &Open, + sizeof (Open), + PXENV_UNDI_OPEN + ); + if (EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + PXE + UNDI SHUTDOWN + Op-Code: PXENV_UNDI_SHUTDOWN (0005h) + Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call resets the network adapter and leaves it in a safe state for another driver to program it. + Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the + Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again. + typedef struct + { + PXENV_STATUS Status; + } PXENV_UNDI_SHUTDOWN_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiShutdown ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_SHUTDOWN_T), + PXENV_UNDI_SHUTDOWN + ); +} + +/** + PXE + UNDI OPEN + Op-Code: PXENV_UNDI_OPEN (0006h) + Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call activates the adapter network connection and sets the adapter ready to accept packets + for transmit and receive. + typedef struct { + PXENV_STATUS Status; + UINT16 OpenFlag; + UINT16 PktFilter; + #define FLTR_DIRECTED 0x0001 + #define FLTR_BRDCST 0x0002 + #define FLTR_PRMSCS 0x0004 + #define FLTR_SRC_RTG 0x0008 + PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; + } PXENV_UNDI_OPEN_T; + Set before calling API service + OpenFlag: This is an adapter specific input parameter. This is + supported for the universal NDIS 2.0 driver to pass in the open flags + provided by the protocol driver. (See the NDIS 2.0 specification.) + This can be zero. + PktFilter: Filter for receiving packets. This can be one, or more, of + the FLTR_xxx constants. Multiple values are arithmetically or-ed + together. + directed packets are packets that may come to your MAC address + or the multicast MAC address. + R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h). + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiOpen ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_OPEN_T), + PXENV_UNDI_OPEN + ); +} + +/** + PXE + UNDI CLOSE + Op-Code: PXENV_UNDI_CLOSE (0007h) + Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or + received until the network adapter is open again. + typedef struct { + PXENV_STATUS Status; + } PXENV_UNDI_CLOSE_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiClose ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_CLOSE_T), + PXENV_UNDI_CLOSE + ); +} + +/** + PXE + UNDI TRANSMIT PACKET + Op-Code: PXENV_UNDI_TRANSMIT (0008h) + Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that + has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. + The status code must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call transmits a buffer to the network. The media header + for the packet can be filled by the calling protocol, but it might not be. + The network adapter driver will fill it if required by the values in the + parameter block. The packet is buffered for transmission provided there is + an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no + buffer is available the function returns PXENV_EXIT_FAILURE with a status + code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is + implementation-dependent. An interrupt is generated on completion of the + transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is + permitted in the context of a transmit complete interrupt. + + typedef struct { + PXENV_STATUS Status; + UINT8 Protocol; + #define P_UNKNOWN 0 + #define P_IP 1 + #define P_ARP 2 + #define P_RARP 3 + UINT8 XmitFlag; + #define XMT_DESTADDR 0x0000 + #define XMT_BROADCAST 0x0001 + SEGOFF16 DestAddr; + SEGOFF16 TBD; + UINT32 Reserved[2]; + } t_PXENV_UNDI_TRANSMIT; + + #define MAX_DATA_BLKS 8 + + typedef struct { + UINT16 ImmedLength; + SEGOFF16 Xmit; + UINT16 DataBlkCount; + struct DataBlk { + UINT8 TDPtrType; + UINT8 TDRsvdByte; + UINT16 TDDataLen; + SEGOFF16 TDDataPtr; + } DataBlock[MAX_DATA_BLKS]; + } PXENV_UNDI_TBD_T + + Set before calling API service + Protocol: This is the protocol of the upper layer that is calling UNDI + TRANSMIT call. If the upper layer has filled the media header, this + field must be P_UNKNOWN. + XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a + pointer to the destination media address in the field DestAddr. If + XMT_BROADCAST, the NIC driver fills the broadcast address for the + destination. + TBD: Segment:Offset address of the transmit buffer descriptor. + ImmedLength: Length of the immediate transmit buffer: Xmit. + Xmit: Segment:Offset of the immediate transmit buffer. + DataBlkCount: Number of blocks in this transmit buffer. + TDPtrType: + 0 => 32-bit physical address in TDDataPtr (not supported in this + version of PXE) + 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit + protected mode pointer + TDRsvdByte: Reserved must be zero. + TDDatalen: Data block length in bytes. + TDDataPtr: Segment:Offset of the transmit block. + DataBlock: Array of transmit data blocks. + Returned from API service + Status: See the PXENV_STATUS_xxx constants + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiTransmit ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable + ) +{ + EFI_STATUS Status; + + Status = MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_TRANSMIT_T), + PXENV_UNDI_TRANSMIT + ); + if (Status == EFI_SUCCESS) { + return EFI_SUCCESS; + } + + switch (PxeUndiTable->Status) { + case PXENV_STATUS_OUT_OF_RESOURCES: + return EFI_NOT_READY; + + default: + return EFI_DEVICE_ERROR; + } +} + +/** + PXE + UNDI SET MULTICAST ADDRESS + Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h) + Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call changes the current list of multicast addresses to the input list and resets the network + adapter to accept it. If the number of multicast addresses is zero, multicast is disabled. + typedef struct { + PXENV_STATUS Status; + PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; + } PXENV_UNDI_SET_MCAST_ADDR_T; + Set before calling API service + R_Mcast_Buf: See description in the UNDI RESET ADAPTER + (0004h) API. + Returned from API service + Status: See the PXENV_STATUS_xxx constants + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiSetMcastAddr ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_SET_MCAST_ADDR_T), + PXENV_UNDI_SET_MCAST_ADDR + ); +} + +/** + PXE + UNDI SET STATION ADDRESS + Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah) + Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call sets the MAC address to be the input value and is called before opening the network + adapter. Later, the open call uses this variable as a temporary MAC address to program the + adapter individual address registers. + typedef struct { + PXENV_STATUS Status; + MAC_ADDR StationAddress; + } PXENV_UNDI_SET_STATION_ADDR_T; + Set before calling API service + StationAddress: Temporary MAC address to be used for + transmit and receive. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiSetStationAddr ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_SET_STATION_ADDR_T), + PXENV_UNDI_SET_STATION_ADDR + ); +} + +/** + PXE + UNDI SET PACKET FILTER + Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh) + Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with + the open call. + typedef struct { + PXENV_STATUS Status; + UINT8 filter; + } PXENV_UNDI_SET_PACKET_FILTER_T; + Set before calling API service + Filter: See the receive filter values in the UNDI OPEN + (0006h) API description. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiSetPacketFilter ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_SET_PACKET_FILTER_T), + PXENV_UNDI_SET_PACKET_FILTER + ); +} + +/** + PXE + UNDI GET INFORMATION + Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch) + Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call copies the network adapter variables, including the MAC address, into the input buffer. + Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and + PXENV_UNDI_STARTUP have been issued. All other fields must be valid after + PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been + called. + typedef struct { + PXENV_STATUS Status; + UINT16 BaseIo; + UINT16 IntNumber; + UINT16 MaxTranUnit; + UINT16 HwType; + #define ETHER_TYPE 1 + #define EXP_ETHER_TYPE 2 + #define IEEE_TYPE 6 + #define ARCNET_TYPE 7 + UINT16 HwAddrLen; + MAC_ADDR CurrentNodeAddress; + MAC_ADDR PermNodeAddress; + SEGSEL ROMAddress; + UINT16 RxBufCt; + UINT16 TxBufCt; + } PXENV_UNDI_GET_INFORMATION_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + BaseIO: Adapter base I/O address. + IntNumber: Adapter IRQ number. + MaxTranUnit: Adapter maximum transmit unit. + HWType: Type of protocol at the hardware level. + HWAddrLen: Length of the hardware address. + CurrentNodeAddress: Current hardware address. + PermNodeAddress: Permanent hardware address. + ROMAddress: Real mode ROM segment address. + RxBufCnt: Receive queue length. + TxBufCnt: Transmit queue length. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetInformation ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_GET_INFORMATION_T), + PXENV_UNDI_GET_INFORMATION + ); +} + +/** + PXE + UNDI GET STATISTICS + Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh) + Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized + by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call reads statistical information from the network adapter, and returns. + typedef struct { + PXENV_STATUS Status; + UINT32 XmtGoodFrames; + UINT32 RcvGoodFrames; + UINT32 RcvCRCErrors; + UINT32 RcvResourceErrors; + } PXENV_UNDI_GET_STATISTICS_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + XmtGoodFrames: Number of successful transmissions. + RcvGoodFrames: Number of good frames received. + RcvCRCErrors: Number of frames received with CRC + error. + RcvResourceErrors: Number of frames discarded + because receive queue was full. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetStatistics ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_GET_STATISTICS_T), + PXENV_UNDI_GET_STATISTICS + ); +} + +/** + PXE + UNDI CLEAR STATISTICS + Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh) + Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call clears the statistical information from the network adapter. + typedef struct { + PXENV_STATUS Status; + } PXENV_UNDI_CLEAR_STATISTICS_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiClearStatistics ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_CLEAR_STATISTICS_T), + PXENV_UNDI_CLEAR_STATISTICS + ); +} + +/** + PXE + UNDI INITIATE DIAGS + Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh) + Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the + PXENV_STATUS_xxx constants. + Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run + hardware diagnostics and to update its status information. + typedef struct { + PXENV_STATUS Status; + } PXENV_UNDI_INITIATE_DIAGS_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiInitiateDiags ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_INITIATE_DIAGS_T), + PXENV_UNDI_INITIATE_DIAGS + ); +} + +/** + PXE + UNDI FORCE INTERRUPT + Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h) + Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been + initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the + network adapter driver usually queues the packet and calls the application's callback receive + routine with a pointer to the packet received. Then, the callback routine either can copy the packet + to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied, + the network adapter driver does not remove it from the input queue. When the application wants to + copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive + interrupt. + typedef struct { + PXENV_STATUS Status; + } PXENV_UNDI_FORCE_INTERRUPT_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiForceInterrupt ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_FORCE_INTERRUPT_T), + PXENV_UNDI_FORCE_INTERRUPT + ); +} + +/** + PXE + UNDI GET MULTICAST ADDRESS + Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h) + Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized + by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This call converts the given IP multicast address to a hardware multicast address. + typedef struct { + PXENV_STATUS Status; + IP4 InetAddr; + MAC_ADDR MediaAddr; + } PXENV_UNDI_GET_MCAST_ADDR_T; + Set before calling API service + InetAddr: IP multicast address. + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + MediaAddr: MAC multicast address. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetMcastAddr ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_GET_MCAST_ADDR_T), + PXENV_UNDI_GET_MCAST_ADDR + ); +} + +/** + PXE + UNDI GET NIC TYPE + Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h) + Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE parameter structure that has been initialized by + the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the + NIC information. + Description: This call, if successful, provides the NIC-specific information necessary to identify the network + adapter that is used to boot the system. + Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if + the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific + information can be obtained from the DHCPDISCOVER packet itself. + PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called + before the information provided is valid. + typedef { + PXENV_STATUS Status; + UINT8 NicType; + #define PCI_NIC 2 + #define PnP_NIC 3 + #define CardBus_NIC 4 + Union { + Struct { + UINT16 Vendor_ID; + UINT16 Dev_ID; + UINT8 Base_Class; + UINT8 Sub_Class; + UINT8 Prog_Intf; + UINT8 Rev; + UINT16 BusDevFunc; + UINT16 SubVendor_ID; + UINT16 SubDevice_ID; + } pci, cardbus; + struct { + UINT32 EISA_Dev_ID; + UINT8 Base_Class; + UINT8 Sub_Class; + UINT8 Prog_Intf; + UINT16 CardSelNum; + } pnp; + } info; + } PXENV_UNDI_GET_NIC_TYPE_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + NICType: Type of NIC information stored in the parameter + structure. + Info: Information about the fields in this union can be found + in the [PnP] and [PCI] specifications + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetNicType ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_GET_NIC_TYPE_T), + PXENV_UNDI_GET_NIC_TYPE + ); +} + +/** + PXE + UNDI GET IFACE INFO + Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h) + Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized + by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the + interface specific information. + Description: This call, if successful, provides the network interface specific information such as the interface + type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the + universal drivers such as NDIS or Miniport to communicate to the upper protocol modules. + Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the + universal driver to translate/convert this information into a format that is required in its specification + or to suit the expectation of the upper level protocol modules. + PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called + before the information provided is valid. + typedef struct { + PXENV_STATUS Status + UINT8 IfaceType[16]; + UINT32 LinkSpeed; + UINT32 ServiceFlags; + UINT32 Reserved[4]; + } PXENV_UNDI_GET_NDIS_INFO_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + IfaceType: Name of MAC type in ASCIIZ format. This is + used by the universal NDIS driver to specify its driver type + to the protocol driver. + LinkSpeed: Defined in the NDIS 2.0 specification. + ServiceFlags: Defined in the NDIS 2.0 specification. + Reserved: Must be zero. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetNdisInfo ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_GET_NDIS_INFO_T), + PXENV_UNDI_GET_NDIS_INFO + ); +} + +/** + PXE + UNDI ISR + Op-Code: PXENV_UNDI_ISR (0014h) + Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in + the parameter block indicates the operation to be performed for the call. This field is filled with the + status of that operation on return. + Note: Interrupt Service Routine Operation: + In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the + application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR + API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing + (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT). + When the Network Interface HW generates an interrupt the protocol driver interrupt service + routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then + calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for + the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface + level and read any status values required to further process the interrupt. UNDI must return as + quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or + PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the + interrupt was generated by this particular Network Interface or not. + If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was + not generated by our NIC, and interrupt processing is complete. + If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start + a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is + now complete. + The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to + PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and + return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the + first buffer pointer of that frame in the parameter block. + The protocol driver calls UNDI repeatedly with the FuncFlag equal to + PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received + frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l + remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous + buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter + block. Otherwise it must return the first buffer in the next frame. + If there is no received frame pending to be processed, UNDI processes the transmit completes and + if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the + NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag. + IMPORTANT: It is possible for the protocol driver to be interrupted again while in the + strategy routine when the UNDI re-enables interrupts. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiIsr ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_ISR_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_ISR_T), + PXENV_UNDI_ISR + ); +} + +/** + PXE + STOP UNDI + Op-Code: PXENV_STOP_UNDI (0015h) + Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This routine is responsible for unhooking the Int 1Ah service routine. + Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid + status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from + base memory. Also, UNDI must not be removed from base memory if BC is not removed from base + memory. + Service cannot be used in protected mode. + typedef struct { + PXENV_STATUS Status; + } PXENV_STOP_UNDI_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiStop ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_STOP_UNDI_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_STOP_UNDI_T), + PXENV_STOP_UNDI + ); +} + +/** + PXE + UNDI GET STATE + Op-Code: PXENV_UNDI_GET_STATE (0015h) + Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state + constants + Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call + sequences + typedef struct { + #define PXE_UNDI_GET_STATE_STARTED 1 + #define PXE_UNDI_GET_STATE_INITIALIZED 2 + #define PXE_UNDI_GET_STATE_OPENED 3 + PXENV_STATUS Status; + UINT8 UNDIstate; + } PXENV_UNDI_GET_STATE_T; + Set before calling API service + N/A + Returned from API service + Status: See the PXENV_STATUS_xxx constants. + State: See definitions of the state constants. + Note. UNDI implementation is responsible for maintaining + internal state machine. + UNDI ISR + Op-Code: PXENV_UNDI_ISR (0014h) + Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller. + Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in + the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx + constants. + Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in + the parameter block indicates the operation to be performed for the call. This field is filled with the + status of that operation on return. + + @param SimpleNetworkDevice Device instance + @param PxeUndiTable Point to structure which hold paramter and return value + for option ROM call. + + @return Return value of PXE option ROM far call. +**/ +EFI_STATUS +PxeUndiGetState ( + IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, + IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable + ) +{ + return MakePxeCall ( + SimpleNetworkDevice, + PxeUndiTable, + sizeof (PXENV_UNDI_GET_STATE_T), + PXENV_UNDI_GET_STATE + ); +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf new file mode 100644 index 0000000000..2e6b0c532d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf @@ -0,0 +1,73 @@ +## @file +# SNP driver On Legacy NIC ROM. +# +# Thunk wrapper UEFI driver to produce EFI SNP protocol based on legacy 16 NIC ROM. +# +# 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 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] + BASE_NAME = BiosSnp16 + MODULE_UNI_FILE = BiosSnp16.uni + FILE_GUID = D0CAA91E-2DE4-4b0d-B3DC-09C67E854E34 + MODULE_TYPE = UEFI_DRIVER + INF_VERSION = 0x00010005 + VERSION_STRING = 1.0 + + ENTRY_POINT = BiosSnp16DriverEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gBiosSnp16DriverBinding +# COMPONENT_NAME = gBiosSnp16ComponentName +# + +[Sources] + BiosSnp16.h + BiosSnp16.c + Misc.c + Pxe.h + PxeUndi.c + ComponentName.c + + +[Libraryclasses] + UefiDriverEntryPoint + DebugLib + BaseMemoryLib + UefiBootServicesTableLib + UefiLib + BaseLib + DevicePathLib + MemoryAllocationLib + +[Guids] + gEfiEventExitBootServicesGuid ##CONSUMES ##Event + +[Protocols] + gEfiNetworkInterfaceIdentifierProtocolGuid ##BY_START + gEfiDevicePathProtocolGuid ##BY_START + gEfiDevicePathProtocolGuid ##TO_START + gEfiSimpleNetworkProtocolGuid ##BY_START + gEfiPciIoProtocolGuid ##TO_START + gEfiLegacyBiosProtocolGuid ##CONSUMES + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[UserExtensions.TianoCore."ExtraFiles"] + BiosSnp16Extra.uni diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c new file mode 100644 index 0000000000..f1c8b29508 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c @@ -0,0 +1,3296 @@ +/** @file + ConsoleOut Routines that speak VGA. + +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 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 "BiosVideo.h" + +// +// EFI Driver Binding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = { + BiosVideoDriverBindingSupported, + BiosVideoDriverBindingStart, + BiosVideoDriverBindingStop, + 0x3, + NULL, + NULL +}; + +// +// Global lookup tables for VGA graphics modes +// +UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; + +UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + +UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +// +// Save controller attributes during first start +// +UINT64 mOriginalPciAttributes; +BOOLEAN mPciAttributesSaved = FALSE; + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = { + { 0x00, 0x00, 0x00, 0x00 }, + { 0x98, 0x00, 0x00, 0x00 }, + { 0x00, 0x98, 0x00, 0x00 }, + { 0x98, 0x98, 0x00, 0x00 }, + { 0x00, 0x00, 0x98, 0x00 }, + { 0x98, 0x00, 0x98, 0x00 }, + { 0x00, 0x98, 0x98, 0x00 }, + { 0x98, 0x98, 0x98, 0x00 }, + { 0x10, 0x10, 0x10, 0x00 }, + { 0xff, 0x10, 0x10, 0x00 }, + { 0x10, 0xff, 0x10, 0x00 }, + { 0xff, 0xff, 0x10, 0x00 }, + { 0x10, 0x10, 0xff, 0x00 }, + { 0xf0, 0x10, 0xff, 0x00 }, + { 0x10, 0xff, 0xff, 0x00 }, + { 0xff, 0xff, 0xff, 0x00 } +}; + +// +// Standard timing defined by VESA EDID +// +VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = { + // + // Established Timing I + // + {800, 600, 60}, + {800, 600, 56}, + {640, 480, 75}, + {640, 480, 72}, + {640, 480, 67}, + {640, 480, 60}, + {720, 400, 88}, + {720, 400, 70}, + // + // Established Timing II + // + {1280, 1024, 75}, + {1024, 768, 75}, + {1024, 768, 70}, + {1024, 768, 60}, + {1024, 768, 87}, + {832, 624, 75}, + {800, 600, 75}, + {800, 600, 72}, + // + // Established Timing III + // + {1152, 870, 75} +}; + +/** + Supported. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a device + path + + @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this + driver, Otherwise, this controller cannot be + managed by this driver + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + EFI_DEV_PATH *Node; + + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + 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; + } + + if (Status == EFI_ALREADY_STARTED) { + // + // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure, + // because VgaMiniPort protocol is installed on controller handle directly. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + } + // + // See if this is a PCI Graphics Controller by looking at the Command register and + // Class Code Register + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = EFI_UNSUPPORTED; + if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) { + + Status = EFI_SUCCESS; + // + // If this is a graphics controller, + // go further check RemainingDevicePath validation + // + if (RemainingDevicePath != NULL) { + Node = (EFI_DEV_PATH *) RemainingDevicePath; + // + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, return EFI_SUCCESS + // + if (!IsDevicePathEnd (Node)) { + // + // If RemainingDevicePath isn't the End of Device Path Node, + // check its validation + // + if (Node->DevPath.Type != ACPI_DEVICE_PATH || + Node->DevPath.SubType != ACPI_ADR_DP || + DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) { + Status = EFI_UNSUPPORTED; + } + } + } + } + +Done: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + + +/** + Install Graphics Output Protocol onto VGA device handles. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a device + path + + @return EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Flags; + UINT64 Supports; + + // + // Initialize local variables + // + PciIo = NULL; + ParentDevicePath = NULL; + + // + // + // See if the Legacy BIOS Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Prepare for status code + // + Status = gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open the IO Abstraction(s) needed + // + 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; + } + + // + // Save original PCI attributes + // + if (!mPciAttributesSaved) { + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationGet, + 0, + &mOriginalPciAttributes + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + mPciAttributesSaved = TRUE; + } + + // + // Get supported PCI attributes + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16); + if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE, + ParentDevicePath + ); + // + // Enable the device and make sure VGA cycles are being forwarded to this VGA device + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Supports, + NULL + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT, + ParentDevicePath + ); + goto Done; + } + // + // Check to see if there is a legacy option ROM image associated with this PCI device + // + Status = LegacyBios->CheckPciRom ( + LegacyBios, + Controller, + NULL, + NULL, + &Flags + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Post the legacy option ROM if it is available. + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_P_PC_RESET, + ParentDevicePath + ); + Status = LegacyBios->InstallPciRom ( + LegacyBios, + Controller, + NULL, + &Flags, + NULL, + NULL, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + ParentDevicePath + ); + goto Done; + } + + if (RemainingDevicePath != NULL) { + if (IsDevicePathEnd (RemainingDevicePath) && + (FeaturePcdGet (PcdBiosVideoCheckVbeEnable) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable))) { + // + // If RemainingDevicePath is the End of Device Path Node, + // don't create any child device and return EFI_SUCESS + Status = EFI_SUCCESS; + goto Done; + } + } + + // + // Create child handle and install GraphicsOutputProtocol on it + // + Status = BiosVideoChildHandleInstall ( + This, + Controller, + PciIo, + LegacyBios, + ParentDevicePath, + RemainingDevicePath + ); + +Done: + if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE, + ParentDevicePath + ); + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED, + ParentDevicePath + ); + if (!HasChildHandle (Controller)) { + if (mPciAttributesSaved) { + // + // Restore original PCI attributes + // + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + mOriginalPciAttributes, + NULL + ); + } + } + // + // Release PCI I/O Protocols on the controller handle. + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + return Status; +} + + +/** + Stop. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param NumberOfChildren Number of children handle created by this driver + @param ChildHandleBuffer Buffer containing child handle created + + @retval EFI_SUCCESS Driver disconnected successfully from controller + @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + BOOLEAN AllChildrenStopped; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + + AllChildrenStopped = TRUE; + + if (NumberOfChildren == 0) { + // + // Close PCI I/O protocol on the controller handle + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + for (Index = 0; Index < NumberOfChildren; Index++) { + Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]); + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + if (!HasChildHandle (Controller)) { + if (mPciAttributesSaved) { + Status = gBS->HandleProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Restore original PCI attributes + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + mOriginalPciAttributes, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + } + + + return EFI_SUCCESS; +} + + +/** + Install child handles if the Handle supports MBR format. + + @param This Calling context. + @param ParentHandle Parent Handle + @param ParentPciIo Parent PciIo interface + @param ParentLegacyBios Parent LegacyBios interface + @param ParentDevicePath Parent Device Path + @param RemainingDevicePath Remaining Device Path + + @retval EFI_SUCCESS If a child handle was added + @retval other A child handle was not added + +**/ +EFI_STATUS +BiosVideoChildHandleInstall ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_PCI_IO_PROTOCOL *ParentPciIo, + IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + BIOS_VIDEO_DEV *BiosVideoPrivate; + PCI_TYPE00 Pci; + ACPI_ADR_DEVICE_PATH AcpiDeviceNode; + BOOLEAN ProtocolInstalled; + + // + // Allocate the private device structure for video device + // + BiosVideoPrivate = (BIOS_VIDEO_DEV *) AllocateZeroPool ( + sizeof (BIOS_VIDEO_DEV) + ); + if (NULL == BiosVideoPrivate) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // See if this is a VGA compatible controller or not + // + Status = ParentPciIo->Pci.Read ( + ParentPciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + ParentDevicePath + ); + goto Done; + } + BiosVideoPrivate->VgaCompatible = FALSE; + if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) { + BiosVideoPrivate->VgaCompatible = TRUE; + } + + if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) { + BiosVideoPrivate->VgaCompatible = TRUE; + } + + if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) { + // + // Create EXIT_BOOT_SERIVES Event + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + BiosVideoNotifyExitBootServices, + BiosVideoPrivate, + &gEfiEventExitBootServicesGuid, + &BiosVideoPrivate->ExitBootServicesEvent + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + + // + // Initialize the child private structure + // + BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE; + + // + // Fill in Graphics Output specific mode structures + // + BiosVideoPrivate->HardwareNeedsStarting = TRUE; + BiosVideoPrivate->ModeData = NULL; + BiosVideoPrivate->LineBuffer = NULL; + BiosVideoPrivate->VgaFrameBuffer = NULL; + BiosVideoPrivate->VbeFrameBuffer = NULL; + + // + // Fill in the Graphics Output Protocol + // + BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode; + BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode; + + + // + // Allocate buffer for Graphics Output Protocol mode information + // + BiosVideoPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool ( + sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE) + ); + if (NULL == BiosVideoPrivate->GraphicsOutput.Mode) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + BiosVideoPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool ( + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) + ); + if (NULL == BiosVideoPrivate->GraphicsOutput.Mode->Info) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Assume that Graphics Output Protocol will be produced until proven otherwise + // + BiosVideoPrivate->ProduceGraphicsOutput = TRUE; + + // + // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node. + // + if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) { + if (RemainingDevicePath == NULL) { + ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH)); + AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; + AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; + AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0); + SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); + + BiosVideoPrivate->GopDevicePath = AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode + ); + } else { + BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath); + } + + // + // Creat child handle and device path protocol firstly + // + BiosVideoPrivate->Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiDevicePathProtocolGuid, + BiosVideoPrivate->GopDevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + + // + // Fill in the VGA Mini Port Protocol fields + // + BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode; + BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5; + BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; + + // + // Child handle need to consume the Legacy Bios protocol + // + BiosVideoPrivate->LegacyBios = ParentLegacyBios; + + // + // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally + // + BiosVideoPrivate->PciIo = ParentPciIo; + + // + // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output + // + if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable)) { + Status = BiosVideoCheckForVbe (BiosVideoPrivate); + DEBUG ((EFI_D_INFO, "BiosVideoCheckForVbe - %r\n", Status)); + } else { + Status = EFI_UNSUPPORTED; + } + if (EFI_ERROR (Status)) { + // + // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support + // for the standard 640x480 16 color VGA mode + // + DEBUG ((EFI_D_INFO, "VgaCompatible - %x\n", BiosVideoPrivate->VgaCompatible)); + if (BiosVideoPrivate->VgaCompatible) { + if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable)) { + Status = BiosVideoCheckForVga (BiosVideoPrivate); + DEBUG ((EFI_D_INFO, "BiosVideoCheckForVga - %r\n", Status)); + } else { + Status = EFI_UNSUPPORTED; + } + } + + if (EFI_ERROR (Status)) { + // + // Free GOP mode structure if it is not freed before + // VgaMiniPort does not need this structure any more + // + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; + } + FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode = NULL; + } + + // + // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do + // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol. + // + BiosVideoPrivate->ProduceGraphicsOutput = FALSE; + + // + // INT services are available, so on the 80x25 and 80x50 text mode are supported + // + BiosVideoPrivate->VgaMiniPort.MaxMode = 2; + } + } + + ProtocolInstalled = FALSE; + + if (BiosVideoPrivate->ProduceGraphicsOutput) { + // + // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiGraphicsOutputProtocolGuid, + &BiosVideoPrivate->GraphicsOutput, + &gEfiEdidDiscoveredProtocolGuid, + &BiosVideoPrivate->EdidDiscovered, + &gEfiEdidActiveProtocolGuid, + &BiosVideoPrivate->EdidActive, + NULL + ); + + if (!EFI_ERROR (Status)) { + // + // Open the Parent Handle for the child + // + Status = gBS->OpenProtocol ( + ParentHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &BiosVideoPrivate->PciIo, + This->DriverBindingHandle, + BiosVideoPrivate->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + ProtocolInstalled = TRUE; + } + } + + if (!ProtocolInstalled) { + // + // Install VGA Mini Port Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ParentHandle, + &gEfiVgaMiniPortProtocolGuid, + &BiosVideoPrivate->VgaMiniPort, + NULL + ); + } + +Done: + if (EFI_ERROR (Status)) { + if ((BiosVideoPrivate != NULL) && (BiosVideoPrivate->ExitBootServicesEvent != NULL)) { + gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent); + } + // + // Free private data structure + // + BiosVideoDeviceReleaseResource (BiosVideoPrivate); + } + + return Status; +} + + +/** + Deregister an video child handle and free resources. + + @param This Protocol instance pointer. + @param Controller Video controller handle + @param Handle Video child handle + + @return EFI_STATUS + +**/ +EFI_STATUS +BiosVideoChildHandleUninstall ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET Regs; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_PCI_IO_PROTOCOL *PciIo; + + BiosVideoPrivate = NULL; + GraphicsOutput = NULL; + PciIo = NULL; + Status = EFI_UNSUPPORTED; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput); + } + + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Handle, + &gEfiVgaMiniPortProtocolGuid, + (VOID **) &VgaMiniPort, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort); + } + } + + if (BiosVideoPrivate == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x03; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x14; + Regs.H.BL = 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + // + // Close PCI I/O protocol that opened by child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Uninstall protocols on child handle + // + if (BiosVideoPrivate->ProduceGraphicsOutput) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + BiosVideoPrivate->Handle, + &gEfiDevicePathProtocolGuid, + BiosVideoPrivate->GopDevicePath, + &gEfiGraphicsOutputProtocolGuid, + &BiosVideoPrivate->GraphicsOutput, + &gEfiEdidDiscoveredProtocolGuid, + &BiosVideoPrivate->EdidDiscovered, + &gEfiEdidActiveProtocolGuid, + &BiosVideoPrivate->EdidActive, + NULL + ); + } + if (!BiosVideoPrivate->ProduceGraphicsOutput) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + &BiosVideoPrivate->VgaMiniPort, + NULL + ); + } + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + return Status; + } + + if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) { + // + // Close EXIT_BOOT_SERIVES Event + // + gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent); + } + + // + // Release all allocated resources + // + BiosVideoDeviceReleaseResource (BiosVideoPrivate); + + return EFI_SUCCESS; +} + + +/** + Release resource for biso video instance. + + @param BiosVideoPrivate Video child device private data structure + +**/ +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + if (BiosVideoPrivate == NULL) { + return ; + } + + // + // Release all the resourses occupied by the BIOS_VIDEO_DEV + // + + // + // Free VGA Frame Buffer + // + if (BiosVideoPrivate->VgaFrameBuffer != NULL) { + FreePool (BiosVideoPrivate->VgaFrameBuffer); + } + // + // Free VBE Frame Buffer + // + if (BiosVideoPrivate->VbeFrameBuffer != NULL) { + FreePool (BiosVideoPrivate->VbeFrameBuffer); + } + // + // Free line buffer + // + if (BiosVideoPrivate->LineBuffer != NULL) { + FreePool (BiosVideoPrivate->LineBuffer); + } + // + // Free mode data + // + if (BiosVideoPrivate->ModeData != NULL) { + FreePool (BiosVideoPrivate->ModeData); + } + // + // Free memory allocated below 1MB + // + if (BiosVideoPrivate->PagesBelow1MB != 0) { + gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB); + } + + if (BiosVideoPrivate->VbeSaveRestorePages != 0) { + gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages); + } + + // + // Free graphics output protocol occupied resource + // + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; + } + FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode = NULL; + } + // + // Free EDID discovered protocol occupied resource + // + if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) { + FreePool (BiosVideoPrivate->EdidDiscovered.Edid); + } + // + // Free EDID active protocol occupied resource + // + if (BiosVideoPrivate->EdidActive.Edid != NULL) { + FreePool (BiosVideoPrivate->EdidActive.Edid); + } + + if (BiosVideoPrivate->GopDevicePath!= NULL) { + FreePool (BiosVideoPrivate->GopDevicePath); + } + + FreePool (BiosVideoPrivate); + + return ; +} + + +/** + Generate a search key for a specified timing data. + + @param EdidTiming Pointer to EDID timing + + @return The 32 bit unique key for search. + +**/ +UINT32 +CalculateEdidKey ( + VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming + ) +{ + UINT32 Key; + + // + // Be sure no conflicts for all standard timing defined by VESA. + // + Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution; + return Key; +} + + +/** + Parse the Established Timing and Standard Timing in EDID data block. + + @param EdidBuffer Pointer to EDID data block + @param ValidEdidTiming Valid EDID timing information + + @retval TRUE The EDID data is valid. + @retval FALSE The EDID data is invalid. + +**/ +BOOLEAN +ParseEdidData ( + UINT8 *EdidBuffer, + VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming + ) +{ + UINT8 CheckSum; + UINT32 Index; + UINT32 ValidNumber; + UINT32 TimingBits; + UINT8 *BufferIndex; + UINT16 HorizontalResolution; + UINT16 VerticalResolution; + UINT8 AspectRatio; + UINT8 RefreshRate; + VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming; + VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock; + + EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer; + + // + // Check the checksum of EDID data + // + CheckSum = 0; + for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) { + CheckSum = (UINT8) (CheckSum + EdidBuffer[Index]); + } + if (CheckSum != 0) { + return FALSE; + } + + ValidNumber = 0; + gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0); + + if ((EdidDataBlock->EstablishedTimings[0] != 0) || + (EdidDataBlock->EstablishedTimings[1] != 0) || + (EdidDataBlock->EstablishedTimings[2] != 0) + ) { + // + // Established timing data + // + TimingBits = EdidDataBlock->EstablishedTimings[0] | + (EdidDataBlock->EstablishedTimings[1] << 8) | + ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ; + for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) { + if ((TimingBits & 0x1) != 0) { + DEBUG ((EFI_D_INFO, "Established Timing: %d x %d\n", + mEstablishedEdidTiming[Index].HorizontalResolution, mEstablishedEdidTiming[Index].VerticalResolution)); + ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]); + ValidNumber ++; + } + TimingBits = TimingBits >> 1; + } + } + + // + // Parse the standard timing data + // + BufferIndex = &EdidDataBlock->StandardTimingIdentification[0]; + for (Index = 0; Index < 8; Index ++) { + // + // Check if this is a valid Standard Timing entry + // VESA documents unused fields should be set to 01h + // + if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){ + // + // A valid Standard Timing + // + HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248); + AspectRatio = (UINT8) (BufferIndex[1] >> 6); + switch (AspectRatio) { + case 0: + VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10); + break; + case 1: + VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3); + break; + case 2: + VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4); + break; + case 3: + VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9); + break; + default: + VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3); + break; + } + RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60); + DEBUG ((EFI_D_INFO, "Standard Timing: %d x %d\n", HorizontalResolution, VerticalResolution)); + TempTiming.HorizontalResolution = HorizontalResolution; + TempTiming.VerticalResolution = VerticalResolution; + TempTiming.RefreshRate = RefreshRate; + ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming); + ValidNumber ++; + } + BufferIndex += 2; + } + + // + // Parse the Detailed Timing data + // + BufferIndex = &EdidDataBlock->DetailedTimingDescriptions[0]; + for (Index = 0; Index < 4; Index ++, BufferIndex += VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE) { + if ((BufferIndex[0] == 0x0) && (BufferIndex[1] == 0x0)) { + // + // Check if this is a valid Detailed Timing Descriptor + // If first 2 bytes are zero, it is monitor descriptor other than detailed timing descriptor + // + continue; + } + // + // Calculate Horizontal and Vertical resolution + // + TempTiming.HorizontalResolution = ((UINT16)(BufferIndex[4] & 0xF0) << 4) | (BufferIndex[2]); + TempTiming.VerticalResolution = ((UINT16)(BufferIndex[7] & 0xF0) << 4) | (BufferIndex[5]); + DEBUG ((EFI_D_INFO, "Detailed Timing %d: %d x %d\n", + Index, TempTiming.HorizontalResolution, TempTiming.VerticalResolution)); + ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming); + ValidNumber ++; + } + + ValidEdidTiming->ValidNumber = ValidNumber; + return TRUE; +} + + +/** + Search a specified Timing in all the valid EDID timings. + + @param ValidEdidTiming All valid EDID timing information. + @param EdidTiming The Timing to search for. + + @retval TRUE Found. + @retval FALSE Not found. + +**/ +BOOLEAN +SearchEdidTiming ( + VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming, + VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming + ) +{ + UINT32 Index; + UINT32 Key; + + Key = CalculateEdidKey (EdidTiming); + + for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) { + if (Key == ValidEdidTiming->Key[Index]) { + return TRUE; + } + } + + return FALSE; +} + +/** + Check if all video child handles have been uninstalled. + + @param Controller Video controller handle + + @return TRUE Child handles exist. + @return FALSE All video child handles have been uninstalled. + +**/ +BOOLEAN +HasChildHandle ( + IN EFI_HANDLE Controller + ) +{ + UINTN Index; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + BOOLEAN HasChild; + + EntryCount = 0; + HasChild = FALSE; + gBS->OpenProtocolInformation ( + Controller, + &gEfiPciIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + for (Index = 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + HasChild = TRUE; + } + } + + return HasChild; +} + +/** + Check for VBE device. + + @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS VBE device found + +**/ +EFI_STATUS +BiosVideoCheckForVbe ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET Regs; + UINT16 *ModeNumberPtr; + UINT16 VbeModeNumber; + BOOLEAN ModeFound; + BOOLEAN EdidFound; + BIOS_VIDEO_MODE_DATA *ModeBuffer; + BIOS_VIDEO_MODE_DATA *CurrentModeData; + UINTN PreferMode; + UINTN ModeNumber; + VESA_BIOS_EXTENSIONS_EDID_TIMING Timing; + VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming; + EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride; + UINT32 EdidAttributes; + BOOLEAN EdidOverrideFound; + UINTN EdidOverrideDataSize; + UINT8 *EdidOverrideDataBlock; + UINTN EdidActiveDataSize; + UINT8 *EdidActiveDataBlock; + UINT32 HighestHorizontalResolution; + UINT32 HighestVerticalResolution; + UINTN HighestResolutionMode; + + EdidFound = TRUE; + EdidOverrideFound = FALSE; + EdidOverrideDataBlock = NULL; + EdidActiveDataSize = 0; + EdidActiveDataBlock = NULL; + HighestHorizontalResolution = 0; + HighestVerticalResolution = 0; + HighestResolutionMode = 0; + + // + // Allocate buffer under 1MB for VBE data structures + // + BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES ( + sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK) + ); + + BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1; + + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + BiosVideoPrivate->NumberOfPagesBelow1MB, + &BiosVideoPrivate->PagesBelow1MB + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING)); + + // + // Fill in the VBE related data structures + // + BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB); + BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1); + BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1); + BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1); + BiosVideoPrivate->VbeSaveRestorePages = 0; + BiosVideoPrivate->VbeSaveRestoreBuffer = 0; + + // + // Test to see if the Video Adapter is compliant with VBE 3.0 + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION; + gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0); + BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE; + Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Status = EFI_DEVICE_ERROR; + + // + // See if the VESA call succeeded + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + return Status; + } + // + // Check for 'VESA' signature + // + if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) { + return Status; + } + // + // Check to see if this is VBE 2.0 or higher + // + if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) { + return Status; + } + + EdidFound = FALSE; + EdidAttributes = 0xff; + EdidOverrideDataSize = 0; + + // + // Find EDID Override protocol firstly, this protocol is installed by platform if needed. + // + Status = gBS->LocateProtocol ( + &gEfiEdidOverrideProtocolGuid, + NULL, + (VOID **) &EdidOverride + ); + if (!EFI_ERROR (Status)) { + // + // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow + // + EdidOverrideDataBlock = AllocatePool (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2); + if (NULL == EdidOverrideDataBlock) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status = EdidOverride->GetEdid ( + EdidOverride, + BiosVideoPrivate->Handle, + &EdidAttributes, + &EdidOverrideDataSize, + (UINT8 **) &EdidOverrideDataBlock + ); + if (!EFI_ERROR (Status) && + EdidAttributes == 0 && + EdidOverrideDataSize != 0) { + // + // Succeeded to get EDID Override Data + // + EdidOverrideFound = TRUE; + } + } + + if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) { + // + // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned, + // read EDID information through INT10 call + // + + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID; + Regs.X.BX = 1; + Regs.X.CX = 0; + Regs.X.DX = 0; + Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + // + // See if the VESA call succeeded + // + if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + // + // Set EDID Discovered Data + // + BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; + BiosVideoPrivate->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool ( + VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE, + BiosVideoPrivate->VbeEdidDataBlock + ); + + if (NULL == BiosVideoPrivate->EdidDiscovered.Edid) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + EdidFound = TRUE; + } + } + + if (EdidFound) { + EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; + EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid; + } else if (EdidOverrideFound) { + EdidActiveDataSize = EdidOverrideDataSize; + EdidActiveDataBlock = EdidOverrideDataBlock; + EdidFound = TRUE; + } + + if (EdidFound) { + // + // Parse EDID data structure to retrieve modes supported by monitor + // + if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) { + // + // Copy EDID Override Data to EDID Active Data + // + BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize; + BiosVideoPrivate->EdidActive.Edid = (UINT8 *) AllocateCopyPool ( + EdidActiveDataSize, + EdidActiveDataBlock + ); + if (NULL == BiosVideoPrivate->EdidActive.Edid) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + } + } else { + BiosVideoPrivate->EdidActive.SizeOfEdid = 0; + BiosVideoPrivate->EdidActive.Edid = NULL; + EdidFound = FALSE; + } + + // + // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode + // + ModeNumberPtr = (UINT16 *) + ( + (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) | + ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff) + ); + + PreferMode = 0; + ModeNumber = 0; + + // + // ModeNumberPtr may be not 16-byte aligned, so ReadUnaligned16 is used to access the buffer pointed by ModeNumberPtr. + // + for (VbeModeNumber = ReadUnaligned16 (ModeNumberPtr); + VbeModeNumber != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; + VbeModeNumber = ReadUnaligned16 (++ModeNumberPtr)) { + // + // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number. + // + if ((VbeModeNumber & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) { + continue; + } + // + // Get the information about the mode + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION; + Regs.X.CX = VbeModeNumber; + gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0); + Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + // + // See if the call succeeded. If it didn't, then try the next mode. + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + continue; + } + // + // See if the mode supports color. If it doesn't then try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) { + continue; + } + // + // See if the mode supports graphics. If it doesn't then try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) { + continue; + } + // + // See if the mode supports a linear frame buffer. If it doesn't then try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) { + continue; + } + // + // See if the mode supports 32 bit color. If it doesn't then try the next mode. + // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the + // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel + // + if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) { + continue; + } + + if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) { + continue; + } + + if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) { + continue; + } + // + // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode. + // + if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) { + continue; + } + + DEBUG ((EFI_D_INFO, "Video Controller Mode 0x%x: %d x %d\n", + VbeModeNumber, BiosVideoPrivate->VbeModeInformationBlock->XResolution, BiosVideoPrivate->VbeModeInformationBlock->YResolution)); + + if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) { + // + // EDID exist, check whether this mode match with any mode in EDID + // + Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; + Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; + if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) { + // + // When EDID comes from INT10 call, EDID does not include 800x600, 640x480 and 1024x768, + // but INT10 can support these modes, we add them into GOP mode. + // + if ((BiosVideoPrivate->EdidDiscovered.SizeOfEdid != 0) && + !((Timing.HorizontalResolution) == 1024 && (Timing.VerticalResolution == 768)) && + !((Timing.HorizontalResolution) == 800 && (Timing.VerticalResolution == 600)) && + !((Timing.HorizontalResolution) == 640 && (Timing.VerticalResolution == 480))) { + continue; + } + } + } + + // + // Select a reasonable mode to be set for current display mode + // + ModeFound = FALSE; + + if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 && + BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768 + ) { + ModeFound = TRUE; + } + if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 && + BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600 + ) { + ModeFound = TRUE; + PreferMode = ModeNumber; + } + if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 && + BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480 + ) { + ModeFound = TRUE; + } + + if ((!EdidFound) && (!ModeFound)) { + // + // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480 + // + continue; + } + + // + // Record the highest resolution mode to set later + // + if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution > HighestHorizontalResolution) || + ((BiosVideoPrivate->VbeModeInformationBlock->XResolution == HighestHorizontalResolution) && + (BiosVideoPrivate->VbeModeInformationBlock->YResolution > HighestVerticalResolution))) { + HighestHorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; + HighestVerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; + HighestResolutionMode = ModeNumber; + } + + // + // Add mode to the list of available modes + // + ModeNumber ++; + ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool ( + ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA) + ); + if (NULL == ModeBuffer) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + if (ModeNumber > 1) { + CopyMem ( + ModeBuffer, + BiosVideoPrivate->ModeData, + (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA) + ); + } + + if (BiosVideoPrivate->ModeData != NULL) { + FreePool (BiosVideoPrivate->ModeData); + } + + CurrentModeData = &ModeBuffer[ModeNumber - 1]; + CurrentModeData->VbeModeNumber = VbeModeNumber; + if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) { + CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine; + CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition; + CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1); + CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition; + CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1); + CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition; + CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1); + CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition; + CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1); + } else { + CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine; + CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition; + CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1); + CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition; + CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1); + CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition; + CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1); + CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition; + CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1); + } + + CurrentModeData->PixelFormat = PixelBitMask; + if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) && + (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) { + if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) { + CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor; + } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) { + CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + } + } + + CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position; + CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position; + CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position; + CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position; + + CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr; + CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; + CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; + + CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel; + CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution; + // + // Make sure the FrameBufferSize does not exceed the max available frame buffer size reported by VEB. + // + ASSERT (CurrentModeData->FrameBufferSize <= (UINTN)(BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024)); + + BiosVideoPrivate->ModeData = ModeBuffer; + } + // + // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT + // + if (ModeNumber == 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // Assign Gop's Blt function + // + BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt; + + BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = (UINT32) ModeNumber; + // + // Current mode is unknow till now, set it to an invalid mode. + // + BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; + + // + // Find the best mode to initialize + // + if ((PcdGet32 (PcdVideoHorizontalResolution) == 0x0) || (PcdGet32 (PcdVideoVerticalResolution) == 0x0)) { + DEBUG_CODE ( + BIOS_VIDEO_MODE_DATA *ModeData; + ModeData = &BiosVideoPrivate->ModeData[HighestResolutionMode]; + DEBUG ((EFI_D_INFO, "BiosVideo set highest resolution %d x %d\n", + ModeData->HorizontalResolution, ModeData->VerticalResolution)); + ); + PreferMode = HighestResolutionMode; + } + Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode); + if (EFI_ERROR (Status)) { + for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) { + Status = BiosVideoGraphicsOutputSetMode ( + &BiosVideoPrivate->GraphicsOutput, + (UINT32) PreferMode + ); + if (!EFI_ERROR (Status)) { + break; + } + } + if (PreferMode == ModeNumber) { + // + // None mode is set successfully. + // + goto Done; + } + } + +Done: + // + // If there was an error, then free the mode structure + // + if (EFI_ERROR (Status)) { + if (BiosVideoPrivate->ModeData != NULL) { + FreePool (BiosVideoPrivate->ModeData); + BiosVideoPrivate->ModeData = NULL; + BiosVideoPrivate->MaxMode = 0; + } + if (EdidOverrideDataBlock != NULL) { + FreePool (EdidOverrideDataBlock); + } + } + + return Status; +} + + +/** + Check for VGA device. + + @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS Standard VGA device found + +**/ +EFI_STATUS +BiosVideoCheckForVga ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + EFI_STATUS Status; + BIOS_VIDEO_MODE_DATA *ModeBuffer; + + Status = EFI_UNSUPPORTED; + + // + // Assign Gop's Blt function + // + BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt; + + // + // Add mode to the list of available modes + // caller should guarantee that Mode has been allocated. + // + ASSERT (BiosVideoPrivate->GraphicsOutput.Mode != NULL); + BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1; + + ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool ( + sizeof (BIOS_VIDEO_MODE_DATA) + ); + if (NULL == ModeBuffer) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + ModeBuffer->VbeModeNumber = 0x0012; + ModeBuffer->BytesPerScanLine = 640; + ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000); + ModeBuffer->HorizontalResolution = 640; + ModeBuffer->VerticalResolution = 480; + ModeBuffer->PixelFormat = PixelBltOnly; + ModeBuffer->BitsPerPixel = 8; + ModeBuffer->ColorDepth = 32; + ModeBuffer->RefreshRate = 60; + + BiosVideoPrivate->ModeData = ModeBuffer; + + // + // Test to see if the Video Adapter support the 640x480 16 color mode + // + BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; + Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0); + +Done: + // + // If there was an error, then free the mode structure + // + if (EFI_ERROR (Status)) { + if (BiosVideoPrivate->ModeData != NULL) { + FreePool (BiosVideoPrivate->ModeData); + BiosVideoPrivate->ModeData = NULL; + } + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; + } + FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode = NULL; + } + } + return Status; +} + +// +// Graphics Output Protocol Member Functions for VESA BIOS Extensions +// + +/** + Graphics Output protocol interface to get video mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info + buffer. + @param Info Caller allocated buffer that returns information + about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the + video mode. + @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 +BiosVideoGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + BIOS_VIDEO_MODE_DATA *ModeData; + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + if (BiosVideoPrivate->HardwareNeedsStarting) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR, + BiosVideoPrivate->GopDevicePath + ); + return EFI_NOT_STARTED; + } + + if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool ( + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) + ); + if (NULL == *Info) { + return EFI_OUT_OF_RESOURCES; + } + + *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + + ModeData = &BiosVideoPrivate->ModeData[ModeNumber]; + (*Info)->Version = 0; + (*Info)->HorizontalResolution = ModeData->HorizontalResolution; + (*Info)->VerticalResolution = ModeData->VerticalResolution; + (*Info)->PixelFormat = ModeData->PixelFormat; + CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask)); + + (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel; + + return EFI_SUCCESS; +} + +/** + Worker function to set video mode. + + @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV. + @param ModeData The mode data to be set. + @param DevicePath Pointer to Device Path Protocol. + + @retval EFI_SUCCESS Graphics mode was changed. + @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. + +**/ +EFI_STATUS +BiosVideoSetModeWorker ( + IN BIOS_VIDEO_DEV *BiosVideoPrivate, + IN BIOS_VIDEO_MODE_DATA *ModeData, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET Regs; + + if (BiosVideoPrivate->LineBuffer != NULL) { + FreePool (BiosVideoPrivate->LineBuffer); + } + + if (BiosVideoPrivate->VgaFrameBuffer != NULL) { + FreePool (BiosVideoPrivate->VgaFrameBuffer); + } + + if (BiosVideoPrivate->VbeFrameBuffer != NULL) { + FreePool (BiosVideoPrivate->VbeFrameBuffer); + } + + BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool ( + ModeData->BytesPerScanLine + ); + if (NULL == BiosVideoPrivate->LineBuffer) { + return EFI_OUT_OF_RESOURCES; + } + // + // Clear all registers + // + ZeroMem (&Regs, sizeof (Regs)); + + if (ModeData->VbeModeNumber < 0x100) { + // + // Allocate a working buffer for BLT operations to the VGA frame buffer + // + BiosVideoPrivate->VgaFrameBuffer = (UINT8 *) AllocatePool (4 * 480 * 80); + if (NULL == BiosVideoPrivate->VgaFrameBuffer) { + return EFI_OUT_OF_RESOURCES; + } + // + // Set VGA Mode + // + Regs.X.AX = ModeData->VbeModeNumber; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + } else { + // + // Allocate a working buffer for BLT operations to the VBE frame buffer + // + BiosVideoPrivate->VbeFrameBuffer = + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool ( + ModeData->BytesPerScanLine * ModeData->VerticalResolution + ); + if (NULL == BiosVideoPrivate->VbeFrameBuffer) { + return EFI_OUT_OF_RESOURCES; + } + // + // Set VBE mode + // + Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE; + Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER); + ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)); + Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock); + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + // + // Check to see if the call succeeded + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR, + DevicePath + ); + return EFI_DEVICE_ERROR; + } + // + // Initialize the state of the VbeFrameBuffer + // + Status = BiosVideoPrivate->PciIo->Mem.Read ( + BiosVideoPrivate->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) ModeData->LinearFrameBuffer, + (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2, + BiosVideoPrivate->VbeFrameBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + +/** + Graphics Output protocol interface to set video mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @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. + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ) +{ + EFI_STATUS Status; + BIOS_VIDEO_DEV *BiosVideoPrivate; + BIOS_VIDEO_MODE_DATA *ModeData; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + ModeData = &BiosVideoPrivate->ModeData[ModeNumber]; + + if (ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + if (ModeNumber == This->Mode->Mode) { + // + // Clear screen to black + // + ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + BiosVideoGraphicsOutputVbeBlt ( + This, + &Background, + EfiBltVideoFill, + 0, + 0, + 0, + 0, + ModeData->HorizontalResolution, + ModeData->VerticalResolution, + 0 + ); + return EFI_SUCCESS; + } + + Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->GopDevicePath); + if (EFI_ERROR (Status)) { + return Status; + } + + This->Mode->Mode = ModeNumber; + This->Mode->Info->Version = 0; + This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; + This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; + This->Mode->Info->PixelFormat = ModeData->PixelFormat; + CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask)); + This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel; + This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + This->Mode->FrameBufferSize = ModeData->FrameBufferSize; + This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer; + + BiosVideoPrivate->HardwareNeedsStarting = FALSE; + + return EFI_SUCCESS; +} + +/** + Update physical frame buffer, copy 4 bytes block, then copy remaining bytes. + + @param PciIo The pointer of EFI_PCI_IO_PROTOCOL + @param VbeBuffer The data to transfer to screen + @param MemAddress Physical frame buffer base address + @param DestinationX The X coordinate of the destination for BltOperation + @param DestinationY The Y coordinate of the destination for BltOperation + @param TotalBytes The total bytes of copy + @param VbePixelWidth Bytes per pixel + @param BytesPerScanLine Bytes per scan line + +**/ +VOID +CopyVideoBuffer ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 *VbeBuffer, + IN VOID *MemAddress, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN TotalBytes, + IN UINT32 VbePixelWidth, + IN UINTN BytesPerScanLine + ) +{ + UINTN FrameBufferAddr; + UINTN CopyBlockNum; + UINTN RemainingBytes; + UINTN UnalignedBytes; + EFI_STATUS Status; + + FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth; + + // + // If TotalBytes is less than 4 bytes, only start byte copy. + // + if (TotalBytes < 4) { + Status = PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + TotalBytes, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + return; + } + + // + // If VbeBuffer is not 4-byte aligned, start byte copy. + // + UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3; + + if (UnalignedBytes != 0) { + Status = PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + UnalignedBytes, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + FrameBufferAddr += UnalignedBytes; + VbeBuffer += UnalignedBytes; + } + + // + // Calculate 4-byte block count and remaining bytes. + // + CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2; + RemainingBytes = (TotalBytes - UnalignedBytes) & 3; + + // + // Copy 4-byte block and remaining bytes to physical frame buffer. + // + if (CopyBlockNum != 0) { + Status = PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + CopyBlockNum, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + } + + if (RemainingBytes != 0) { + FrameBufferAddr += (CopyBlockNum << 2); + VbeBuffer += (CopyBlockNum << 2); + Status = PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + RemainingBytes, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + } +} + +/** + Worker function to block transfer for VBE device. + + @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOperation + @param SourceY The Y coordinate of the source for BltOperation + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt rectangle in + pixels + @param Height The height of a rectangle in the blt rectangle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta of 0 is + used, the entire BltBuffer will be operated on. If + a subrectangle of the BltBuffer is used, then + Delta represents the number of bytes in a row of + the BltBuffer. + @param Mode Mode data. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +BiosVideoVbeBltWorker ( + IN BIOS_VIDEO_DEV *BiosVideoPrivate, + 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, + IN BIOS_VIDEO_MODE_DATA *Mode + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_TPL OriginalTPL; + UINTN DstY; + UINTN SrcY; + UINTN DstX; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; + VOID *MemAddress; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; + UINTN BytesPerScanLine; + UINTN Index; + UINT8 *VbeBuffer; + UINT8 *VbeBuffer1; + UINT8 *BltUint8; + UINT32 VbePixelWidth; + UINT32 Pixel; + UINTN TotalBytes; + + PciIo = BiosVideoPrivate->PciIo; + + VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer; + MemAddress = Mode->LinearFrameBuffer; + BytesPerScanLine = Mode->BytesPerScanLine; + VbePixelWidth = Mode->BitsPerPixel / 8; + BltUint8 = (UINT8 *) BltBuffer; + TotalBytes = Width * VbePixelWidth; + + if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + // + // We need to fill the Virtual Screen buffer with the blt data. + // The virtual screen is upside down, as the first row is the bootom row of + // the image. + // + if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > Mode->VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > Mode->HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > Mode->VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > Mode->HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } + // + // If Delta is zero, then the entire BltBuffer is being used, so Delta + // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, + // the number of bytes in each row can be computed. + // + if (Delta == 0) { + Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } + // + // We have to raise to TPL Notify, so we make an atomic write the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY); + + switch (BltOperation) { + case EfiBltVideoToBltBuffer: + for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) { + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + // + // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL + // + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth)); + for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { + Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24; + Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask); + Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask); + Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask); + Blt->Reserved = 0; + Blt++; + VbeBuffer += VbePixelWidth; + } + + } + break; + + case EfiBltVideoToVideo: + for (Index = 0; Index < Height; Index++) { + if (DestinationY <= SourceY) { + SrcY = SourceY + Index; + DstY = DestinationY + Index; + } else { + SrcY = SourceY + Height - Index - 1; + DstY = DestinationY + Height - Index - 1; + } + + VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth); + VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth); + + gBS->CopyMem ( + VbeBuffer, + VbeBuffer1, + TotalBytes + ); + + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + + case EfiBltVideoFill: + VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8; + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer + // + Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | + ( + (Blt->Green & Mode->Green.Mask) << + Mode->Green.Position + ) | + ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); + + for (Index = 0; Index < Width; Index++) { + gBS->CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + VbeBuffer += VbePixelWidth; + } + + VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); + for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) { + gBS->CopyMem ( + (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), + VbeBuffer, + TotalBytes + ); + } + + for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) { + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + + case EfiBltBufferToVideo: + for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) { + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); + for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer + // + Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | + ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) | + ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); + gBS->CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + Blt++; + VbeBuffer += VbePixelWidth; + } + + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); + + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + + default: ; + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} + +/** + Graphics Output protocol instance to block transfer for VBE device. + + @param This Pointer to Graphics Output protocol instance + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOperation + @param SourceY The Y coordinate of the source for BltOperation + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt rectangle in + pixels + @param Height The height of a rectangle in the blt rectangle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta of 0 is + used, the entire BltBuffer will be operated on. If + a subrectangle of the BltBuffer is used, then + Delta represents the number of bytes in a row of + the BltBuffer. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVbeBlt ( + 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 + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + BIOS_VIDEO_MODE_DATA *Mode; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode]; + + return BiosVideoVbeBltWorker ( + BiosVideoPrivate, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta, + Mode + ); +} + +/** + Write graphics controller registers. + + @param PciIo Pointer to PciIo protocol instance of the + controller + @param Address Register address + @param Data Data to be written to register + + @return None + +**/ +VOID +WriteGraphicsController ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINTN Address, + IN UINTN Data + ) +{ + Address = Address | (Data << 8); + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER, + 1, + &Address + ); +} + + +/** + Read the four bit plane of VGA frame buffer. + + @param PciIo Pointer to PciIo protocol instance of the + controller + @param HardwareBuffer Hardware VGA frame buffer address + @param MemoryBuffer Memory buffer address + @param WidthInBytes Number of bytes in a line to read + @param Height Height of the area to read + + @return None + +**/ +VOID +VgaReadBitPlanes ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 *HardwareBuffer, + UINT8 *MemoryBuffer, + UINTN WidthInBytes, + UINTN Height + ) +{ + UINTN BitPlane; + UINTN Rows; + UINTN FrameBufferOffset; + UINT8 *Source; + UINT8 *Destination; + + // + // Program the Mode Register Write mode 0, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 + ); + + for (BitPlane = 0, FrameBufferOffset = 0; + BitPlane < VGA_NUMBER_OF_BIT_PLANES; + BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE + ) { + // + // Program the Read Map Select Register to select the correct bit plane + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER, + BitPlane + ); + + Source = HardwareBuffer; + Destination = MemoryBuffer + FrameBufferOffset; + + for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Source, + WidthInBytes, + (VOID *) Destination + ); + } + } +} + + +/** + Internal routine to convert VGA color to Grahpics Output color. + + @param MemoryBuffer Buffer containing VGA color + @param CoordinateX The X coordinate of pixel on screen + @param CoordinateY The Y coordinate of pixel on screen + @param BltBuffer Buffer to contain converted Grahpics Output color + + @return None + +**/ +VOID +VgaConvertToGraphicsOutputColor ( + UINT8 *MemoryBuffer, + UINTN CoordinateX, + UINTN CoordinateY, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ) +{ + UINTN Mask; + UINTN Bit; + UINTN Color; + + MemoryBuffer += ((CoordinateY << 6) + (CoordinateY << 4) + (CoordinateX >> 3)); + Mask = mVgaBitMaskTable[CoordinateX & 0x07]; + for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) { + if ((*MemoryBuffer & Mask) != 0) { + Color |= Bit; + } + } + + *BltBuffer = mVgaColorToGraphicsOutputColor[Color]; +} + +/** + Internal routine to convert Grahpics Output color to VGA color. + + @param BltBuffer buffer containing Grahpics Output color + + @return Converted VGA color + +**/ +UINT8 +VgaConvertColor ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ) +{ + UINT8 Color; + + Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04)); + if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) { + Color |= 0x08; + } + + return Color; +} + + +/** + Grahpics Output protocol instance to block transfer for VGA device. + + @param This Pointer to Grahpics Output protocol instance + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOperation + @param SourceY The Y coordinate of the source for BltOperation + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt rectangle in + pixels + @param Height The height of a rectangle in the blt rectangle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta of 0 is + used, the entire BltBuffer will be operated on. If + a subrectangle of the BltBuffer is used, then + Delta represents the number of bytes in a row of + the BltBuffer. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVgaBlt ( + 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 + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_TPL OriginalTPL; + UINT8 *MemAddress; + UINTN BytesPerScanLine; + UINTN Bit; + UINTN Index; + UINTN Index1; + UINTN StartAddress; + UINTN Bytes; + UINTN Offset; + UINT8 LeftMask; + UINT8 RightMask; + UINTN Address; + UINTN AddressFix; + UINT8 *Address1; + UINT8 *SourceAddress; + UINT8 *DestinationAddress; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Data; + UINT8 PixelColor; + UINT8 *VgaFrameBuffer; + UINTN SourceOffset; + UINTN SourceWidth; + UINTN Rows; + UINTN Columns; + UINTN CoordinateX; + UINTN CoordinateY; + UINTN CurrentMode; + + if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + CurrentMode = This->Mode->Mode; + PciIo = BiosVideoPrivate->PciIo; + MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer; + BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3; + VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer; + + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + // + // We need to fill the Virtual Screen buffer with the blt data. + // The virtual screen is upside down, as the first row is the bootom row of + // the image. + // + if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } + // + // If Delta is zero, then the entire BltBuffer is being used, so Delta + // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, + // the number of bytes in each row can be computed. + // + if (Delta == 0) { + Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } + // + // We have to raise to TPL Notify, so we make an atomic write the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Compute some values we need for VGA + // + switch (BltOperation) { + case EfiBltVideoToBltBuffer: + + SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); + SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1; + + // + // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer + // + VgaReadBitPlanes ( + PciIo, + MemAddress + SourceOffset, + VgaFrameBuffer + SourceOffset, + SourceWidth, + Height + ); + + // + // Convert VGA Bit Planes to a Graphics Output 32-bit color value + // + BltBuffer += (DestinationY * (Delta >> 2) + DestinationX); + for (Rows = 0, CoordinateY = SourceY; Rows < Height; Rows++, CoordinateY++, BltBuffer += (Delta >> 2)) { + for (Columns = 0, CoordinateX = SourceX; Columns < Width; Columns++, CoordinateX++, BltBuffer++) { + VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, CoordinateY, BltBuffer); + } + + BltBuffer -= Width; + } + + break; + + case EfiBltVideoToVideo: + // + // Check for an aligned Video to Video operation + // + if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) { + // + // Program the Mode Register Write mode 1, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 + ); + + SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3)); + DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + Bytes = Width >> 3; + for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) { + PciIo->CopyMem ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) (DestinationAddress + Offset), + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) (SourceAddress + Offset), + Bytes + ); + } + } else { + SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); + SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1; + + // + // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer + // + VgaReadBitPlanes ( + PciIo, + MemAddress + SourceOffset, + VgaFrameBuffer + SourceOffset, + SourceWidth, + Height + ); + } + + break; + + case EfiBltVideoFill: + StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3); + LeftMask = mVgaLeftMaskTable[DestinationX & 0x07]; + RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07]; + if (Bytes == 0) { + LeftMask = (UINT8) (LeftMask & RightMask); + RightMask = 0; + } + + if (LeftMask == 0xff) { + StartAddress--; + Bytes++; + LeftMask = 0; + } + + if (RightMask == 0xff) { + Bytes++; + RightMask = 0; + } + + PixelColor = VgaConvertColor (BltBuffer); + + // + // Program the Mode Register Write mode 2, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 + ); + + // + // Program the Data Rotate/Function Select Register to replace + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER, + VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE + ); + + if (LeftMask != 0) { + // + // Program the BitMask register with the Left column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + LeftMask + ); + + for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) { + // + // Read data from the bit planes into the latches + // + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &Data + ); + // + // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask + // + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &PixelColor + ); + } + } + + if (Bytes > 1) { + // + // Program the BitMask register with the middle column mask of 0xff + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + 0xff + ); + + for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) { + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthFillUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + Bytes - 1, + &PixelColor + ); + } + } + + if (RightMask != 0) { + // + // Program the BitMask register with the Right column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + RightMask + ); + + for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) { + // + // Read data from the bit planes into the latches + // + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &Data + ); + // + // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask + // + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &PixelColor + ); + } + } + break; + + case EfiBltBufferToVideo: + StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + LeftMask = mVgaBitMaskTable[DestinationX & 0x07]; + + // + // Program the Mode Register Write mode 2, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 + ); + + // + // Program the Data Rotate/Function Select Register to replace + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER, + VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE + ); + + for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) { + for (Index1 = 0; Index1 < Width; Index1++) { + BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]); + } + AddressFix = Address; + + for (Bit = 0; Bit < 8; Bit++) { + // + // Program the BitMask register with the Left column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + LeftMask + ); + + for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) { + // + // Read data from the bit planes into the latches + // + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address1, + 1, + &Data + ); + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address1, + 1, + &BiosVideoPrivate->LineBuffer[Index1] + ); + } + + LeftMask = (UINT8) (LeftMask >> 1); + if (LeftMask == 0) { + LeftMask = 0x80; + AddressFix++; + } + } + } + + break; + + default: ; + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} + +// +// VGA Mini Port Protocol Functions +// + +/** + VgaMiniPort protocol interface to set mode. + + @param This Pointer to VgaMiniPort protocol instance + @param ModeNumber The index of the mode + + @retval EFI_UNSUPPORTED The requested mode is not supported + @retval EFI_SUCCESS The requested mode is set successfully + +**/ +EFI_STATUS +EFIAPI +BiosVideoVgaMiniPortSetMode ( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_IA32_REGISTER_SET Regs; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Make sure the ModeNumber is a valid value + // + if (ModeNumber >= This->MaxMode) { + return EFI_UNSUPPORTED; + } + // + // Get the device structure for this device + // + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This); + + switch (ModeNumber) { + case 0: + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x14; + Regs.H.BL = 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + break; + + case 1: + // + // Set the 80x50 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + Regs.H.AH = 0x11; + Regs.H.AL = 0x12; + Regs.H.BL = 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Event handler for Exit Boot Service. + + @param Event The event that be siganlled when exiting boot service. + @param Context Pointer to instance of BIOS_VIDEO_DEV. + +**/ +VOID +EFIAPI +BiosVideoNotifyExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_IA32_REGISTER_SET Regs; + + BiosVideoPrivate = (BIOS_VIDEO_DEV *)Context; + + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x03; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Regs.H.AH = 0x00; + Regs.H.AL = 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x04; + Regs.H.BL = 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); +} + +/** + The user Entry Point for module UefiBiosVideo. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +BiosVideoEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gBiosVideoDriverBinding, + ImageHandle, + &gBiosVideoComponentName, + &gBiosVideoComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + // + // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver + // + return gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiLegacyBiosGuid, + NULL, + NULL + ); +} + diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h new file mode 100644 index 0000000000..88ab1d7cf4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h @@ -0,0 +1,539 @@ +/** @file + +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 _BIOS_GRAPHICS_OUTPUT_H_ +#define _BIOS_GRAPHICS_OUTPUT_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "VesaBiosExtensions.h" + +// +// Packed format support: The number of bits reserved for each of the colors and the actual +// position of RGB in the frame buffer is specified in the VBE Mode information +// +typedef struct { + UINT8 Position; // Position of the color + UINT8 Mask; // The number of bits expressed as a mask +} BIOS_VIDEO_COLOR_PLACEMENT; + +// +// BIOS Graphics Output Graphical Mode Data +// +typedef struct { + UINT16 VbeModeNumber; + UINT16 BytesPerScanLine; + VOID *LinearFrameBuffer; + UINTN FrameBufferSize; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; + UINT32 BitsPerPixel; + BIOS_VIDEO_COLOR_PLACEMENT Red; + BIOS_VIDEO_COLOR_PLACEMENT Green; + BIOS_VIDEO_COLOR_PLACEMENT Blue; + BIOS_VIDEO_COLOR_PLACEMENT Reserved; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelBitMask; +} BIOS_VIDEO_MODE_DATA; + +// +// BIOS video child handle private data Structure +// +#define BIOS_VIDEO_DEV_SIGNATURE SIGNATURE_32 ('B', 'V', 'M', 'p') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + + // + // Consumed Protocols + // + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + // + // Produced Protocols + // + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered; + EFI_EDID_ACTIVE_PROTOCOL EdidActive; + EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort; + + // + // General fields + // + BOOLEAN VgaCompatible; + BOOLEAN ProduceGraphicsOutput; + + // + // Graphics Output Protocol related fields + // + BOOLEAN HardwareNeedsStarting; + UINTN CurrentMode; + UINTN MaxMode; + BIOS_VIDEO_MODE_DATA *ModeData; + UINT8 *LineBuffer; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; + UINT8 *VgaFrameBuffer; + + // + // VESA Bios Extensions related fields + // + UINTN NumberOfPagesBelow1MB; // Number of 4KB pages in PagesBelow1MB + EFI_PHYSICAL_ADDRESS PagesBelow1MB; // Buffer for all VBE Information Blocks + VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *VbeInformationBlock; // 0x200 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; // 0x100 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *VbeEdidDataBlock; // 0x80 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; // 59 bytes. Must be allocated below 1MB + UINTN VbeSaveRestorePages; // Number of 4KB pages in VbeSaveRestoreBuffer + EFI_PHYSICAL_ADDRESS VbeSaveRestoreBuffer; // Must be allocated below 1MB + // + // Status code + // + EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; + + EFI_EVENT ExitBootServicesEvent; +} BIOS_VIDEO_DEV; + +#define BIOS_VIDEO_DEV_FROM_PCI_IO_THIS(a) CR (a, BIOS_VIDEO_DEV, PciIo, BIOS_VIDEO_DEV_SIGNATURE) +#define BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS(a) CR (a, BIOS_VIDEO_DEV, GraphicsOutput, BIOS_VIDEO_DEV_SIGNATURE) +#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV, VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE) + +#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2; + +// +// Driver Binding Protocol functions +// + +/** + Supported. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a device + path + + @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this + driver, Otherwise, this controller cannot be + managed by this driver + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + + +/** + Install Graphics Output Protocol onto VGA device handles. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a device + path + + @return EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + + +/** + Stop. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param NumberOfChildren Number of children handle created by this driver + @param ChildHandleBuffer Buffer containing child handle created + + @retval EFI_SUCCESS Driver disconnected successfully from controller + @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Private worker functions +// + +/** + Check for VBE device. + + @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS VBE device found + +**/ +EFI_STATUS +BiosVideoCheckForVbe ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ); + + +/** + Check for VGA device. + + @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS Standard VGA device found + +**/ +EFI_STATUS +BiosVideoCheckForVga ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ); + + + + +/** + Release resource for biso video instance. + + @param BiosVideoPrivate Video child device private data structure + +**/ +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ); + +// +// BIOS Graphics Output Protocol functions +// + +/** + Graphics Output protocol interface to get video mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info + buffer. + @param Info Caller 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_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ); + + +/** + Graphics Output protocol interface to set video mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @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. + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ); + + +/** + Graphics Output protocol instance to block transfer for VBE device. + + @param This Pointer to Graphics Output protocol instance + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOperation + @param SourceY The Y coordinate of the source for BltOperation + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt rectangle in + pixels + @param Height The height of a rectangle in the blt rectangle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta of 0 is + used, the entire BltBuffer will be operated on. If + a subrectangle of the BltBuffer is used, then + Delta represents the number of bytes in a row of + the BltBuffer. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVbeBlt ( + 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 + ); + + +/** + Grahpics Output protocol instance to block transfer for VGA device. + + @param This Pointer to Grahpics Output protocol instance + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOperation + @param SourceY The Y coordinate of the source for BltOperation + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt rectangle in + pixels + @param Height The height of a rectangle in the blt rectangle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta of 0 is + used, the entire BltBuffer will be operated on. If + a subrectangle of the BltBuffer is used, then + Delta represents the number of bytes in a row of + the BltBuffer. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVgaBlt ( + 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 + ); + +// +// BIOS VGA Mini Port Protocol functions +// + +/** + VgaMiniPort protocol interface to set mode. + + @param This Pointer to VgaMiniPort protocol instance + @param ModeNumber The index of the mode + + @retval EFI_UNSUPPORTED The requested mode is not supported + @retval EFI_SUCCESS The requested mode is set successfully + +**/ +EFI_STATUS +EFIAPI +BiosVideoVgaMiniPortSetMode ( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +/** + Event handler for Exit Boot Service. + + @param Event The event that be siganlled when exiting boot service. + @param Context Pointer to instance of BIOS_VIDEO_DEV. + +**/ +VOID +EFIAPI +BiosVideoNotifyExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// Standard VGA Definitions +// +#define VGA_HORIZONTAL_RESOLUTION 640 +#define VGA_VERTICAL_RESOLUTION 480 +#define VGA_NUMBER_OF_BIT_PLANES 4 +#define VGA_PIXELS_PER_BYTE 8 +#define VGA_BYTES_PER_SCAN_LINE (VGA_HORIZONTAL_RESOLUTION / VGA_PIXELS_PER_BYTE) +#define VGA_BYTES_PER_BIT_PLANE (VGA_VERTICAL_RESOLUTION * VGA_BYTES_PER_SCAN_LINE) + +#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER 0x3ce +#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER 0x3cf + +#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER 0x00 + +#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01 + +#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER 0x02 + +#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER 0x03 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE 0x00 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND 0x08 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR 0x10 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR 0x18 + +#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER 0x04 + +#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER 0x05 +#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0 0x00 +#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1 0x08 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 0x00 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 0x01 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 0x02 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3 0x03 + +#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER 0x06 + +#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER 0x07 + +#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER 0x08 + +/** + Install child handles if the Handle supports MBR format. + + @param This Calling context. + @param ParentHandle Parent Handle + @param ParentPciIo Parent PciIo interface + @param ParentLegacyBios Parent LegacyBios interface + @param ParentDevicePath Parent Device Path + @param RemainingDevicePath Remaining Device Path + + @retval EFI_SUCCESS If a child handle was added + @retval other A child handle was not added + +**/ +EFI_STATUS +BiosVideoChildHandleInstall ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_PCI_IO_PROTOCOL *ParentPciIo, + IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Deregister an video child handle and free resources. + + @param This Protocol instance pointer. + @param Controller Video controller handle + @param Handle Video child handle + + @return EFI_STATUS + +**/ +EFI_STATUS +BiosVideoChildHandleUninstall ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_HANDLE Handle + ); + +/** + Release resource for biso video instance. + + @param BiosVideoPrivate Video child device private data structure + +**/ +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ); + +/** + Check if all video child handles have been uninstalled. + + @param Controller Video controller handle + + @return TRUE Child handles exist. + @return FALSE All video child handles have been uninstalled. + +**/ +BOOLEAN +HasChildHandle ( + IN EFI_HANDLE Controller + ); +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni new file mode 100644 index 0000000000..db9c068146 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni new file mode 100644 index 0000000000..50334d82c4 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c new file mode 100644 index 0000000000..d9bd0a9238 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c @@ -0,0 +1,313 @@ +/** @file + +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 "BiosVideo.h" + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetDriverName ( + 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 +BiosVideoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName = { + BiosVideoComponentNameGetDriverName, + BiosVideoComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosVideoComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosVideoComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = { + { + "eng;en", + L"BIOS[INT10] Video Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mBiosVideoDriverNameTable, + DriverName, + (BOOLEAN)(This == &gBiosVideoComponentName) + ); +} + +/** + 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 +BiosVideoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h new file mode 100644 index 0000000000..25eee6921d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h @@ -0,0 +1,466 @@ +/** @file + +Copyright (c) 2006 - 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 _VESA_BIOS_EXTENSIONS_H_ +#define _VESA_BIOS_EXTENSIONS_H_ + +// +// Turn on byte packing of data structures +// +#pragma pack(1) +// +// VESA BIOS Extensions status codes +// +#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f + +// +// VESA BIOS Extensions Services +// +#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION 0x4f00 + +/*++ + + Routine Description: + Function 00 : Return Controller Information + + Arguments: + Inputs: + AX = 0x4f00 + ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION 0x4f01 + +/*++ + + Routine Description: + Function 01 : Return Mode Information + + Arguments: + Inputs: + AX = 0x4f01 + CX = Mode Number + ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02 + +/*++ + + Routine Description: + Function 02 : Set Mode + + Arguments: + Inputs: + AX = 0x4f02 + BX = Desired mode to set + D0-D8 = Mode Number + D9-D10 = Reserved (must be 0) + D11 = 0 - Use current default refresh rate + = 1 - Use user specfieid CRTC values for refresh rate + D12-D13 = Reserved (must be 0) + D14 = 0 - Use windowed frame buffer model + = 1 - Use linear/flat frame buffer model + D15 = 0 - Clear display memory + = 1 - Don't clear display memory + ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE 0x4f03 + +/*++ + + Routine Description: + Function 03 : Return Current Mode + + Arguments: + Inputs: + AX = 0x4f03 + Outputs: + AX = Return Status + BX = Current mode + D0-D13 = Mode Number + D14 = 0 - Windowed frame buffer model + = 1 - Linear/flat frame buffer model + D15 = 0 - Memory cleared at last mode set + = 1 - Memory not cleared at last mode set + +--*/ +#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04 + +/*++ + + Routine Description: + Function 04 : Save/Restore State + + Arguments: + Inputs: + AX = 0x4f03 + DL = 0x00 - Return Save/Restore State buffer size + = 0x01 - Save State + = 0x02 - Restore State + CX = Requested Status + D0 = Save/Restore controller hardware state + D1 = Save/Restore BIOS data state + D2 = Save/Restore DAC state + D3 = Save/Restore Regsiter state + ES:BX = Pointer to buffer if DL=1 or DL=2 + Outputs: + AX = Return Status + BX = Number of 64 byte blocks to hold the state buffer if DL=0 + +--*/ +#define VESA_BIOS_EXTENSIONS_EDID 0x4f15 + +/*++ + + Routine Description: + Function 15 : implement VBE/DDC service + + Arguments: + Inputs: + AX = 0x4f15 + BL = 0x00 - Report VBE/DDC Capabilities + CX = 0x00 - Controller unit number (00 = primary controller) + ES:DI = Null pointer, must be 0:0 in version 1.0 + Outputs: + AX = Return Status + BH = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes) + BL = DDC level supported + D0 = 0 DDC1 not supported + = 1 DDC1 supported + D1 = 0 DDC2 not supported + = 1 DDC2 supported + D2 = 0 Screen not blanked during data transfer + = 1 Screen blanked during data transfer + + Inputs: + AX = 0x4f15 + BL = 0x01 - Read EDID + CX = 0x00 - Controller unit number (00 = primary controller) + DX = 0x00 - EDID block number + ES:DI = Pointer to buffer in which the EDID block is returned + Outputs: + AX = Return Status +--*/ + +// +// Timing data from EDID data block +// +#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE 128 +#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17 + +// +// Established Timings: 24 possible resolutions +// Standard Timings: 8 possible resolutions +// Detailed Timings: 4 possible resolutions +// +#define VESA_BIOS_EXTENSIONS_EDID_TIMING_MAX_NUMBER 36 + +// +// Timing data size for Established Timings, Standard Timings and Detailed Timings +// +#define VESA_BIOS_EXTENSIONS_ESTABLISHED_TIMING_SIZE 3 +#define VESA_BIOS_EXTENSIONS_STANDARD_TIMING_SIZE 16 +#define VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE 18 +#define VESA_BIOS_EXTENSIONS_DETAILED_TIMING_DESCRIPTOR_MAX_SIZE 72 + +typedef struct { + UINT16 HorizontalResolution; + UINT16 VerticalResolution; + UINT16 RefreshRate; +} VESA_BIOS_EXTENSIONS_EDID_TIMING; + +typedef struct { + UINT32 ValidNumber; + UINT32 Key[VESA_BIOS_EXTENSIONS_EDID_TIMING_MAX_NUMBER]; +} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING; + +typedef struct { + UINT8 Header[8]; //EDID header "00 FF FF FF FF FF FF 00" + UINT16 ManufactureName; //EISA 3-character ID + UINT16 ProductCode; //Vendor assigned code + UINT32 SerialNumber; //32-bit serial number + UINT8 WeekOfManufacture; //Week number + UINT8 YearOfManufacture; //Year + UINT8 EdidVersion; //EDID Structure Version + UINT8 EdidRevision; //EDID Structure Revision + UINT8 VideoInputDefinition; + UINT8 MaxHorizontalImageSize; //cm + UINT8 MaxVerticalImageSize; //cm + UINT8 DisplayTransferCharacteristic; + UINT8 FeatureSupport; + UINT8 RedGreenLowBits; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0 + UINT8 BlueWhiteLowBits; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0 + UINT8 RedX; //Red-x Bits 9 - 2 + UINT8 RedY; //Red-y Bits 9 - 2 + UINT8 GreenX; //Green-x Bits 9 - 2 + UINT8 GreenY; //Green-y Bits 9 - 2 + UINT8 BlueX; //Blue-x Bits 9 - 2 + UINT8 BlueY; //Blue-y Bits 9 - 2 + UINT8 WhiteX; //White-x Bits 9 - 2 + UINT8 WhiteY; //White-x Bits 9 - 2 + UINT8 EstablishedTimings[VESA_BIOS_EXTENSIONS_ESTABLISHED_TIMING_SIZE]; + UINT8 StandardTimingIdentification[VESA_BIOS_EXTENSIONS_STANDARD_TIMING_SIZE]; + UINT8 DetailedTimingDescriptions[VESA_BIOS_EXTENSIONS_DETAILED_TIMING_DESCRIPTOR_MAX_SIZE]; + UINT8 ExtensionFlag; //Number of (optional) 128-byte EDID extension blocks to follow + UINT8 Checksum; +} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK; + +// +// Super VGA Information Block +// +typedef struct { + UINT32 VESASignature; // 'VESA' 4 byte signature + UINT16 VESAVersion; // VBE version number + UINT32 OEMStringPtr; // Pointer to OEM string + UINT32 Capabilities; // Capabilities of video card + UINT32 VideoModePtr; // Pointer to an array of 16-bit supported modes values terminated by 0xFFFF + UINT16 TotalMemory; // Number of 64kb memory blocks + UINT16 OemSoftwareRev; // VBE implementation Software revision + UINT32 OemVendorNamePtr; // VbeFarPtr to Vendor Name String + UINT32 OemProductNamePtr; // VbeFarPtr to Product Name String + UINT32 OemProductRevPtr; // VbeFarPtr to Product Revision String + UINT8 Reserved[222]; // Reserved for VBE implementation scratch area + UINT8 OemData[256]; // Data area for OEM strings. Pad to 512 byte block size +} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK; + +// +// Super VGA Information Block VESASignature values +// +#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE SIGNATURE_32 ('V', 'E', 'S', 'A') +#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE SIGNATURE_32 ('V', 'B', 'E', '2') + +// +// Super VGA Information Block VESAVersion values +// +#define VESA_BIOS_EXTENSIONS_VERSION_1_2 0x0102 +#define VESA_BIOS_EXTENSIONS_VERSION_2_0 0x0200 +#define VESA_BIOS_EXTENSIONS_VERSION_3_0 0x0300 + +// +// Super VGA Information Block Capabilities field bit defintions +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01 // 0: DAC width is fixed at 6 bits/color +// 1: DAC width switchable to 8 bits/color +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02 // 0: Controller is VGA compatible +// 1: Controller is not VGA compatible +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04 // 0: Normal RAMDAC operation +// 1: Use blank bit in function 9 to program RAMDAC +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC 0x08 // 0: No hardware stereoscopic signal support +// 1: Hardware stereoscopic signal support +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC 0x10 // 0: Stero signaling supported via external VESA stereo connector +// 1: Stero signaling supported via VESA EVC connector +// +// Super VGA mode number bite field definitions +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100 // 0: Not a VESA defined VBE mode +// 1: A VESA defined VBE mode +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800 // 0: Use current BIOS default referesh rate +// 1: Use the user specified CRTC values for refresh rate +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER 0x4000 // 0: Use a banked/windowed frame buffer +// 1: Use a linear/flat frame buffer +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY 0x8000 // 0: Clear display memory +// 1: Preseve display memory +// +// Super VGA Information Block mode list terminator value +// +#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff + +// +// Window Function +// +typedef +VOID +(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) ( + VOID + ); + +// +// Super VGA Mode Information Block +// +typedef struct { + // + // Manadory fields for all VESA Bios Extensions revisions + // + UINT16 ModeAttributes; // Mode attributes + UINT8 WinAAttributes; // Window A attributes + UINT8 WinBAttributes; // Window B attributes + UINT16 WinGranularity; // Window granularity in k + UINT16 WinSize; // Window size in k + UINT16 WinASegment; // Window A segment + UINT16 WinBSegment; // Window B segment + UINT32 WindowFunction; // Pointer to window function + UINT16 BytesPerScanLine; // Bytes per scanline + // + // Manadory fields for VESA Bios Extensions 1.2 and above + // + UINT16 XResolution; // Horizontal resolution + UINT16 YResolution; // Vertical resolution + UINT8 XCharSize; // Character cell width + UINT8 YCharSize; // Character cell height + UINT8 NumberOfPlanes; // Number of memory planes + UINT8 BitsPerPixel; // Bits per pixel + UINT8 NumberOfBanks; // Number of CGA style banks + UINT8 MemoryModel; // Memory model type + UINT8 BankSize; // Size of CGA style banks + UINT8 NumberOfImagePages; // Number of images pages + UINT8 Reserved1; // Reserved + UINT8 RedMaskSize; // Size of direct color red mask + UINT8 RedFieldPosition; // Bit posn of lsb of red mask + UINT8 GreenMaskSize; // Size of direct color green mask + UINT8 GreenFieldPosition; // Bit posn of lsb of green mask + UINT8 BlueMaskSize; // Size of direct color blue mask + UINT8 BlueFieldPosition; // Bit posn of lsb of blue mask + UINT8 RsvdMaskSize; // Size of direct color res mask + UINT8 RsvdFieldPosition; // Bit posn of lsb of res mask + UINT8 DirectColorModeInfo; // Direct color mode attributes + // + // Manadory fields for VESA Bios Extensions 2.0 and above + // + UINT32 PhysBasePtr; // Physical Address for flat memory frame buffer + UINT32 Reserved2; // Reserved + UINT16 Reserved3; // Reserved + // + // Manadory fields for VESA Bios Extensions 3.0 and above + // + UINT16 LinBytesPerScanLine; // Bytes/scan line for linear modes + UINT8 BnkNumberOfImagePages; // Number of images for banked modes + UINT8 LinNumberOfImagePages; // Number of images for linear modes + UINT8 LinRedMaskSize; // Size of direct color red mask (linear mode) + UINT8 LinRedFieldPosition; // Bit posiiton of lsb of red mask (linear modes) + UINT8 LinGreenMaskSize; // Size of direct color green mask (linear mode) + UINT8 LinGreenFieldPosition; // Bit posiiton of lsb of green mask (linear modes) + UINT8 LinBlueMaskSize; // Size of direct color blue mask (linear mode) + UINT8 LinBlueFieldPosition; // Bit posiiton of lsb of blue mask (linear modes) + UINT8 LinRsvdMaskSize; // Size of direct color reserved mask (linear mode) + UINT8 LinRsvdFieldPosition; // Bit posiiton of lsb of reserved mask (linear modes) + UINT32 MaxPixelClock; // Maximum pixel clock (in Hz) for graphics mode + UINT8 Pad[190]; // Pad to 256 byte block size +} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK; + +// +// Super VGA Mode Information Block ModeAttributes field bit defintions +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE 0x0001 // 0: Mode not supported in handware +// 1: Mode supported in handware +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004 // 0: TTY Output functions not supported by BIOS +// 1: TTY Output functions supported by BIOS +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008 // 0: Monochrome mode +// 1: Color mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS 0x0010 // 0: Text mode +// 1: Graphics mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020 // 0: VGA compatible mode +// 1: Not a VGA compatible mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED 0x0040 // 0: VGA compatible windowed memory mode +// 1: Not a VGA compatible windowed memory mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080 // 0: No linear fram buffer mode available +// 1: Linear frame buffer mode available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100 // 0: No double scan mode available +// 1: Double scan mode available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED 0x0200 // 0: No interlaced mode is available +// 1: Interlaced mode is available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400 // 0: No hardware triple buffer mode support available +// 1: Hardware triple buffer mode support available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC 0x0800 // 0: No hardware steroscopic display support +// 1: Hardware steroscopic display support +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY 0x1000 // 0: No dual display start address support +// 1: Dual display start address support +// +// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit defintions +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01 // 0: Single non-relocatable window only +// 1: Relocatable window(s) are supported +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE 0x02 // 0: Window is not readable +// 1: Window is readable +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE 0x04 // 0: Window is not writable +// 1: Window is writable +// +// Super VGA Mode Information Block DirectColorMode field bit defintions +// +#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP 0x01 // 0: Color ram is fixed +// 1: Color ramp is programmable +// +#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE 0x02 // 0: Bits in Rsvd field are reserved +// 1: Bits in Rsdv field are usable +// +// Super VGA Memory Models +// +typedef enum { + MemPL = 3, // Planar memory model + MemPK = 4, // Packed pixel memory model + MemRGB= 6, // Direct color RGB memory model + MemYUV= 7 // Direct color YUV memory model +} VESA_BIOS_EXTENSIONS_MEMORY_MODELS; + +// +// Super VGA CRTC Information Block +// +typedef struct { + UINT16 HorizontalTotal; // Horizontal total in pixels + UINT16 HorizontalSyncStart; // Horizontal sync start in pixels + UINT16 HorizontalSyncEnd; // Horizontal sync end in pixels + UINT16 VericalTotal; // Vertical total in pixels + UINT16 VericalSyncStart; // Vertical sync start in pixels + UINT16 VericalSyncEnd; // Vertical sync end in pixels + UINT8 Flags; // Flags (Interlaced/DoubleScan/etc). + UINT32 PixelClock; // Pixel clock in units of Hz + UINT16 RefreshRate; // Refresh rate in units of 0.01 Hz + UINT8 Reserved[40]; // Pad +} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK; + +#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01 // 0: Graphics mode is not souble scanned +// 1: Graphics mode is double scanned +// +#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02 // 0: Graphics mode is not interlaced +// 1: Graphics mode is interlaced +// +#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE 0x04 // 0: Horizontal sync polarity is positive(+) +// 0: Horizontal sync polarity is negative(-) +// +#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08 // 0: Verical sync polarity is positive(+) +// 0: Verical sync polarity is negative(-) +// +// Turn off byte packing of data structures +// +#pragma pack() + +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf new file mode 100644 index 0000000000..7b1764acfc --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf @@ -0,0 +1,87 @@ +## @file +# Video driver based on legacy bios. +# +# This driver by using Legacy Bios protocol service to support csm Video +# and produce Graphics Output Protocol. +# +# 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 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 = BiosVideoDxe + MODULE_UNI_FILE = BiosVideoDxe.uni + FILE_GUID = 0B04B2ED-861C-42cd-A22F-C3AAFACCB896 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = BiosVideoEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gBiosVideoDriverBinding +# COMPONENT_NAME = gBiosVideoComponentName +# + +[Sources] + BiosVideo.c + BiosVideo.h + ComponentName.c + VesaBiosExtensions.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +[LibraryClasses] + MemoryAllocationLib + DevicePathLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + ReportStatusCodeLib + DebugLib + PcdLib + + +[Guids] + gEfiLegacyBiosGuid ## PRODUCES ##GUID # Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver + gEfiEventExitBootServicesGuid ## CONSUMES ##Event + +[Protocols] + gEfiVgaMiniPortProtocolGuid ## BY_START + gEfiEdidDiscoveredProtocolGuid ## BY_START + gEfiGraphicsOutputProtocolGuid ## BY_START + gEfiEdidActiveProtocolGuid ## BY_START + gEfiLegacyBiosProtocolGuid ## CONSUMES + gEfiPciIoProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## BY_START + gEfiEdidOverrideProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## SOMETIMES_CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + BiosVideoDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.S b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.S new file mode 100644 index 0000000000..a785256052 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.S @@ -0,0 +1,67 @@ +## @file +# Interrupt Redirection Template +# +# Copyright (c) 2006, Intel 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. +# +## + +ASM_GLOBAL ASM_PFX(InterruptRedirectionTemplate) + +#---------------------------------------------------------------------------- +# Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F +# +# Input: None +# +# Output: None +# +# Prototype: VOID +# InterruptRedirectionTemplate ( +# VOID +# ); +# +# Saves: None +# +# Modified: None +# +# Description: Contains the code that is copied into low memory (below 640K). +# This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. +# This template must be copied into low memory, and the IDT entries +# 0x68-0x6F must be point to the low memory copy of this code. Each +# entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily +# computed. +# +#---------------------------------------------------------------------------- +ASM_PFX(InterruptRedirectionTemplate): + int $0x8 + .byte 0xcf + nop + int $0x9 + .byte 0xcf + nop + int $0xa + .byte 0xcf + nop + int $0xb + .byte 0xcf + nop + int $0xc + .byte 0xcf + nop + int $0xd + .byte 0xcf + nop + int $0xe + .byte 0xcf + nop + int $0xf + .byte 0xcf + nop diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.asm b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.asm new file mode 100644 index 0000000000..410ce5be6e --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.asm @@ -0,0 +1,73 @@ +;; @file +; Interrupt Redirection Template +; +; Copyright (c) 2006, Intel 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. +; +;; + +.686P +.MODEL FLAT, C +.CODE + +;---------------------------------------------------------------------------- +; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F +; +; Input: None +; +; Output: None +; +; Prototype: VOID +; InterruptRedirectionTemplate ( +; VOID +; ); +; +; Saves: None +; +; Modified: None +; +; Description: Contains the code that is copied into low memory (below 640K). +; This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. +; This template must be copied into low memory, and the IDT entries +; 0x68-0x6F must be point to the low memory copy of this code. Each +; entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily +; computed. +; +;---------------------------------------------------------------------------- + +InterruptRedirectionTemplate PROC C + int 08h + DB 0cfh ; IRET + nop + int 09h + DB 0cfh ; IRET + nop + int 0ah + DB 0cfh ; IRET + nop + int 0bh + DB 0cfh ; IRET + nop + int 0ch + DB 0cfh ; IRET + nop + int 0dh + DB 0cfh ; IRET + nop + int 0eh + DB 0cfh ; IRET + nop + int 0fh + DB 0cfh ; IRET + nop +InterruptRedirectionTemplate ENDP + +END \ No newline at end of file diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c new file mode 100644 index 0000000000..8c8f6d321b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c @@ -0,0 +1,277 @@ +/** @file + +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 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 "LegacyBiosInterface.h" + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + Note: BBS compliant drives ARE NOT available until this call by + either shell or EFI. + + @param This Protocol instance pointer. + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Drive numbers assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosPrepareToBootEfi ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ) +{ + // + // Shadow All Opion ROM + // + LegacyBiosShadowAllLegacyOproms (This); + return EFI_SUCCESS; +} + + +/** + To boot from an unconventional device like parties and/or execute + HDD diagnostics. + + @param This Protocol instance pointer. + @param Attributes How to interpret the other input parameters + @param BbsEntry The 0-based index into the BbsTable for the + parent device. + @param BeerData Pointer to the 128 bytes of ram BEER data. + @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. + The caller must provide a pointer to the specific + Service Area and not the start all Service Areas. + EFI_INVALID_PARAMETER if error. Does NOT return if no error. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosBootUnconventionalDevice ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UDC_ATTRIBUTES Attributes, + IN UINTN BbsEntry, + IN VOID *BeerData, + IN VOID *ServiceAreaData + ) +{ + return EFI_INVALID_PARAMETER; +} + + +/** + Attempt to legacy boot the BootOption. If the EFI contexted has been + compromised this function will not return. + + @param This Protocol instance pointer. + @param BbsDevicePath EFI Device Path from BootXXXX variable. + @param LoadOptionsSize Size of LoadOption in size. + @param LoadOptions LoadOption from BootXXXX variable + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +EFIAPI +LegacyBiosLegacyBoot ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Build the E820 table. + + @param Private Legacy BIOS Instance data + @param Size Size of E820 Table + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildE820 ( + IN LEGACY_BIOS_INSTANCE *Private, + OUT UINTN *Size + ) +{ + *Size = 0; + return EFI_SUCCESS; +} + +/** + Get all BBS info + + @param This Protocol instance pointer. + @param HddCount Number of HDD_INFO structures + @param HddInfo Onboard IDE controller information + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Tables returned + @retval EFI_NOT_FOUND resource not found + @retval EFI_DEVICE_ERROR can not get BBS table + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetBbsInfo ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *HddCount, + OUT HDD_INFO **HddInfo, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Fill in the standard BDA for Keyboard LEDs + + @param This Protocol instance pointer. + @param Leds Current LED status + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosUpdateKeyboardLedStatus ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 Leds + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Relocate this image under 4G memory for IPF. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Image successfully relocated. + @retval EFI_ABORTED Failed to relocate image. + +**/ +EFI_STATUS +RelocateImageUnder4GIfNeeded ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + UINTN NumberOfPages; + EFI_PHYSICAL_ADDRESS LoadedImageBase; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_PHYSICAL_ADDRESS MemoryAddress; + EFI_HANDLE NewImageHandle; + + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID *) &LoadedImage + ); + + if (!EFI_ERROR (Status)) { + LoadedImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImage->ImageBase; + if (LoadedImageBase > 0xffffffff) { + NumberOfPages = (UINTN) (DivU64x32(LoadedImage->ImageSize, EFI_PAGE_SIZE) + 1); + + // + // Allocate buffer below 4GB here + // + Status = AllocateLegacyMemory ( + AllocateMaxAddress, + 0x7FFFFFFF, + NumberOfPages, // do we have to convert this to pages?? + &MemoryAddress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + ImageContext.Handle = (VOID *)(UINTN)LoadedImageBase; + ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; + + // + // Get information about the image being loaded + // + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + ImageContext.ImageAddress = (PHYSICAL_ADDRESS)MemoryAddress; + // + // Align buffer on section boundry + // + ImageContext.ImageAddress += ImageContext.SectionAlignment - 1; + ImageContext.ImageAddress &= ~((PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1); + + // + // Load the image to our new buffer + // + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + gBS->FreePages (MemoryAddress, NumberOfPages); + return Status; + } + + // + // Relocate the image in our new buffer + // + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + gBS->FreePages (MemoryAddress, NumberOfPages); + return Status; + } + + // + // Create a new handle with gEfiCallerIdGuid to be used as the ImageHandle fore the reloaded image + // + NewImageHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &NewImageHandle, + &gEfiCallerIdGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable); + if (EFI_ERROR (Status)) { + gBS->FreePages (MemoryAddress, NumberOfPages); + return Status; + } + // + // return error directly the BS will unload this image + // + return EFI_ABORTED; + } + } + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h new file mode 100644 index 0000000000..26aa3a694b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h @@ -0,0 +1,102 @@ +/** @file + +Copyright (c) 2007 - 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 _IPF_THUNK_H_ +#define _IPF_THUNK_H_ + +#include "LegacyBiosInterface.h" +#include + +/** + Template of real mode code. + + @param CodeStart Start address of code. + @param CodeEnd End address of code + @param ReverseThunkStart Start of reverse thunk. + @param IntThunk Low memory thunk. + +**/ +VOID +RealModeTemplate ( + OUT UINTN *CodeStart, + OUT UINTN *CodeEnd, + OUT UINTN *ReverseThunkStart, + LOW_MEMORY_THUNK *IntThunk + ); + +/** + Register physical address of Esal Data Area + + @param ReverseThunkCodeAddress Reverse Thunk Address + @param IntThunkAddress IntThunk Address + + @retval EFI_SUCCESS ESAL data area set successfully. + +**/ +EFI_STATUS +EsalSetSalDataArea ( + IN UINTN ReverseThunkCodeAddress, + IN UINTN IntThunkAddress + ); + +/** + Get address of reverse thunk. + + @retval EFI_SAL_SUCCESS Address of reverse thunk returned successfully. + +**/ +SAL_RETURN_REGS +EsalGetReverseThunkAddress ( + VOID + ); + +typedef struct { + UINT32 Eax; // 0 + UINT32 Ecx; // 4 + UINT32 Edx; // 8 + UINT32 Ebx; // 12 + UINT32 Esp; // 16 + UINT32 Ebp; // 20 + UINT32 Esi; // 24 + UINT32 Edi; // 28 + UINT32 Eflag; // 32 + UINT32 Eip; // 36 + UINT16 Cs; // 40 + UINT16 Ds; // 42 + UINT16 Es; // 44 + UINT16 Fs; // 46 + UINT16 Gs; // 48 + UINT16 Ss; // 50 +} IPF_DWORD_REGS; + +/** + Entrypoint of IA32 code. + + @param CallTypeData Data of call type + @param DwordRegister Register set of IA32 general registers + and segment registers + @param StackPointer Stack pointer. + @param StackSize Size of stack. + +**/ +VOID +EfiIaEntryPoint ( + UINT64 CallTypeData, + IPF_DWORD_REGS *DwordRegister, + UINT64 StackPointer, + UINT64 StackSize + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i new file mode 100644 index 0000000000..441bb25e3d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i @@ -0,0 +1,89 @@ +//// @file +// +// Copyright (c) 2006, Intel 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. +// +//// + +#define NUM_REAL_GDT_ENTRIES 3 +#define LOW_STACK_SIZE (8*1024) // 8k? + +// +// Low memory Thunk Structure +// +#define Code 0 +#define LowReverseThunkStart Code + 4096 +#define GdtDesc LowReverseThunkStart + 4 +#define IdtDesc GdtDesc + 6 +#define FlatSs IdtDesc + 6 +#define FlatEsp FlatSs + 4 +#define LowCodeSelector FlatEsp + 4 +#define LowDataSelector LowCodeSelector + 4 +#define LowStack LowDataSelector + 4 +#define RealModeIdtDesc LowStack + 4 +#define RealModeGdt RealModeIdtDesc + 6 +#define RealModeGdtDesc RealModeGdt + (8 * NUM_REAL_GDT_ENTRIES) +#define RevRealDs RealModeGdtDesc + 6 +#define RevRealSs RevRealDs + 2 +#define RevRealEsp RevRealSs + 2 +#define RevRealIdtDesc RevRealEsp + 4 +#define RevFlatDataSelector RevRealIdtDesc + 6 +#define RevFlatStack RevFlatDataSelector + 2 +#define Stack RevFlatStack + 4 +#define RevThunkStack Stack + LOW_STACK_SIZE + +#define EfiToLegacy16InitTable RevThunkStack + LOW_STACK_SIZE +#define InitTableBiosLessThan1MB EfiToLegacy16InitTable +#define InitTableHiPmmMemory InitTableBiosLessThan1MB + 4 +#define InitTablePmmMemorySizeInBytes InitTableHiPmmMemory + 4 +#define InitTableReverseThunkCallSegment InitTablePmmMemorySizeInBytes + 4 +#define InitTableReverseThunkCallOffset InitTableReverseThunkCallSegment + 2 +#define InitTableNumberE820Entries InitTableReverseThunkCallOffset + 2 +#define InitTableOsMemoryAbove1Mb InitTableNumberE820Entries + 4 +#define InitTableThunkStart InitTableOsMemoryAbove1Mb + 4 +#define InitTableThunkSizeInBytes InitTableThunkStart + 4 +#define InitTable16InitTableEnd InitTableThunkSizeInBytes + 4 + +#define EfiToLegacy16BootTable InitTable16InitTableEnd +#define BootTableBiosLessThan1MB EfiToLegacy16BootTable +#define BootTableHiPmmMemory BootTableBiosLessThan1MB + 4 +#define BootTablePmmMemorySizeInBytes BootTableHiPmmMemory + 4 +#define BootTableReverseThunkCallSegment BootTablePmmMemorySizeInBytes + 4 +#define BootTableReverseThunkCallOffset BootTableReverseThunkCallSegment + 2 +#define BootTableNumberE820Entries BootTableReverseThunkCallOffset + 2 +#define BootTableOsMemoryAbove1Mb BootTableNumberE820Entries + 4 +#define BootTableThunkStart BootTableOsMemoryAbove1Mb + 4 +#define BootTableThunkSizeInBytes BootTableThunkStart + 4 +#define EfiToLegacy16BootTableEnd BootTableThunkSizeInBytes + 4 + +#define InterruptRedirectionCode EfiToLegacy16BootTableEnd +#define PciHandler InterruptRedirectionCode + 32 + + +// +// Register Sets (16 Bit) +// + +#define AX 0 +#define BX 2 +#define CX 4 +#define DX 6 +#define SI 8 +#define DI 10 +#define Flags 12 +#define ES 14 +#define CS 16 +#define SS 18 +#define DS 20 +#define BP 22 + + + diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s new file mode 100644 index 0000000000..fc56176934 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s @@ -0,0 +1,524 @@ +//// @file +// +// Copyright (c) 1999 - 2008, Intel 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. +// +//// + +.file "IpfThunk.s" + +#include "IpfMacro.i" +#include "Ipf/IpfThunk.i" + +.align 0x10 +//----------------------------------------------------------------------------- +//++ +// EfiIaEntryPoint +// +// Register physical address of Esal Data Area +// +// On Entry : +// in1 = ptr to legacy bios reg +// in2 = ptr to Call Stack +// in3 = Call Stack Size +// +// Return Value: +// r8 = SAL_SUCCESS +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY(EfiIaEntryPoint) + + alloc loc0 = 8,10,8,0;; + + mov out0 = r0;; + mov out1 = r0;; + mov out2 = r0;; + mov out3 = r0;; + mov out4 = r0;; + mov out5 = r0;; + mov out6 = r0;; + mov out7 = r0;; + + mov loc1 = b0;; // save efi (b0) + mov loc2 = psr;; // save efi (PSR) + mov loc3 = gp;; // save efi (GP) + mov loc4 = pr;; // save efi (PR) + mov loc5 = sp;; // save efi (SP) + mov loc6 = r13;; // save efi (TP) + mov loc7 = ar.lc;; // save efi (LC) + mov loc8 = ar.fpsr;; // save efi (FPSR) + + mov r8 = r0;; // return status + mov r9 = r0;; // return value + mov r10 = r0;; // return value + mov r11 = r0;; // return value + +bios_int_func:: + rsm 0x4000;; // i(14)=0, disable interrupt + srlz.d;; + srlz.i;; + +//---------------------// +// save fp registers // +//---------------------// + + dep sp = 0,sp,0,4;; // align 16 + add sp = -16,sp;; // post decrement + +int_ip_1x:: + mov r2 = ip;; + add r2 = (int_ip_1y - int_ip_1x),r2;; + mov b7 = r2;; + br save_fp_registers;; + +int_ip_1y:: + add sp = 16,sp;; // adjust (SP) + mov loc9 = sp;; // save (SP) + adds sp = 0x10,in1;; // in1 + 0x10 = SP + ld4 sp = [sp];; // SP + adds r17 = 0x32,in1;; // in1 + 0x32 = SS + ld2 r17 = [r17];; // SS + movl r2 = 0xffffffff;; // if no SS:SP, then define new SS:SP + cmp.ne p6,p0 = sp,r2;; + movl r2 = 0xffff;; + cmp.ne.or p6,p0 = r17,r2;; + (p6) br.sptk bif_1;; + + mov sp = in3;; // 16-bit stack pointer + mov r2 = psr;; + tbit.z p6,p7 = r2,17;; // psr.dt (Physical OR Virtual) + +bif_ip1x:: + mov r2 = in2;; // ia32 callback stack top + mov r3 = in3;; // 16-bit stack pointer + sub r2 = r2,r3;; + shr.u r17 = r2,4;; // 16-bit stack segment + +bif_1:: + extr.u sp = sp,0,16;; // SP (16-bit sp for legacy code) + dep sp = 0,sp,0,3;; // align 8 + cmp.eq p6,p0 = 0,sp;; // if SP=0000 then wrap to 0x10000 + (p6) dep sp = -1,sp,16,1;; + shladd r2 = r17,4,sp;; // ESP = SS<<4+SP + add r2 = -8,r2;; // post decrement 64 bit pointer + add sp = -8,sp;; // post decrement SP + +sale_ip1x:: + mov r18 = ip;; + adds r18 = (sale_ip1y - sale_ip1x),r18;; + sub r18 = r18,r2;; // return address - CS base + add r18 = r18,sp;; // adjustment for stack + shl r18 = r18,32;; + movl r19 = 0xb80f66fa;; // CLI, JMPE xxxxxxxx + or r18 = r18,r19;; + st8 [r2] = r18;; // (FA,66,0F,B8,xx,xx,xx,xx) + + cmp.eq p6,p0 = 0,sp;; // if SP=0000 then wrap to 0x10000 + (p6) dep sp = -1,sp,16,1;; + shladd r2 = r17,4,sp;; // ESP=SS<<4+SP + add r2 = -2,r2;; // post decrement 64 bit pointer + add sp = -2,sp;; // post decrement SP + + movl r18 = 0x8000000000000100;; // CALL FAR function + cmp.eq p6,p7 = in0,r18;; + (p6) add r19 = 0x28,in1;; // in1 + 0x28 = CS + (p6) ld2 r18 = [r19],-4;; // CS + (p6) st2 [r2] = r18,-2;; // in1 + 0x24 = EIP + (p6) ld2 r18 = [r19];; // EIP + (p6) st2 [r2] = r18,-2;; // + (p6) movl r18 = 0x9a90;; // nop, CALLFAR xxxx:yyyy + + (p7) movl r18 = 0xcd;; // INT xx + (p7) dep r18 = in0,r18,8,8;; + st2 [r2] = r18;; // (CD,xx) + + mov r18 = r2;; // EIP for legacy execution + +//------------------------------// +// flush 32 bytes legacy code // +//------------------------------// + + dep r2 = 0,r2,0,5;; // align to 32 + fc r2;; + sync.i;; + srlz.i;; + srlz.d;; + +//------------------------------// +// load legacy registers // +//------------------------------// + mov r2 = in1;; // IA32 BIOS register state + ld4 r8 = [r2],4;; // in1 + 0 = EAX + ld4 r9 = [r2],4;; // in1 + 4 = ECX + ld4 r10 = [r2],4;; // in1 + 8 = EDX + ld4 r11 = [r2],4;; // in1 + 12 = EBX + + add r2 = 4,r2;; // in1 + 16 = ESP (skip) + + ld4 r13 = [r2],4;; // in1 + 20 = EBP + ld4 r14 = [r2],4;; // in1 + 24 = ESI + ld4 r15 = [r2],4;; // in1 + 28 = EDI + ld4 r3 = [r2],4;; // in1 + 32 = EFLAGS + mov ar.eflag = r3;; + + add r2 = 4,r2;; // in1 + 36 = EIP (skip) + add r2 = 2,r2;; // in1 + 40 = CS (skip) + + ld2 r16 = [r2],2;; // in1 + 42 = DS, (r16 = GS,FS,ES,DS) + movl r27 = 0xc93fffff00000000;; + dep r27 = r16,r27,4,16;; // r27 = DSD + + ld2 r19 = [r2],2;; // in1 + 44 = ES + dep r16 = r19,r16,16,16;; + movl r24 = 0xc93fffff00000000;; + dep r24 = r19,r24,4,16;; // r24 = ESD + + ld2 r19 = [r2],2;; // in1 + 46 = FS + dep r16 = r19,r16,32,16;; + movl r28 = 0xc93fffff00000000;; + dep r28 = r19,r28,4,16;; // r28 = FSD + + ld2 r19 = [r2],2;; // in1 + 48 = GS + dep r16 = r19,r16,48,16;; + movl r29 = 0xc93fffff00000000;; + dep r29 = r19,r29,4,16;; // r29 = GSD + + mov r30 = r0;; // r30 = LDTD, clear NaT + mov r31 = r0;; // r31 = GDTD, clear NaT + + dep r17 = r17,r17,16,16;; // CS = SS, (r17 = TSS,LDT,SS,CS) + + movl r3 = 0x0930ffff00000000;; + dep r3 = r17,r3,4,16;; + mov ar.csd = r3;; // ar25 = CSD + mov ar.ssd = r3;; // ar26 = SSD + +//------------------------------// +// give control to INT function // +//------------------------------// + + br.call.sptk b0 = execute_int_function;; + +//------------------------------// +// store legacy registers // +//------------------------------// + + mov r2 = in1;; + st4 [r2] = r8,4;; // EAX + st4 [r2] = r9,4;; // ECX + st4 [r2] = r10,4;; // EDX + st4 [r2] = r11,4;; // EBX + + add r2 = 4,r2;; // ESP (skip) + + st4 [r2] = r13,4;; // EBP + st4 [r2] = r14,4;; // ESI + st4 [r2] = r15,4;; // EDI + + mov r3 = ar.eflag;; + st4 [r2] = r3,4;; // EFLAGS + + add r2 = 4,r2;; // EIP (skip) + add r2 = 2,r2;; // CS (skip) + + st2 [r2] = r16,2;; // DS, (r16 = GS,FS,ES,DS) + + extr.u r3 = r16,16,16;; + st2 [r2] = r3,2;; // ES + + extr.u r3 = r16,32,16;; + st2 [r2] = r3,2;; // FS + + extr.u r3 = r16,48,16;; + st2 [r2] = r3,2;; // GS + +//------------------------------// +// restore fp registers // +//------------------------------// + mov sp = loc9;; // restore (SP) +int_ip_2x:: + mov r2 = ip;; + add r2 = (int_ip_2y - int_ip_2x),r2;; + mov b7 = r2;; + br restore_fp_registers;; + +int_ip_2y:: + mov r8 = r0;; // return status + mov r9 = r0;; // return value + mov r10 = r0;; // return value + mov r11 = r0;; // return value + + mov ar.fpsr = loc8;; // restore efi (FPSR) + mov ar.lc = loc7;; // restore efi (LC) + mov r13 = loc6;; // restore efi (TP) + mov sp = loc5;; // restore efi (SP) + mov pr = loc4;; // restore efi (PR) + mov gp = loc3;; // restore efi (GP) + mov psr.l = loc2;; // restore efi (PSR) + srlz.d;; + srlz.i;; + mov b0 = loc1;; // restore efi (b0) + mov ar.pfs = loc0;; + br.ret.sptk b0;; // return to efi + +PROCEDURE_EXIT (EfiIaEntryPoint) + +//==============================// +// EXECUTE_INT_FUNCTION // +//==============================// +// switch to virtual address // +//------------------------------// + +execute_int_function:: + + alloc r2 = 0,0,0,0;; // cfm.sof=0 + flushrs;; + + rsm 0x2000;; // ic(13)=0 for control register programming + srlz.d;; + srlz.i;; + + mov r2 = psr;; + dep r2 = -1,r2,34,1;; // set is(34) + dep r2 = -1,r2,44,1;; // set bn(44) + dep r2 = -1,r2,36,1;; // set it(36) + dep r2 = -1,r2,27,1;; // set rt(27) + dep r2 = -1,r2,17,1;; // set dt(17) + dep r2 = 0,r2,3,1;; // reset ac(3) + dep r2 = -1,r2,13,1;; // set ic(13) + + mov cr.ipsr = r2;; + mov cr.ifs = r0;; // clear interruption function state register + mov cr.iip = r18;; + + rfi;; // go to legacy code execution + +//------------------------------// +// back from legacy code // +//------------------------------// +// switch to physical address // +//------------------------------// + +sale_ip1y:: + rsm 0x6000;; // i(14)=0,ic(13)=0 for control reg programming + srlz.d;; + srlz.i;; + + mov r2 = psr;; + dep r2 = -1,r2,44,1;; // set bn(44) + dep r2 = 0,r2,36,1;; // reset it(36) + dep r2 = 0,r2,27,1;; // reset rt(27) + dep r2 = 0,r2,17,1;; // reset dt(17) + dep r2 = -1,r2,13,1;; // set ic(13) + mov cr.ipsr = r2;; + +sale_ip2x:: + mov r2 = ip;; + add r2 = (sale_ip2y - sale_ip2x),r2;; + mov cr.ifs = r0;; // clear interruption function state register + mov cr.iip = r2;; + rfi;; + +sale_ip2y:: + br.ret.sptk b0;; // return to SAL + +//------------------------------// +// store fp registers // +//------------------------------// +save_fp_registers:: + stf.spill [sp]=f2,-16;; stf.spill [sp]=f3,-16;; + stf.spill [sp]=f4,-16;; stf.spill [sp]=f5,-16;; stf.spill [sp]=f6,-16;; stf.spill [sp]=f7,-16;; + stf.spill [sp]=f8,-16;; stf.spill [sp]=f9,-16;; stf.spill [sp]=f10,-16;; stf.spill [sp]=f11,-16;; + stf.spill [sp]=f12,-16;; stf.spill [sp]=f13,-16;; stf.spill [sp]=f14,-16;; stf.spill [sp]=f15,-16;; + stf.spill [sp]=f16,-16;; stf.spill [sp]=f17,-16;; stf.spill [sp]=f18,-16;; stf.spill [sp]=f19,-16;; + stf.spill [sp]=f20,-16;; stf.spill [sp]=f21,-16;; stf.spill [sp]=f22,-16;; stf.spill [sp]=f23,-16;; + stf.spill [sp]=f24,-16;; stf.spill [sp]=f25,-16;; stf.spill [sp]=f26,-16;; stf.spill [sp]=f27,-16;; + stf.spill [sp]=f28,-16;; stf.spill [sp]=f29,-16;; stf.spill [sp]=f30,-16;; stf.spill [sp]=f31,-16;; + stf.spill [sp]=f32,-16;; stf.spill [sp]=f33,-16;; stf.spill [sp]=f34,-16;; stf.spill [sp]=f35,-16;; + stf.spill [sp]=f36,-16;; stf.spill [sp]=f37,-16;; stf.spill [sp]=f38,-16;; stf.spill [sp]=f39,-16;; + stf.spill [sp]=f40,-16;; stf.spill [sp]=f41,-16;; stf.spill [sp]=f42,-16;; stf.spill [sp]=f43,-16;; + stf.spill [sp]=f44,-16;; stf.spill [sp]=f45,-16;; stf.spill [sp]=f46,-16;; stf.spill [sp]=f47,-16;; + stf.spill [sp]=f48,-16;; stf.spill [sp]=f49,-16;; stf.spill [sp]=f50,-16;; stf.spill [sp]=f51,-16;; + stf.spill [sp]=f52,-16;; stf.spill [sp]=f53,-16;; stf.spill [sp]=f54,-16;; stf.spill [sp]=f55,-16;; + stf.spill [sp]=f56,-16;; stf.spill [sp]=f57,-16;; stf.spill [sp]=f58,-16;; stf.spill [sp]=f59,-16;; + stf.spill [sp]=f60,-16;; stf.spill [sp]=f61,-16;; stf.spill [sp]=f62,-16;; stf.spill [sp]=f63,-16;; + stf.spill [sp]=f64,-16;; stf.spill [sp]=f65,-16;; stf.spill [sp]=f66,-16;; stf.spill [sp]=f67,-16;; + stf.spill [sp]=f68,-16;; stf.spill [sp]=f69,-16;; stf.spill [sp]=f70,-16;; stf.spill [sp]=f71,-16;; + stf.spill [sp]=f72,-16;; stf.spill [sp]=f73,-16;; stf.spill [sp]=f74,-16;; stf.spill [sp]=f75,-16;; + stf.spill [sp]=f76,-16;; stf.spill [sp]=f77,-16;; stf.spill [sp]=f78,-16;; stf.spill [sp]=f79,-16;; + stf.spill [sp]=f80,-16;; stf.spill [sp]=f81,-16;; stf.spill [sp]=f82,-16;; stf.spill [sp]=f83,-16;; + stf.spill [sp]=f84,-16;; stf.spill [sp]=f85,-16;; stf.spill [sp]=f86,-16;; stf.spill [sp]=f87,-16;; + stf.spill [sp]=f88,-16;; stf.spill [sp]=f89,-16;; stf.spill [sp]=f90,-16;; stf.spill [sp]=f91,-16;; + stf.spill [sp]=f92,-16;; stf.spill [sp]=f93,-16;; stf.spill [sp]=f94,-16;; stf.spill [sp]=f95,-16;; + stf.spill [sp]=f96,-16;; stf.spill [sp]=f97,-16;; stf.spill [sp]=f98,-16;; stf.spill [sp]=f99,-16;; + stf.spill [sp]=f100,-16;;stf.spill [sp]=f101,-16;;stf.spill [sp]=f102,-16;;stf.spill [sp]=f103,-16;; + stf.spill [sp]=f104,-16;;stf.spill [sp]=f105,-16;;stf.spill [sp]=f106,-16;;stf.spill [sp]=f107,-16;; + stf.spill [sp]=f108,-16;;stf.spill [sp]=f109,-16;;stf.spill [sp]=f110,-16;;stf.spill [sp]=f111,-16;; + stf.spill [sp]=f112,-16;;stf.spill [sp]=f113,-16;;stf.spill [sp]=f114,-16;;stf.spill [sp]=f115,-16;; + stf.spill [sp]=f116,-16;;stf.spill [sp]=f117,-16;;stf.spill [sp]=f118,-16;;stf.spill [sp]=f119,-16;; + stf.spill [sp]=f120,-16;;stf.spill [sp]=f121,-16;;stf.spill [sp]=f122,-16;;stf.spill [sp]=f123,-16;; + stf.spill [sp]=f124,-16;;stf.spill [sp]=f125,-16;;stf.spill [sp]=f126,-16;;stf.spill [sp]=f127,-16;; + invala;; + br b7;; + +//------------------------------// +// restore fp registers // +//------------------------------// +restore_fp_registers:: + ldf.fill f127=[sp],16;;ldf.fill f126=[sp],16;;ldf.fill f125=[sp],16;;ldf.fill f124=[sp],16;; + ldf.fill f123=[sp],16;;ldf.fill f122=[sp],16;;ldf.fill f121=[sp],16;;ldf.fill f120=[sp],16;; + ldf.fill f119=[sp],16;;ldf.fill f118=[sp],16;;ldf.fill f117=[sp],16;;ldf.fill f116=[sp],16;; + ldf.fill f115=[sp],16;;ldf.fill f114=[sp],16;;ldf.fill f113=[sp],16;;ldf.fill f112=[sp],16;; + ldf.fill f111=[sp],16;;ldf.fill f110=[sp],16;;ldf.fill f109=[sp],16;;ldf.fill f108=[sp],16;; + ldf.fill f107=[sp],16;;ldf.fill f106=[sp],16;;ldf.fill f105=[sp],16;;ldf.fill f104=[sp],16;; + ldf.fill f103=[sp],16;;ldf.fill f102=[sp],16;;ldf.fill f101=[sp],16;;ldf.fill f100=[sp],16;; + ldf.fill f99=[sp],16;; ldf.fill f98=[sp],16;; ldf.fill f97=[sp],16;; ldf.fill f96=[sp],16;; + ldf.fill f95=[sp],16;; ldf.fill f94=[sp],16;; ldf.fill f93=[sp],16;; ldf.fill f92=[sp],16;; + ldf.fill f91=[sp],16;; ldf.fill f90=[sp],16;; ldf.fill f89=[sp],16;; ldf.fill f88=[sp],16;; + ldf.fill f87=[sp],16;; ldf.fill f86=[sp],16;; ldf.fill f85=[sp],16;; ldf.fill f84=[sp],16;; + ldf.fill f83=[sp],16;; ldf.fill f82=[sp],16;; ldf.fill f81=[sp],16;; ldf.fill f80=[sp],16;; + ldf.fill f79=[sp],16;; ldf.fill f78=[sp],16;; ldf.fill f77=[sp],16;; ldf.fill f76=[sp],16;; + ldf.fill f75=[sp],16;; ldf.fill f74=[sp],16;; ldf.fill f73=[sp],16;; ldf.fill f72=[sp],16;; + ldf.fill f71=[sp],16;; ldf.fill f70=[sp],16;; ldf.fill f69=[sp],16;; ldf.fill f68=[sp],16;; + ldf.fill f67=[sp],16;; ldf.fill f66=[sp],16;; ldf.fill f65=[sp],16;; ldf.fill f64=[sp],16;; + ldf.fill f63=[sp],16;; ldf.fill f62=[sp],16;; ldf.fill f61=[sp],16;; ldf.fill f60=[sp],16;; + ldf.fill f59=[sp],16;; ldf.fill f58=[sp],16;; ldf.fill f57=[sp],16;; ldf.fill f56=[sp],16;; + ldf.fill f55=[sp],16;; ldf.fill f54=[sp],16;; ldf.fill f53=[sp],16;; ldf.fill f52=[sp],16;; + ldf.fill f51=[sp],16;; ldf.fill f50=[sp],16;; ldf.fill f49=[sp],16;; ldf.fill f48=[sp],16;; + ldf.fill f47=[sp],16;; ldf.fill f46=[sp],16;; ldf.fill f45=[sp],16;; ldf.fill f44=[sp],16;; + ldf.fill f43=[sp],16;; ldf.fill f42=[sp],16;; ldf.fill f41=[sp],16;; ldf.fill f40=[sp],16;; + ldf.fill f39=[sp],16;; ldf.fill f38=[sp],16;; ldf.fill f37=[sp],16;; ldf.fill f36=[sp],16;; + ldf.fill f35=[sp],16;; ldf.fill f34=[sp],16;; ldf.fill f33=[sp],16;; ldf.fill f32=[sp],16;; + ldf.fill f31=[sp],16;; ldf.fill f30=[sp],16;; ldf.fill f29=[sp],16;; ldf.fill f28=[sp],16;; + ldf.fill f27=[sp],16;; ldf.fill f26=[sp],16;; ldf.fill f25=[sp],16;; ldf.fill f24=[sp],16;; + ldf.fill f23=[sp],16;; ldf.fill f22=[sp],16;; ldf.fill f21=[sp],16;; ldf.fill f20=[sp],16;; + ldf.fill f19=[sp],16;; ldf.fill f18=[sp],16;; ldf.fill f17=[sp],16;; ldf.fill f16=[sp],16;; + ldf.fill f15=[sp],16;; ldf.fill f14=[sp],16;; ldf.fill f13=[sp],16;; ldf.fill f12=[sp],16;; + ldf.fill f11=[sp],16;; ldf.fill f10=[sp],16;; ldf.fill f9=[sp],16;; ldf.fill f8=[sp],16;; + ldf.fill f7=[sp],16;; ldf.fill f6=[sp],16;; ldf.fill f5=[sp],16;; ldf.fill f4=[sp],16;; + ldf.fill f3=[sp],16;; ldf.fill f2=[sp],16;; + invala;; + br b7;; + +//----------------------------------------------------------------------------- +//++ +// EsalSetSalDataArea +// +// Register physical address of Esal Data Area +// +// On Entry : +// in0 = Reverse Thunk Address +// in1 = IntThunk Address +// +// Return Value: +// r8 = SAL_SUCCESS +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- + +PROCEDURE_ENTRY (EsalSetSalDataArea) + + NESTED_SETUP (4,8,0,0) + +EsalCalcStart1_3:: + mov r8 = ip;; + add r8 = (ReverseThunkAddress - EsalCalcStart1_3), r8;; + st8 [r8] = in0;; + +EsalCalcStart1_4:: + mov r8 = ip;; + add r8 = (IntThunkAddress - EsalCalcStart1_4), r8;; + st8 [r8] = in1;; + + mov r8 = r0;; + + NESTED_RETURN + +PROCEDURE_EXIT (EsalSetSalDataArea) + +//----------------------------------------------------------------------------- +//++ +// EsagGetReverseThunkAddress +// +// Register physical address of Esal Data Area +// +// On Entry : +// out0 = CodeStart +// out1 = CodeEnd +// out1 = ReverseThunkCode +// +// Return Value: +// r8 = SAL_SUCCESS +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- + +PROCEDURE_ENTRY (EsalGetReverseThunkAddress) + + NESTED_SETUP (4,8,0,0) + +EsalCalcStart1_31:: + mov r8 = ip;; + add r8 = (Ia32CodeStart - EsalCalcStart1_31), r8;; + mov r9 = r8;; + +EsalCalcStart1_41:: + mov r8 = ip;; + add r8 = (Ia32CodeEnd - EsalCalcStart1_41), r8;; + mov r10 = r8;; + +EsalCalcStart1_51:: + mov r8 = ip;; + add r8 = (ReverseThunkAddress - EsalCalcStart1_51), r8;; + mov r11 = r8;; + mov r8 = r0;; + + NESTED_RETURN + +PROCEDURE_EXIT (EsalGetReverseThunkAddress) + + +.align 16 +PROCEDURE_ENTRY (InterruptRedirectionTemplate) + data8 0x90CFCD08 + data8 0x90CFCD09 + data8 0x90CFCD0A + data8 0x90CFCD0B + data8 0x90CFCD0C + data8 0x90CFCD0D + data8 0x90CFCD0E + data8 0x90CFCD0F +PROCEDURE_EXIT (InterruptRedirectionTemplate) + +//------------------------------// +// Reverse Thunk Code // +//------------------------------// + +Ia32CodeStart:: + br.sptk.few Ia32CodeStart;; // IPF CSM integration -Bug (Write This Code) +ReverseThunkCode:: + data8 0xb80f66fa // CLI, JMPE xxxx +ReverseThunkAddress:: + data8 0 // Return Address +IntThunkAddress:: + data8 0 // IntThunk Address +Ia32CodeEnd:: + + + + diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c new file mode 100644 index 0000000000..e601bbd63b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c @@ -0,0 +1,550 @@ +/** @file + Call into 16-bit BIOS code + + BugBug: Thunker does A20 gate. Can we get rid of this code or + put it into Legacy16 code. + +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 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 "LegacyBiosInterface.h" +#include "IpfThunk.h" + +/** + Gets the current flat GDT and IDT descriptors and store them in + Private->IntThunk. These values are used by the Thunk code. + This method must be called before every thunk in order to assure + that the correct GDT and IDT are restored after the thunk. + + @param Private Private context for Legacy BIOS + + @retval EFI_SUCCESS Should only pass. + +**/ +EFI_STATUS +LegacyBiosGetFlatDescs ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + return EFI_SUCCESS; +} + + +/** + BIOS interrupt call function. + + @param BiosInt Int number of BIOS call + @param Segment Segment number + @param Offset Offset in segment + @param Regs IA32 Register set. + @param Stack Base address of stack + @param StackSize Size of stack + + @retval EFI_SUCCESS BIOS interrupt call succeeds. + +**/ +EFI_STATUS +BiosIntCall ( + IN UINT16 BiosInt, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ) +{ + IPF_DWORD_REGS DwordRegs; + UINT64 IntTypeVariable; + + IntTypeVariable = 0x8000000000000000; + IntTypeVariable |= (UINT64)BiosInt; + + DwordRegs.Cs = Segment; + DwordRegs.Eip = Offset; + + DwordRegs.Ds = Regs->X.DS; + DwordRegs.Es = Regs->X.ES; + DwordRegs.Fs = Regs->X.ES; + DwordRegs.Gs = Regs->X.ES; + DwordRegs.Ss = 0xFFFF; + + DwordRegs.Eax = Regs->X.AX; + DwordRegs.Ebx = Regs->X.BX; + // + // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, AX = B10Dh is + // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to write. + // + DwordRegs.Ecx = Regs->E.ECX; + DwordRegs.Edx = Regs->X.DX; + + DwordRegs.Ebp = Regs->X.BP; + DwordRegs.Eflag = *((UINT16 *) &Regs->X.Flags); + + DwordRegs.Edi = Regs->X.DI; + DwordRegs.Esi = Regs->X.SI; + DwordRegs.Esp = 0xFFFFFFFF; + + EfiIaEntryPoint (IntTypeVariable, &DwordRegs, ((UINTN) Stack + StackSize), StackSize); + + Regs->X.CS = DwordRegs.Cs; + + Regs->X.DS = (UINT16) DwordRegs.Ds; + Regs->X.SS = (UINT16) DwordRegs.Ss; + + Regs->E.EAX = DwordRegs.Eax; + Regs->E.EBX = DwordRegs.Ebx; + Regs->E.ECX = DwordRegs.Ecx; + Regs->E.EDX = DwordRegs.Edx; + + Regs->E.EBP = DwordRegs.Ebp; + CopyMem (&Regs->X.Flags, &DwordRegs.Eflag, sizeof (EFI_FLAGS_REG)); + + Regs->E.EDI = DwordRegs.Edi; + Regs->E.ESI = DwordRegs.Esi; + + return EFI_SUCCESS; +} + + +/** + Template of real mode code. + + @param CodeStart Start address of code. + @param CodeEnd End address of code + @param ReverseThunkStart Start of reverse thunk. + @param IntThunk Low memory thunk. + +**/ +VOID +RealModeTemplate ( + OUT UINTN *CodeStart, + OUT UINTN *CodeEnd, + OUT UINTN *ReverseThunkStart, + LOW_MEMORY_THUNK *IntThunk + ) +{ + SAL_RETURN_REGS SalStatus; + + SalStatus = EsalGetReverseThunkAddress (); + + *CodeStart = SalStatus.r9; + *CodeEnd = SalStatus.r10; + *ReverseThunkStart = SalStatus.r11; + +} + + +/** + Allocate memory < 1 MB and copy the thunker code into low memory. Se up + all the descriptors. + + @param Private Private context for Legacy BIOS + + @retval EFI_SUCCESS Should only pass. + +**/ +EFI_STATUS +LegacyBiosInitializeThunk ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + GDT32 *CodeGdt; + GDT32 *DataGdt; + UINTN CodeStart; + UINTN CodeEnd; + UINTN ReverseThunkStart; + UINT32 Base; + LOW_MEMORY_THUNK *IntThunk; + UINTN TempData; + + ASSERT (Private); + + IntThunk = Private->IntThunk; + + // + // Clear the reserved descriptor + // + ZeroMem (&(IntThunk->RealModeGdt[0]), sizeof (GDT32)); + + // + // Setup a descriptor for real-mode code + // + CodeGdt = &(IntThunk->RealModeGdt[1]); + + // + // Fill in the descriptor with our real-mode segment value + // + CodeGdt->Type = 0xA; + // + // code/read + // + CodeGdt->System = 1; + CodeGdt->Dpl = 0; + CodeGdt->Present = 1; + CodeGdt->Software = 0; + CodeGdt->Reserved = 0; + CodeGdt->DefaultSize = 0; + // + // 16 bit operands + // + CodeGdt->Granularity = 0; + + CodeGdt->LimitHi = 0; + CodeGdt->LimitLo = 0xffff; + + Base = (*((UINT32 *) &IntThunk->Code)); + CodeGdt->BaseHi = (Base >> 24) & 0xFF; + CodeGdt->BaseMid = (Base >> 16) & 0xFF; + CodeGdt->BaseLo = Base & 0xFFFF; + + // + // Setup a descriptor for read-mode data + // + DataGdt = &(IntThunk->RealModeGdt[2]); + CopyMem (DataGdt, CodeGdt, sizeof (GDT32)); + + DataGdt->Type = 0x2; + // + // read/write data + // + DataGdt->BaseHi = 0x0; + // + // Base = 0 + // + DataGdt->BaseMid = 0x0; + // + DataGdt->BaseLo = 0x0; + // + DataGdt->LimitHi = 0x0F; + // + // Limit = 4Gb + // + DataGdt->LimitLo = 0xFFFF; + // + DataGdt->Granularity = 0x1; + // + // + // Compute selector value + // + IntThunk->RealModeGdtDesc.Limit = (UINT16) (sizeof (IntThunk->RealModeGdt) - 1); + CopyMem (&IntThunk->RealModeGdtDesc.Base, (UINT32 *) &IntThunk->RealModeGdt, sizeof (UINT32)); + // + // IntThunk->RealModeGdtDesc.Base = *((UINT32*) &IntThunk->RealModeGdt); + // + IntThunk->RealModeIdtDesc.Limit = 0xFFFF; + IntThunk->RealModeIdtDesc.Base = 0; + IntThunk->LowCodeSelector = (UINT32) ((UINTN) CodeGdt - IntThunk->RealModeGdtDesc.Base); + IntThunk->LowDataSelector = (UINT32) ((UINTN) DataGdt - IntThunk->RealModeGdtDesc.Base); + + // + // Initialize low real-mode code thunk + // + RealModeTemplate (&CodeStart, &CodeEnd, &ReverseThunkStart, IntThunk); + + TempData = (UINTN) &(IntThunk->Code); + IntThunk->LowReverseThunkStart = ((UINT32) TempData + (UINT32) (ReverseThunkStart - CodeStart)); + + EsalSetSalDataArea (TempData, (UINTN) IntThunk); + CopyMem (IntThunk->Code, (VOID *) CodeStart, CodeEnd - CodeStart); + + IntThunk->EfiToLegacy16InitTable.ReverseThunkCallSegment = EFI_SEGMENT (*((UINT32 *) &IntThunk->LowReverseThunkStart)); + IntThunk->EfiToLegacy16InitTable.ReverseThunkCallOffset = EFI_OFFSET (*((UINT32 *) &IntThunk->LowReverseThunkStart)); + + return EFI_SUCCESS; +} + + +/** + Thunk to 16-bit real mode and execute a software interrupt with a vector + of BiosInt. Regs will contain the 16-bit register context on entry and + exit. + + @param This Protocol instance pointer. + @param BiosInt Processor interrupt vector to invoke + @param Regs Register contexted passed into (and returned) from + thunk to 16-bit mode + + @retval FALSE Thunk completed, and there were no BIOS errors in the + target code. See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN EFI_IA32_REGISTER_SET *Regs + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + LOW_MEMORY_THUNK *IntThunk; + UINT16 *Stack16; + EFI_TPL OriginalTpl; + UINTN IaSegment; + UINTN IaOffset; + UINTN *Address; + UINTN TempData; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + IntThunk = Private->IntThunk; + + // + // Get the current flat GDT, IDT, and SS and store them in Private->IntThunk. + // + Status = LegacyBiosGetFlatDescs (Private); + ASSERT_EFI_ERROR (Status); + + Regs->X.Flags.Reserved1 = 1; + Regs->X.Flags.Reserved2 = 0; + Regs->X.Flags.Reserved3 = 0; + Regs->X.Flags.Reserved4 = 0; + Regs->X.Flags.IOPL = 3; + Regs->X.Flags.NT = 0; + Regs->X.Flags.IF = 1; + Regs->X.Flags.TF = 0; + Regs->X.Flags.CF = 0; + // + // Clear the error flag; thunk code may set it. + // + Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE); + + // + // Copy regs to low memory stack + // + Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); + CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET)); + + // + // Provide low stack esp + // + TempData = ((UINTN) Stack16) - ((UINTN) IntThunk); + IntThunk->LowStack = *((UINT32 *) &TempData); + + // + // Stack for reverse thunk flat mode. + // It must point to top of stack (end of stack space). + // + TempData = ((UINTN) IntThunk->RevThunkStack) + LOW_STACK_SIZE; + IntThunk->RevFlatStack = *((UINT32 *) &TempData); + + // + // The call to Legacy16 is a critical section to EFI + // + OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + // + // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. + // + Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Call the real mode thunk code + // + TempData = BiosInt * 4; + Address = (UINTN *) TempData; + IaOffset = 0xFFFF & (*Address); + IaSegment = 0xFFFF & ((*Address) >> 16); + + Status = BiosIntCall ( + BiosInt, + (UINT16) IaSegment, + (UINT16) IaOffset, + (EFI_IA32_REGISTER_SET *) Stack16, + IntThunk, + IntThunk->LowStack + ); + + // + // Check for errors with the thunk + // + switch (Status) { + case THUNK_OK: + break; + + case THUNK_ERR_A20_UNSUP: + case THUNK_ERR_A20_FAILED: + default: + // + // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error). + // + Regs->X.Flags.CF = 1; + break; + } + + Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + // + // End critical section + // + gBS->RestoreTPL (OriginalTpl); + + // + // Return the resulting registers + // + CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET)); + + return (BOOLEAN) (Regs->X.Flags.CF != 0); +} + + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and returned) from + thunk to 16-bit mode + @param Stack Caller allocated stack used to pass arguments + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS errors in the + target code. See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosFarCall86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + LOW_MEMORY_THUNK *IntThunk; + UINT16 *Stack16; + EFI_TPL OriginalTpl; + UINTN IaSegment; + UINTN IaOffset; + UINTN TempData; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + IntThunk = Private->IntThunk; + IaSegment = Segment; + IaOffset = Offset; + + // + // Get the current flat GDT and IDT and store them in Private->IntThunk. + // + Status = LegacyBiosGetFlatDescs (Private); + ASSERT_EFI_ERROR (Status); + + Regs->X.Flags.Reserved1 = 1; + Regs->X.Flags.Reserved2 = 0; + Regs->X.Flags.Reserved3 = 0; + Regs->X.Flags.Reserved4 = 0; + Regs->X.Flags.IOPL = 3; + Regs->X.Flags.NT = 0; + Regs->X.Flags.IF = 1; + Regs->X.Flags.TF = 0; + Regs->X.Flags.CF = 0; + // + // Clear the error flag; thunk code may set it. + // + Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE); + if (Stack != NULL && StackSize != 0) { + // + // Copy Stack to low memory stack + // + Stack16 -= StackSize / sizeof (UINT16); + CopyMem (Stack16, Stack, StackSize); + } + // + // Copy regs to low memory stack + // + Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); + CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET)); + + // + // Provide low stack esp + // + TempData = ((UINTN) Stack16) - ((UINTN) IntThunk); + IntThunk->LowStack = *((UINT32 *) &TempData); + + // + // The call to Legacy16 is a critical section to EFI + // + OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + // + // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. + // + Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Call the real mode thunk code + // + Status = BiosIntCall ( + 0x100, + (UINT16) IaSegment, + (UINT16) IaOffset, + (EFI_IA32_REGISTER_SET *) Stack16, + IntThunk, + IntThunk->LowStack + ); + + // + // Check for errors with the thunk + // + switch (Status) { + case THUNK_OK: + break; + + case THUNK_ERR_A20_UNSUP: + case THUNK_ERR_A20_FAILED: + default: + // + // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error). + // + Regs->X.Flags.CF = 1; + break; + } + // + // Restore protected mode interrupt state + // + Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + // + // End critical section + // + gBS->RestoreTPL (OriginalTpl); + + // + // Return the resulting registers + // + CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET)); + Stack16 += sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); + + if (Stack != NULL && StackSize != 0) { + // + // Copy low memory stack to Stack + // + CopyMem (Stack, Stack16, StackSize); + Stack16 += StackSize / sizeof (UINT16); + } + + return (BOOLEAN) (Regs->X.Flags.CF != 0); +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c new file mode 100644 index 0000000000..6ee43ad676 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c @@ -0,0 +1,384 @@ +/** @file + +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 "LegacyBiosInterface.h" +#include + +// Give floppy 3 states +// FLOPPY_PRESENT_WITH_MEDIA = Floppy controller present and media is inserted +// FLOPPY_NOT_PRESENT = No floppy controller present +// FLOPPY_PRESENT_NO_MEDIA = Floppy controller present but no media inserted +// +#define FLOPPY_NOT_PRESENT 0 +#define FLOPPY_PRESENT_WITH_MEDIA 1 +#define FLOPPY_PRESENT_NO_MEDIA 2 + +BBS_TABLE *mBbsTable; +BOOLEAN mBbsTableDoneFlag = FALSE; +BOOLEAN IsHaveMediaInFloppy = TRUE; + +/** + Checks the state of the floppy and if media is inserted. + + This routine checks the state of the floppy and if media is inserted. + There are 3 cases: + No floppy present - Set BBS entry to ignore + Floppy present & no media - Set BBS entry to lowest priority. We cannot + set it to ignore since 16-bit CSM will + indicate no floppy and thus drive A: is + unusable. CSM-16 will not try floppy since + lowest priority and thus not incur boot + time penality. + Floppy present & media - Set BBS entry to some priority. + + @return State of floppy media + +**/ +UINT8 +HasMediaInFloppy ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_ISA_IO_PROTOCOL *IsaIo; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + + HandleBuffer = NULL; + HandleCount = 0; + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIsaIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + // + // If don't find any ISA/IO protocol assume no floppy. Need for floppy + // free system + // + if (HandleCount == 0) { + return FLOPPY_NOT_PRESENT; + } + + ASSERT (HandleBuffer != NULL); + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) { + continue; + } + // + // Update blockio in case the floppy is inserted in during BdsTimeout + // + Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); + + if (EFI_ERROR (Status)) { + continue; + } + + Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + + if (EFI_ERROR (Status)) { + continue; + } + + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (BlkIo->Media->MediaPresent) { + FreePool (HandleBuffer); + return FLOPPY_PRESENT_WITH_MEDIA; + } else { + FreePool (HandleBuffer); + return FLOPPY_PRESENT_NO_MEDIA; + } + } + + FreePool (HandleBuffer); + + return FLOPPY_NOT_PRESENT; + +} + + +/** + Complete build of BBS TABLE. + + @param Private Legacy BIOS Instance data + @param BbsTable BBS Table passed to 16-bit code + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +LegacyBiosBuildBbs ( + IN LEGACY_BIOS_INSTANCE *Private, + IN BBS_TABLE *BbsTable + ) +{ + UINTN BbsIndex; + HDD_INFO *HddInfo; + UINTN HddIndex; + UINTN Index; + + // + // First entry is floppy. + // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE. + // Next n entries are filled in after each ROM is dispatched. + // Entry filled in if follow BBS spec. See LegacyPci.c + // Next entries are for non-BBS compliant ROMS. They are filled in by + // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority + // occurs after that invocation. + // + // Floppy + // Set default state. + // + IsHaveMediaInFloppy = HasMediaInFloppy (); + if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) { + BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY; + } else { + if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) { + BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY; + } else { + BbsTable[0].BootPriority = BBS_IGNORE_ENTRY; + } + } + + BbsTable[0].Bus = 0xff; + BbsTable[0].Device = 0xff; + BbsTable[0].Function = 0xff; + BbsTable[0].DeviceType = BBS_FLOPPY; + BbsTable[0].Class = 01; + BbsTable[0].SubClass = 02; + BbsTable[0].StatusFlags.OldPosition = 0; + BbsTable[0].StatusFlags.Reserved1 = 0; + BbsTable[0].StatusFlags.Enabled = 0; + BbsTable[0].StatusFlags.Failed = 0; + BbsTable[0].StatusFlags.MediaPresent = 0; + BbsTable[0].StatusFlags.Reserved2 = 0; + + // + // Onboard HDD - Note Each HDD controller controls 2 drives + // Master & Slave + // + HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; + // + // Get IDE Drive Info + // + LegacyBiosBuildIdeData (Private, &HddInfo, 0); + + for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) { + + BbsIndex = HddIndex * 2 + 1; + for (Index = 0; Index < 2; ++Index) { + + BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus; + BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device; + BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function; + BbsTable[BbsIndex + Index].Class = 01; + BbsTable[BbsIndex + Index].SubClass = 01; + BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0; + BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0; + BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0; + BbsTable[BbsIndex + Index].StatusFlags.Failed = 0; + BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0; + BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0; + + // + // If no controller found or no device found set to ignore + // else set to unprioritized and set device type + // + if (HddInfo[HddIndex].CommandBaseAddress == 0) { + BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; + } else { + if (Index == 0) { + if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) { + BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; + if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) { + BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; + } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) { + BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; + } else { + // + // for ZIPDISK + // + BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; + } + } else { + BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; + } + } else { + if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) { + BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; + if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) { + BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; + } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) { + BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; + } else { + // + // for ZIPDISK + // + BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; + } + } else { + BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; + } + } + } + } + } + + return EFI_SUCCESS; + +} + + +/** + Get all BBS info + + @param This Protocol instance pointer. + @param HddCount Number of HDD_INFO structures + @param HddInfo Onboard IDE controller information + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Tables returned + @retval EFI_NOT_FOUND resource not found + @retval EFI_DEVICE_ERROR can not get BBS table + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetBbsInfo ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *HddCount, + OUT HDD_INFO **HddInfo, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ) +{ + LEGACY_BIOS_INSTANCE *Private; + EFI_IA32_REGISTER_SET Regs; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; +// HDD_INFO *LocalHddInfo; +// IN BBS_TABLE *LocalBbsTable; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + UINTN TempData; + UINT32 Granularity; + + HandleBuffer = NULL; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; +// LocalHddInfo = EfiToLegacy16BootTable->HddInfo; +// LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; + + if (!mBbsTableDoneFlag) { + mBbsTable = Private->BbsTablePtr; + + // + // Always enable disk controllers so 16-bit CSM code has valid information for all + // drives. + // + // + // Get PciRootBridgeIO protocol + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + + if (NumHandles == 0) { + return EFI_NOT_FOUND; + } + + mBbsTableDoneFlag = TRUE; + for (Index = 0; Index < NumHandles; Index++) { + // + // Connect PciRootBridgeIO protocol handle with FALSE parameter to let + // PCI bus driver enumerate all subsequent handles + // + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); + + } + + LegacyBiosBuildBbs (Private, mBbsTable); + + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity); + + // + // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs. + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16UpdateBbs; + + // + // Pass in handoff data + // + TempData = (UINTN) EfiToLegacy16BootTable; + Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINT32) TempData); + Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINT32) TempData); + + Private->LegacyBios.FarCall86 ( + This, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity); + + if (Regs.X.AX != 0) { + return EFI_DEVICE_ERROR; + } + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + *HddCount = MAX_IDE_CONTROLLER; + *HddInfo = EfiToLegacy16BootTable->HddInfo; + *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; + *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c new file mode 100644 index 0000000000..c45d5d4c3e --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c @@ -0,0 +1,66 @@ +/** @file + This code fills in BDA (0x400) and EBDA (pointed to by 0x4xx) + information. There is support for doing initializeation before + Legacy16 is loaded and before a legacy boot is attempted. + +Copyright (c) 2006 - 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 "LegacyBiosInterface.h" + +/** + Fill in the standard BDA and EBDA stuff before Legacy16 load + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosInitBda ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + BDA_STRUC *Bda; + UINT8 *Ebda; + + Bda = (BDA_STRUC *) ((UINTN) 0x400); + Ebda = (UINT8 *) ((UINTN) 0x9fc00); + + ZeroMem (Bda, 0x100); + ZeroMem (Ebda, 0x400); + // + // 640k-1k for EBDA + // + Bda->MemSize = 0x27f; + Bda->KeyHead = 0x1e; + Bda->KeyTail = 0x1e; + Bda->FloppyData = 0x00; + Bda->FloppyTimeout = 0xff; + + Bda->KeyStart = 0x001E; + Bda->KeyEnd = 0x003E; + Bda->KeyboardStatus = 0x10; + Bda->Ebda = 0x9fc0; + + // + // Move LPT time out here and zero out LPT4 since some SCSI OPROMS + // use this as scratch pad (LPT4 is Reserved) + // + Bda->Lpt1_2Timeout = 0x1414; + Bda->Lpt3_4Timeout = 0x1400; + + *Ebda = 0x01; + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c new file mode 100644 index 0000000000..dd2e2b9167 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c @@ -0,0 +1,1154 @@ +/** @file + +Copyright (c) 2006 - 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 "LegacyBiosInterface.h" + +#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address)) + +// +// define maximum number of HDD system supports +// +#define MAX_HDD_ENTRIES 0x30 + +// +// Module Global: +// Since this driver will only ever produce one instance of the Private Data +// protocol you are not required to dynamically allocate the PrivateData. +// +LEGACY_BIOS_INSTANCE mPrivateData; + +// +// The SMBIOS table in EfiRuntimeServicesData memory +// +VOID *mRuntimeSmbiosEntryPoint = NULL; + +// +// The SMBIOS table in EfiReservedMemoryType memory +// +EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint = 0; +EFI_PHYSICAL_ADDRESS mStructureTableAddress = 0; +UINTN mStructureTablePages = 0; + +/** + Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode + memory. + + @param AllocateType Allocated Legacy Memory Type + @param StartPageAddress Start address of range + @param Pages Number of pages to allocate + @param Result Result of allocation + + @retval EFI_SUCCESS Legacy16 code loaded + @retval Other No protocol installed, unload driver. + +**/ +EFI_STATUS +AllocateLegacyMemory ( + IN EFI_ALLOCATE_TYPE AllocateType, + IN EFI_PHYSICAL_ADDRESS StartPageAddress, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Result + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemPage; + + // + // Allocate Pages of memory less <= StartPageAddress + // + MemPage = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPageAddress; + Status = gBS->AllocatePages ( + AllocateType, + EfiBootServicesCode, + Pages, + &MemPage + ); + // + // Do not ASSERT on Status error but let caller decide since some cases + // memory is already taken but that is ok. + // + if (!EFI_ERROR (Status)) { + *Result = (EFI_PHYSICAL_ADDRESS) (UINTN) MemPage; + } + // + // If reach here the status = EFI_SUCCESS + // + return Status; +} + + +/** + This function is called when EFI needs to reserve an area in the 0xE0000 or 0xF0000 + 64 KB blocks. + + Note: inconsistency with the Framework CSM spec. Per the spec, this function may be + invoked only once. This limitation is relaxed to allow multiple calls in this implemenation. + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of required region + @param Region Region to use. 00 = Either 0xE0000 or 0xF0000 + block Bit0 = 1 0xF0000 block Bit1 = 1 0xE0000 + block + @param Alignment Address alignment. Bit mapped. First non-zero + bit from right is alignment. + @param LegacyMemoryAddress Region Assigned + + @retval EFI_SUCCESS Region assigned + @retval EFI_ACCESS_DENIED Procedure previously invoked + @retval Other Region not assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN UINTN Region, + IN UINTN Alignment, + OUT VOID **LegacyMemoryAddress + ) +{ + + LEGACY_BIOS_INSTANCE *Private; + EFI_IA32_REGISTER_SET Regs; + EFI_STATUS Status; + UINT32 Granularity; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity); + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16GetTableAddress; + Regs.X.BX = (UINT16) Region; + Regs.X.CX = (UINT16) LegacyMemorySize; + Regs.X.DX = (UINT16) Alignment; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + if (Regs.X.AX == 0) { + *LegacyMemoryAddress = (VOID *) (UINTN) ((Regs.X.DS << 4) + Regs.X.BX); + Status = EFI_SUCCESS; + } else { + Status = EFI_OUT_OF_RESOURCES; + } + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity); + + return Status; +} + + +/** + This function is called when copying data to the region assigned by + EFI_LEGACY_BIOS_PROTOCOL.GetLegacyRegion(). + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of data to copy + @param LegacyMemoryAddress Legacy Region destination address Note: must + be in region assigned by + LegacyBiosGetLegacyRegion + @param LegacyMemorySourceAddress Source of data + + @retval EFI_SUCCESS The data was copied successfully. + @retval EFI_ACCESS_DENIED Either the starting or ending address is out of bounds. +**/ +EFI_STATUS +EFIAPI +LegacyBiosCopyLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN VOID *LegacyMemoryAddress, + IN VOID *LegacyMemorySourceAddress + ) +{ + + LEGACY_BIOS_INSTANCE *Private; + UINT32 Granularity; + + if ((LegacyMemoryAddress < (VOID *)(UINTN)0xE0000 ) || + ((UINTN) LegacyMemoryAddress + LegacyMemorySize > (UINTN) 0x100000) + ) { + return EFI_ACCESS_DENIED; + } + // + // There is no protection from writes over lapping if this function is + // called multiple times. + // + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity); + CopyMem (LegacyMemoryAddress, LegacyMemorySourceAddress, LegacyMemorySize); + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity); + + return EFI_SUCCESS; +} + + +/** + Find Legacy16 BIOS image in the FLASH device and shadow it into memory. Find + the $EFI table in the shadow area. Thunk into the Legacy16 code after it had + been shadowed. + + @param Private Legacy BIOS context data + + @retval EFI_SUCCESS Legacy16 code loaded + @retval Other No protocol installed, unload driver. + +**/ +EFI_STATUS +ShadowAndStartLegacy16 ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + UINT8 *Ptr; + UINT8 *PtrEnd; + BOOLEAN Done; + EFI_COMPATIBILITY16_TABLE *Table; + UINT8 CheckSum; + EFI_IA32_REGISTER_SET Regs; + EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + VOID *LegacyBiosImage; + UINTN LegacyBiosImageSize; + UINTN E820Size; + UINT32 *ClearPtr; + BBS_TABLE *BbsTable; + LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable; + UINTN Index; + UINT32 TpmPointer; + VOID *TpmBinaryImage; + UINTN TpmBinaryImageSize; + UINTN Location; + UINTN Alignment; + UINTN TempData; + EFI_PHYSICAL_ADDRESS Address; + UINT16 OldMask; + UINT16 NewMask; + UINT32 Granularity; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + + Location = 0; + Alignment = 0; + + // + // we allocate the C/D/E/F segment as RT code so no one will use it any more. + // + Address = 0xC0000; + gDS->GetMemorySpaceDescriptor (Address, &Descriptor); + if (Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) { + // + // If it is already reserved, we should be safe, or else we allocate it. + // + Status = gBS->AllocatePages ( + AllocateAddress, + EfiRuntimeServicesCode, + 0x40000/EFI_PAGE_SIZE, + &Address + ); + if (EFI_ERROR (Status)) { + // + // Bugbug: need to figure out whether C/D/E/F segment should be marked as reserved memory. + // + DEBUG ((DEBUG_ERROR, "Failed to allocate the C/D/E/F segment Status = %r", Status)); + } + } + + // + // start testtest + // GetTimerValue (&Ticker); + // + // gRT->SetVariable (L"StartLegacy", + // &gEfiGlobalVariableGuid, + // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + // sizeof (UINT64), + // (VOID *)&Ticker + // ); + // end testtest + // + EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; + Status = Private->LegacyBiosPlatform->GetPlatformInfo ( + Private->LegacyBiosPlatform, + EfiGetPlatformBinarySystemRom, + &LegacyBiosImage, + &LegacyBiosImageSize, + &Location, + &Alignment, + 0, + 0 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Private->BiosStart = (UINT32) (0x100000 - LegacyBiosImageSize); + Private->OptionRom = 0xc0000; + Private->LegacyBiosImageSize = (UINT32) LegacyBiosImageSize; + + // + // Can only shadow into memory allocated for legacy useage. + // + ASSERT (Private->BiosStart > Private->OptionRom); + + // + // Shadow Legacy BIOS. Turn on memory and copy image + // + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity); + + ClearPtr = (VOID *) ((UINTN) 0xc0000); + + // + // Initialize region from 0xc0000 to start of BIOS to all ffs. This allows unused + // regions to be used by EMM386 etc. + // + SetMem ((VOID *) ClearPtr, (UINTN) (0x40000 - LegacyBiosImageSize), 0xff); + + TempData = Private->BiosStart; + + CopyMem ( + (VOID *) TempData, + LegacyBiosImage, + (UINTN) LegacyBiosImageSize + ); + + Private->Cpu->FlushDataCache (Private->Cpu, 0xc0000, 0x40000, EfiCpuFlushTypeWriteBackInvalidate); + + // + // Search for Legacy16 table in Shadowed ROM + // + Done = FALSE; + Table = NULL; + for (Ptr = (UINT8 *) TempData; Ptr < (UINT8 *) ((UINTN) 0x100000) && !Done; Ptr += 0x10) { + if (*(UINT32 *) Ptr == SIGNATURE_32 ('I', 'F', 'E', '$')) { + Table = (EFI_COMPATIBILITY16_TABLE *) Ptr; + PtrEnd = Ptr + Table->TableLength; + for (CheckSum = 0; Ptr < PtrEnd; Ptr++) { + CheckSum = (UINT8) (CheckSum +*Ptr); + } + + Done = TRUE; + } + } + + if (Table == NULL) { + DEBUG ((EFI_D_ERROR, "No Legacy16 table found\n")); + return EFI_NOT_FOUND; + } + + if (!Done) { + // + // Legacy16 table header checksum error. + // + DEBUG ((EFI_D_ERROR, "Legacy16 table found with bad talbe header checksum\n")); + } + + // + // Remember location of the Legacy16 table + // + Private->Legacy16Table = Table; + Private->Legacy16CallSegment = Table->Compatibility16CallSegment; + Private->Legacy16CallOffset = Table->Compatibility16CallOffset; + EfiToLegacy16InitTable = &Private->IntThunk->EfiToLegacy16InitTable; + Private->Legacy16InitPtr = EfiToLegacy16InitTable; + Private->Legacy16BootPtr = &Private->IntThunk->EfiToLegacy16BootTable; + Private->InternalIrqRoutingTable = NULL; + Private->NumberIrqRoutingEntries = 0; + Private->BbsTablePtr = NULL; + Private->LegacyEfiHddTable = NULL; + Private->DiskEnd = 0; + Private->Disk4075 = 0; + Private->HddTablePtr = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo; + Private->NumberHddControllers = MAX_IDE_CONTROLLER; + Private->Dump[0] = 'D'; + Private->Dump[1] = 'U'; + Private->Dump[2] = 'M'; + Private->Dump[3] = 'P'; + + ZeroMem ( + Private->Legacy16BootPtr, + sizeof (EFI_TO_COMPATIBILITY16_BOOT_TABLE) + ); + + // + // Store away a copy of the EFI System Table + // + Table->EfiSystemTable = (UINT32) (UINTN) gST; + + // + // IPF CSM integration -Bug + // + // Construct the Legacy16 boot memory map. This sets up number of + // E820 entries. + // + LegacyBiosBuildE820 (Private, &E820Size); + // + // Initialize BDA and EBDA standard values needed to load Legacy16 code + // + LegacyBiosInitBda (Private); + LegacyBiosInitCmos (Private); + + // + // All legacy interrupt should be masked when do initialization work from legacy 16 code. + // + Private->Legacy8259->GetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL); + NewMask = 0xFFFF; + Private->Legacy8259->SetMask(Private->Legacy8259, &NewMask, NULL, NULL, NULL); + + // + // Call into Legacy16 code to do an INIT + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16InitializeYourself; + Regs.X.ES = EFI_SEGMENT (*((UINT32 *) &EfiToLegacy16InitTable)); + Regs.X.BX = EFI_OFFSET (*((UINT32 *) &EfiToLegacy16InitTable)); + + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Table->Compatibility16CallSegment, + Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + // + // Restore original legacy interrupt mask value + // + Private->Legacy8259->SetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL); + + if (Regs.X.AX != 0) { + return EFI_DEVICE_ERROR; + } + + // + // start testtest + // GetTimerValue (&Ticker); + // + // gRT->SetVariable (L"BackFromInitYourself", + // &gEfiGlobalVariableGuid, + // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + // sizeof (UINT64), + // (VOID *)&Ticker + // ); + // end testtest + // + // Copy E820 table after InitializeYourself is completed + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16GetTableAddress; + Regs.X.CX = (UINT16) E820Size; + Regs.X.DX = 1; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Table->Compatibility16CallSegment, + Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + Table->E820Length = (UINT32) E820Size; + if (Regs.X.AX != 0) { + DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n")); + } else { + TempData = Table->E820Pointer; + CopyMem ((VOID *) TempData, Private->E820Table, E820Size); + } + // + // Get PnPInstallationCheck Info. + // + Private->PnPInstallationCheckSegment = Table->PnPInstallationCheckSegment; + Private->PnPInstallationCheckOffset = Table->PnPInstallationCheckOffset; + + // + // Check if PCI Express is supported. If yes, Save base address. + // + Status = Private->LegacyBiosPlatform->GetPlatformInfo ( + Private->LegacyBiosPlatform, + EfiGetPlatformPciExpressBase, + NULL, + NULL, + &Location, + &Alignment, + 0, + 0 + ); + if (!EFI_ERROR (Status)) { + Private->Legacy16Table->PciExpressBase = (UINT32)Location; + Location = 0; + } + // + // Check if TPM is supported. If yes get a region in E0000,F0000 to copy it + // into, copy it and update pointer to binary image. This needs to be + // done prior to any OPROM for security purposes. + // + Status = Private->LegacyBiosPlatform->GetPlatformInfo ( + Private->LegacyBiosPlatform, + EfiGetPlatformBinaryTpmBinary, + &TpmBinaryImage, + &TpmBinaryImageSize, + &Location, + &Alignment, + 0, + 0 + ); + if (!EFI_ERROR (Status)) { + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16GetTableAddress; + Regs.X.CX = (UINT16) TpmBinaryImageSize; + Regs.X.DX = 1; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Table->Compatibility16CallSegment, + Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + TpmPointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + if (Regs.X.AX != 0) { + DEBUG ((EFI_D_ERROR, "TPM cannot be loaded\n")); + } else { + CopyMem ((VOID *) (UINTN)TpmPointer, TpmBinaryImage, TpmBinaryImageSize); + Table->TpmSegment = Regs.X.DS; + Table->TpmOffset = Regs.X.BX; + + } + } + // + // Lock the Legacy BIOS region + // + Private->Cpu->FlushDataCache (Private->Cpu, Private->BiosStart, (UINT32) LegacyBiosImageSize, EfiCpuFlushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock (Private->LegacyRegion, Private->BiosStart, (UINT32) LegacyBiosImageSize, &Granularity); + + // + // Get the BbsTable from LOW_MEMORY_THUNK + // + BbsTable = (BBS_TABLE *)(UINTN)Private->IntThunk->BbsTable; + ZeroMem ((VOID *)BbsTable, sizeof (Private->IntThunk->BbsTable)); + + EfiToLegacy16BootTable->BbsTable = (UINT32)(UINTN)BbsTable; + Private->BbsTablePtr = (VOID *) BbsTable; + // + // Skip Floppy and possible onboard IDE drives + // + EfiToLegacy16BootTable->NumberBbsEntries = 1 + 2 * MAX_IDE_CONTROLLER; + + for (Index = 0; Index < (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); Index++) { + BbsTable[Index].BootPriority = BBS_IGNORE_ENTRY; + } + // + // Allocate space for Legacy HDD table + // + LegacyEfiHddTable = (LEGACY_EFI_HDD_TABLE *) AllocateZeroPool ((UINTN) MAX_HDD_ENTRIES * sizeof (LEGACY_EFI_HDD_TABLE)); + ASSERT (LegacyEfiHddTable); + + Private->LegacyEfiHddTable = LegacyEfiHddTable; + Private->LegacyEfiHddTableIndex = 0x00; + + // + // start testtest + // GetTimerValue (&Ticker); + // + // gRT->SetVariable (L"EndOfLoadFv", + // &gEfiGlobalVariableGuid, + // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + // sizeof (UINT64), + // (VOID *)&Ticker + // ); + // end testtest + // + return EFI_SUCCESS; +} + +/** + Shadow all legacy16 OPROMs that haven't been shadowed. + Warning: Use this with caution. This routine disconnects all EFI + drivers. If used externally then caller must re-connect EFI + drivers. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS OPROMs shadowed + +**/ +EFI_STATUS +EFIAPI +LegacyBiosShadowAllLegacyOproms ( + IN EFI_LEGACY_BIOS_PROTOCOL *This + ) +{ + LEGACY_BIOS_INSTANCE *Private; + + // + // EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + // EFI_LEGACY16_TABLE *Legacy16Table; + // + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + + // + // LegacyBiosPlatform = Private->LegacyBiosPlatform; + // Legacy16Table = Private->Legacy16Table; + // + // Shadow PCI ROMs. We must do this near the end since this will kick + // of Native EFI drivers that may be needed to collect info for Legacy16 + // + // WARNING: PciIo is gone after this call. + // + PciProgramAllInterruptLineRegisters (Private); + + PciShadowRoms (Private); + + // + // Shadow PXE base code, BIS etc. + // + // LegacyBiosPlatform->ShadowServiceRoms (LegacyBiosPlatform, + // &Private->OptionRom, + // Legacy16Table); + // + return EFI_SUCCESS; +} + +/** + Get the PCI BIOS interface version. + + @param Private Driver private data. + + @return The PCI interface version number in Binary Coded Decimal (BCD) format. + E.g.: 0x0210 indicates 2.10, 0x0300 indicates 3.00 + +**/ +UINT16 +GetPciInterfaceVersion ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_IA32_REGISTER_SET Reg; + BOOLEAN ThunkFailed; + UINT16 PciInterfaceVersion; + + PciInterfaceVersion = 0; + + Reg.X.AX = 0xB101; + Reg.E.EDI = 0; + + ThunkFailed = Private->LegacyBios.Int86 (&Private->LegacyBios, 0x1A, &Reg); + if (!ThunkFailed) { + // + // From PCI Firmware 3.0 Specification: + // If the CARRY FLAG [CF] is cleared and AH is set to 00h, it is still necessary to examine the + // contents of [EDX] for the presence of the string "PCI" + (trailing space) to fully validate the + // presence of the PCI function set. [BX] will further indicate the version level, with enough + // granularity to allow for incremental changes in the code that don't affect the function interface. + // Version numbers are stored as Binary Coded Decimal (BCD) values. For example, Version 2.10 + // would be returned as a 02h in the [BH] registers and 10h in the [BL] registers. + // + if ((Reg.X.Flags.CF == 0) && (Reg.H.AH == 0) && (Reg.E.EDX == SIGNATURE_32 ('P', 'C', 'I', ' '))) { + PciInterfaceVersion = Reg.X.BX; + } + } + return PciInterfaceVersion; +} + +/** + Callback function to calculate SMBIOS table size, and allocate memory for SMBIOS table. + SMBIOS table will be copied into EfiReservedMemoryType memory in legacy boot path. + + @param Event Event whose notification function is being invoked. + @param Context The pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +InstallSmbiosEventCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; + + // + // Get SMBIOS table from EFI configuration table + // + Status = EfiGetSystemConfigurationTable ( + &gEfiSmbiosTableGuid, + &mRuntimeSmbiosEntryPoint + ); + if ((EFI_ERROR (Status)) || (mRuntimeSmbiosEntryPoint == NULL)) { + return; + } + + EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint; + + // + // Allocate memory for SMBIOS Entry Point Structure. + // CSM framework spec requires SMBIOS table below 4GB in EFI_TO_COMPATIBILITY16_BOOT_TABLE. + // + if (mReserveSmbiosEntryPoint == 0) { + // + // Entrypoint structure with fixed size is allocated only once. + // + mReserveSmbiosEntryPoint = SIZE_4GB - 1; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)), + &mReserveSmbiosEntryPoint + ); + if (EFI_ERROR (Status)) { + mReserveSmbiosEntryPoint = 0; + return; + } + DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Entry Point Structure\n")); + } + + if ((mStructureTableAddress != 0) && + (mStructureTablePages < (UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength))) { + // + // If original buffer is not enough for the new SMBIOS table, free original buffer and re-allocate + // + gBS->FreePages (mStructureTableAddress, mStructureTablePages); + mStructureTableAddress = 0; + mStructureTablePages = 0; + DEBUG ((EFI_D_INFO, "Original size is not enough. Re-allocate the memory.\n")); + } + + if (mStructureTableAddress == 0) { + // + // Allocate reserved memory below 4GB. + // Smbios spec requires the structure table is below 4GB. + // + mStructureTableAddress = SIZE_4GB - 1; + mStructureTablePages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + mStructureTablePages, + &mStructureTableAddress + ); + if (EFI_ERROR (Status)) { + gBS->FreePages ( + mReserveSmbiosEntryPoint, + EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)) + ); + mReserveSmbiosEntryPoint = 0; + mStructureTableAddress = 0; + mStructureTablePages = 0; + return; + } + DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Structure Table\n")); + } +} + +/** + Install Driver to produce Legacy BIOS protocol. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Legacy BIOS protocol installed + @retval No protocol installed, unload driver. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosInstall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable; + EFI_PHYSICAL_ADDRESS MemoryAddress; + EFI_PHYSICAL_ADDRESS EbdaReservedBaseAddress; + VOID *MemoryPtr; + EFI_PHYSICAL_ADDRESS MemoryAddressUnder1MB; + UINTN Index; + UINT32 *BaseVectorMaster; + EFI_PHYSICAL_ADDRESS StartAddress; + UINT32 *ClearPtr; + EFI_PHYSICAL_ADDRESS MemStart; + UINT32 IntRedirCode; + UINT32 Granularity; + BOOLEAN DecodeOn; + UINT32 MemorySize; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINT64 Length; + UINT8 *SecureBoot; + EFI_EVENT InstallSmbiosEvent; + + // + // Load this driver's image to memory + // + Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // When UEFI Secure Boot is enabled, CSM module will not start any more. + // + SecureBoot = NULL; + GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL); + if ((SecureBoot != NULL) && (*SecureBoot == SECURE_BOOT_MODE_ENABLE)) { + FreePool (SecureBoot); + return EFI_SECURITY_VIOLATION; + } + + if (SecureBoot != NULL) { + FreePool (SecureBoot); + } + + Private = &mPrivateData; + ZeroMem (Private, sizeof (LEGACY_BIOS_INSTANCE)); + + // + // Grab a copy of all the protocols we depend on. Any error would + // be a dispatcher bug!. + // + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Private->Cpu); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &Private->Timer); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiLegacyRegion2ProtocolGuid, NULL, (VOID **) &Private->LegacyRegion); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiLegacyBiosPlatformProtocolGuid, NULL, (VOID **) &Private->LegacyBiosPlatform); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &Private->Legacy8259); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, (VOID **) &Private->LegacyInterrupt); + ASSERT_EFI_ERROR (Status); + + // + // Locate Memory Test Protocol if exists + // + Status = gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + (VOID **) &Private->GenericMemoryTest + ); + ASSERT_EFI_ERROR (Status); + + // + // Make sure all memory from 0-640K is tested + // + for (StartAddress = 0; StartAddress < 0xa0000; ) { + gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor); + if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) { + StartAddress = Descriptor.BaseAddress + Descriptor.Length; + continue; + } + Length = MIN (Descriptor.Length, 0xa0000 - StartAddress); + Private->GenericMemoryTest->CompatibleRangeTest ( + Private->GenericMemoryTest, + StartAddress, + Length + ); + StartAddress = StartAddress + Length; + } + // + // Make sure all memory from 1MB to 16MB is tested and added to memory map + // + for (StartAddress = BASE_1MB; StartAddress < BASE_16MB; ) { + gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor); + if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) { + StartAddress = Descriptor.BaseAddress + Descriptor.Length; + continue; + } + Length = MIN (Descriptor.Length, BASE_16MB - StartAddress); + Private->GenericMemoryTest->CompatibleRangeTest ( + Private->GenericMemoryTest, + StartAddress, + Length + ); + StartAddress = StartAddress + Length; + } + + Private->Signature = LEGACY_BIOS_INSTANCE_SIGNATURE; + + Private->LegacyBios.Int86 = LegacyBiosInt86; + Private->LegacyBios.FarCall86 = LegacyBiosFarCall86; + Private->LegacyBios.CheckPciRom = LegacyBiosCheckPciRom; + Private->LegacyBios.InstallPciRom = LegacyBiosInstallPciRom; + Private->LegacyBios.LegacyBoot = LegacyBiosLegacyBoot; + Private->LegacyBios.UpdateKeyboardLedStatus = LegacyBiosUpdateKeyboardLedStatus; + Private->LegacyBios.GetBbsInfo = LegacyBiosGetBbsInfo; + Private->LegacyBios.ShadowAllLegacyOproms = LegacyBiosShadowAllLegacyOproms; + Private->LegacyBios.PrepareToBootEfi = LegacyBiosPrepareToBootEfi; + Private->LegacyBios.GetLegacyRegion = LegacyBiosGetLegacyRegion; + Private->LegacyBios.CopyLegacyRegion = LegacyBiosCopyLegacyRegion; + Private->LegacyBios.BootUnconventionalDevice = LegacyBiosBootUnconventionalDevice; + + Private->ImageHandle = ImageHandle; + + // + // Enable read attribute of legacy region. + // + DecodeOn = TRUE; + Private->LegacyRegion->Decode ( + Private->LegacyRegion, + 0xc0000, + 0x40000, + &Granularity, + &DecodeOn + ); + // + // Set Cachebility for legacy region + // BUGBUG: Comments about this legacy region cacheability setting + // This setting will make D865GCHProduction CSM Unhappy + // + if (PcdGetBool (PcdLegacyBiosCacheLegacyRegion)) { + gDS->SetMemorySpaceAttributes ( + 0x0, + 0xA0000, + EFI_MEMORY_WB + ); + gDS->SetMemorySpaceAttributes ( + 0xc0000, + 0x40000, + EFI_MEMORY_WB + ); + } + + gDS->SetMemorySpaceAttributes ( + 0xA0000, + 0x20000, + EFI_MEMORY_UC + ); + + // + // Allocate 0 - 4K for real mode interupt vectors and BDA. + // + AllocateLegacyMemory ( + AllocateAddress, + 0, + 1, + &MemoryAddress + ); + ASSERT (MemoryAddress == 0x000000000); + + ClearPtr = (VOID *) ((UINTN) 0x0000); + + // + // Initialize region from 0x0000 to 4k. This initializes interrupt vector + // range. + // + gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K); + ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00); + + // + // Allocate pages for OPROM usage + // + MemorySize = PcdGet32 (PcdEbdaReservedMemorySize); + ASSERT ((MemorySize & 0xFFF) == 0); + + Status = AllocateLegacyMemory ( + AllocateAddress, + CONVENTIONAL_MEMORY_TOP - MemorySize, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddress + ); + ASSERT_EFI_ERROR (Status); + + ZeroMem ((VOID *) ((UINTN) MemoryAddress), MemorySize); + + // + // Allocate all 32k chunks from 0x60000 ~ 0x88000 for Legacy OPROMs that + // don't use PMM but look for zeroed memory. Note that various non-BBS + // OpROMs expect different areas to be free + // + EbdaReservedBaseAddress = MemoryAddress; + MemoryAddress = PcdGet32 (PcdOpromReservedMemoryBase); + MemorySize = PcdGet32 (PcdOpromReservedMemorySize); + // + // Check if base address and size for reserved memory are 4KB aligned. + // + ASSERT ((MemoryAddress & 0xFFF) == 0); + ASSERT ((MemorySize & 0xFFF) == 0); + // + // Check if the reserved memory is below EBDA reserved range. + // + ASSERT ((MemoryAddress < EbdaReservedBaseAddress) && ((MemoryAddress + MemorySize - 1) < EbdaReservedBaseAddress)); + for (MemStart = MemoryAddress; MemStart < MemoryAddress + MemorySize; MemStart += 0x1000) { + Status = AllocateLegacyMemory ( + AllocateAddress, + MemStart, + 1, + &StartAddress + ); + if (!EFI_ERROR (Status)) { + MemoryPtr = (VOID *) ((UINTN) StartAddress); + ZeroMem (MemoryPtr, 0x1000); + } else { + DEBUG ((EFI_D_ERROR, "WARNING: Allocate legacy memory fail for SCSI card - %x\n", MemStart)); + } + } + + // + // Allocate low PMM memory and zero it out + // + MemorySize = PcdGet32 (PcdLowPmmMemorySize); + ASSERT ((MemorySize & 0xFFF) == 0); + Status = AllocateLegacyMemory ( + AllocateMaxAddress, + CONVENTIONAL_MEMORY_TOP, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddressUnder1MB + ); + ASSERT_EFI_ERROR (Status); + + ZeroMem ((VOID *) ((UINTN) MemoryAddressUnder1MB), MemorySize); + + // + // Allocate space for thunker and Init Thunker + // + Status = AllocateLegacyMemory ( + AllocateMaxAddress, + CONVENTIONAL_MEMORY_TOP, + (sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 2, + &MemoryAddress + ); + ASSERT_EFI_ERROR (Status); + Private->IntThunk = (LOW_MEMORY_THUNK *) (UINTN) MemoryAddress; + EfiToLegacy16InitTable = &Private->IntThunk->EfiToLegacy16InitTable; + EfiToLegacy16InitTable->ThunkStart = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress; + EfiToLegacy16InitTable->ThunkSizeInBytes = (UINT32) (sizeof (LOW_MEMORY_THUNK)); + + Status = LegacyBiosInitializeThunk (Private); + ASSERT_EFI_ERROR (Status); + + // + // Init the legacy memory map in memory < 1 MB. + // + EfiToLegacy16InitTable->BiosLessThan1MB = (UINT32) MemoryAddressUnder1MB; + EfiToLegacy16InitTable->LowPmmMemory = (UINT32) MemoryAddressUnder1MB; + EfiToLegacy16InitTable->LowPmmMemorySizeInBytes = MemorySize; + + MemorySize = PcdGet32 (PcdHighPmmMemorySize); + ASSERT ((MemorySize & 0xFFF) == 0); + // + // Allocate high PMM Memory under 16 MB + // + Status = AllocateLegacyMemory ( + AllocateMaxAddress, + 0x1000000, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddress + ); + if (EFI_ERROR (Status)) { + // + // If it fails, allocate high PMM Memory under 4GB + // + Status = AllocateLegacyMemory ( + AllocateMaxAddress, + 0xFFFFFFFF, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddress + ); + } + if (!EFI_ERROR (Status)) { + EfiToLegacy16InitTable->HiPmmMemory = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress; + EfiToLegacy16InitTable->HiPmmMemorySizeInBytes = MemorySize; + } + + // + // ShutdownAPs(); + // + // Start the Legacy BIOS; + // + Status = ShadowAndStartLegacy16 (Private); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Initialize interrupt redirection code and entries; + // IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. + // + CopyMem ( + Private->IntThunk->InterruptRedirectionCode, + (VOID *) (UINTN) InterruptRedirectionTemplate, + sizeof (Private->IntThunk->InterruptRedirectionCode) + ); + + // + // Save Unexpected interrupt vector so can restore it just prior to boot + // + BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER); + Private->BiosUnexpectedInt = BaseVectorMaster[0]; + IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode; + for (Index = 0; Index < 8; Index++) { + BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4); + } + // + // Save EFI value + // + Private->ThunkSeg = (UINT16) (EFI_SEGMENT (IntRedirCode)); + + // + // Allocate reserved memory for SMBIOS table used in legacy boot if SMBIOS table exists + // + InstallSmbiosEventCallback (NULL, NULL); + + // + // Create callback function to update the size of reserved memory after LegacyBiosDxe starts + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + InstallSmbiosEventCallback, + NULL, + &gEfiSmbiosTableGuid, + &InstallSmbiosEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Make a new handle and install the protocol + // + Private->Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Private->Handle, + &gEfiLegacyBiosProtocolGuid, + EFI_NATIVE_INTERFACE, + &Private->LegacyBios + ); + Private->Csm16PciInterfaceVersion = GetPciInterfaceVersion (Private); + + DEBUG ((EFI_D_INFO, "CSM16 PCI BIOS Interface Version: %02x.%02x\n", + (UINT8) (Private->Csm16PciInterfaceVersion >> 8), + (UINT8) Private->Csm16PciInterfaceVersion + )); + ASSERT (Private->Csm16PciInterfaceVersion != 0); + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf new file mode 100644 index 0000000000..f8cc4f3fc4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf @@ -0,0 +1,150 @@ +## @file +# Legacy Bios Module to support CSM. +# +# This driver installs Legacy Bios Protocol to support CSM module work in EFI system. +# +# 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 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 = LegacyBiosDxe + MODULE_UNI_FILE = LegacyBiosDxe.uni + FILE_GUID = F122A15C-C10B-4d54-8F48-60F4F06DD1AD + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = LegacyBiosInstall + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF +# + +[Sources] + LegacyCmos.c + LegacyIde.c + LegacyBios.c + LegacyBda.c + LegacyBiosInterface.h + LegacyPci.c + +[Sources.Ia32] + IA32/InterruptTable.S + IA32/InterruptTable.asm + Thunk.c + LegacyBootSupport.c + LegacyBbs.c + LegacySio.c + +[Sources.X64] + X64/InterruptTable.asm + X64/InterruptTable.S + Thunk.c + LegacyBootSupport.c + LegacyBbs.c + LegacySio.c + +[Sources.IPF] + Ipf/IpfThunk.s + Ipf/Thunk.c + Ipf/IpfThunk.i + Ipf/IpfBootSupport.c + Ipf/IpfThunk.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +[LibraryClasses] + DevicePathLib + UefiBootServicesTableLib + MemoryAllocationLib + UefiDriverEntryPoint + BaseMemoryLib + UefiLib + DebugLib + DxeServicesTableLib + PcdLib + ReportStatusCodeLib + PeCoffLib + CacheMaintenanceLib + DebugAgentLib + +[LibraryClasses.IA32] + IoLib + HobLib + UefiRuntimeServicesTableLib + BaseLib + +[LibraryClasses.X64] + IoLib + HobLib + UefiRuntimeServicesTableLib + BaseLib + +[LibraryClasses.IPF] + IoLib + UefiRuntimeServicesTableLib + + +[Guids] + gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_CONSUMES ##GUID #Used in LegacyBiosBuildIdeData() to assure device is a disk + gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ##SystemTable + gEfiLegacyBiosGuid ## SOMETIMES_CONSUMES ##GUID #Used in LegacyBiosInstallVgaRom() to locate handle buffer + +[Guids.IA32] + gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ##SystemTable + gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ##SystemTable + +[Guids.X64] + gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ##SystemTable + gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ##SystemTable + + +[Protocols] + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES + gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiPciRootBridgeIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiCpuArchProtocolGuid ## CONSUMES + gEfiTimerArchProtocolGuid ## CONSUMES + gEfiIsaIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiGenericMemTestProtocolGuid ## CONSUMES + gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimpleTextInProtocolGuid ## SOMETIMES_CONSUMES + gEfiLegacy8259ProtocolGuid ## CONSUMES + gEfiLegacyBiosPlatformProtocolGuid ## CONSUMES + gEfiLegacyInterruptProtocolGuid ## CONSUMES + gEfiLegacyRegion2ProtocolGuid ## CONSUMES + gEfiLegacyBiosProtocolGuid ## PRODUCES + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEndOpromShadowAddress ## SOMETIMES_CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize ## CONSUMES + +[Depex] + gEfiLegacyRegion2ProtocolGuid AND gEfiLegacyInterruptProtocolGuid AND gEfiLegacyBiosPlatformProtocolGuid AND gEfiLegacy8259ProtocolGuid AND gEfiGenericMemTestProtocolGuid AND gEfiCpuArchProtocolGuid AND gEfiTimerArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + LegacyBiosDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni new file mode 100644 index 0000000000..30e995c2dc Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni new file mode 100644 index 0000000000..c62c69e3cd Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h new file mode 100644 index 0000000000..fcc0190d1e --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h @@ -0,0 +1,1541 @@ +/** @file + +Copyright (c) 2006 - 2015, Intel 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 _LEGACY_BIOS_INTERFACE_ +#define _LEGACY_BIOS_INTERFACE_ + + +#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 + +// +// BUGBUG: This entry maybe changed to PCD in future and wait for +// redesign of BDS library +// +#define MAX_BBS_ENTRIES 0x100 + +// +// Thunk Status Codes +// (These apply only to errors with the thunk and not to the code that was +// thunked to.) +// +#define THUNK_OK 0x00 +#define THUNK_ERR_A20_UNSUP 0x01 +#define THUNK_ERR_A20_FAILED 0x02 + +// +// Vector base definitions +// +// +// 8259 Hardware definitions +// +#define LEGACY_MODE_BASE_VECTOR_MASTER 0x08 +#define LEGACY_MODE_BASE_VECTOR_SLAVE 0x70 + +// +// The original PC used INT8-F for master PIC. Since these mapped over +// processor exceptions TIANO moved the master PIC to INT68-6F. +// +// The vector base for slave PIC is set as 0x70 for PC-AT compatibility. +// +#define PROTECTED_MODE_BASE_VECTOR_MASTER 0x68 +#define PROTECTED_MODE_BASE_VECTOR_SLAVE 0x70 + +// +// When we call CSM16 functions, some CSM16 use es:[offset + 0xabcd] to get data passed from CSM32, +// offset + 0xabcd could overflow which exceeds 0xFFFF which is invalid in real mode. +// So this will keep offset as small as possible to avoid offset overflow in real mode. +// +#define NORMALIZE_EFI_SEGMENT(_Adr) (UINT16) (((UINTN) (_Adr)) >> 4) +#define NORMALIZE_EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xf) + +// +// Trace defines +// +// +#define LEGACY_BDA_TRACE 0x000 +#define LEGACY_BIOS_TRACE 0x040 +#define LEGACY_BOOT_TRACE 0x080 +#define LEGACY_CMOS_TRACE 0x0C0 +#define LEGACY_IDE_TRACE 0x100 +#define LEGACY_MP_TRACE 0x140 +#define LEGACY_PCI_TRACE 0x180 +#define LEGACY_SIO_TRACE 0x1C0 + +#define LEGACY_PCI_TRACE_000 LEGACY_PCI_TRACE + 0x00 +#define LEGACY_PCI_TRACE_001 LEGACY_PCI_TRACE + 0x01 +#define LEGACY_PCI_TRACE_002 LEGACY_PCI_TRACE + 0x02 +#define LEGACY_PCI_TRACE_003 LEGACY_PCI_TRACE + 0x03 +#define LEGACY_PCI_TRACE_004 LEGACY_PCI_TRACE + 0x04 +#define LEGACY_PCI_TRACE_005 LEGACY_PCI_TRACE + 0x05 +#define LEGACY_PCI_TRACE_006 LEGACY_PCI_TRACE + 0x06 +#define LEGACY_PCI_TRACE_007 LEGACY_PCI_TRACE + 0x07 +#define LEGACY_PCI_TRACE_008 LEGACY_PCI_TRACE + 0x08 +#define LEGACY_PCI_TRACE_009 LEGACY_PCI_TRACE + 0x09 +#define LEGACY_PCI_TRACE_00A LEGACY_PCI_TRACE + 0x0A +#define LEGACY_PCI_TRACE_00B LEGACY_PCI_TRACE + 0x0B +#define LEGACY_PCI_TRACE_00C LEGACY_PCI_TRACE + 0x0C +#define LEGACY_PCI_TRACE_00D LEGACY_PCI_TRACE + 0x0D +#define LEGACY_PCI_TRACE_00E LEGACY_PCI_TRACE + 0x0E +#define LEGACY_PCI_TRACE_00F LEGACY_PCI_TRACE + 0x0F + +#define BDA_VIDEO_MODE 0x49 + +#define IDE_PI_REGISTER_PNE BIT0 +#define IDE_PI_REGISTER_SNE BIT2 + +typedef struct { + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + UINT32 ShadowAddress; + UINT32 ShadowedSize; + UINT8 DiskStart; + UINT8 DiskEnd; +} ROM_INSTANCE_ENTRY; + +// +// Values for RealModeGdt +// +#if defined (MDE_CPU_IA32) + +#define NUM_REAL_GDT_ENTRIES 3 +#define CONVENTIONAL_MEMORY_TOP 0xA0000 // 640 KB +#define INITIAL_VALUE_BELOW_1K 0x0 + +#elif defined (MDE_CPU_X64) + +#define NUM_REAL_GDT_ENTRIES 8 +#define CONVENTIONAL_MEMORY_TOP 0xA0000 // 640 KB +#define INITIAL_VALUE_BELOW_1K 0x0 + +#elif defined (MDE_CPU_IPF) + +#define NUM_REAL_GDT_ENTRIES 3 +#define CONVENTIONAL_MEMORY_TOP 0x80000 // 512 KB +#define INITIAL_VALUE_BELOW_1K 0xff + +#endif + +#pragma pack(1) + +// +// Define what a processor GDT looks like +// +typedef struct { + UINT32 LimitLo : 16; + UINT32 BaseLo : 16; + UINT32 BaseMid : 8; + UINT32 Type : 4; + UINT32 System : 1; + UINT32 Dpl : 2; + UINT32 Present : 1; + UINT32 LimitHi : 4; + UINT32 Software : 1; + UINT32 Reserved : 1; + UINT32 DefaultSize : 1; + UINT32 Granularity : 1; + UINT32 BaseHi : 8; +} GDT32; + +typedef struct { + UINT16 LimitLow; + UINT16 BaseLow; + UINT8 BaseMid; + UINT8 Attribute; + UINT8 LimitHi; + UINT8 BaseHi; +} GDT64; + +// +// Define what a processor descriptor looks like +// This data structure must be kept in sync with ASM STRUCT in Thunk.inc +// +typedef struct { + UINT16 Limit; + UINT64 Base; +} DESCRIPTOR64; + +typedef struct { + UINT16 Limit; + UINT32 Base; +} DESCRIPTOR32; + +// +// Low stub lay out +// +#define LOW_STACK_SIZE (8 * 1024) // 8k? +#define EFI_MAX_E820_ENTRY 100 +#define FIRST_INSTANCE 1 +#define NOT_FIRST_INSTANCE 0 + +#if defined (MDE_CPU_IA32) +typedef struct { + // + // Space for the code + // The address of Code is also the beginning of the relocated Thunk code + // + CHAR8 Code[4096]; // ? + // + // The address of the Reverse Thunk code + // Note that this member CONTAINS the address of the relocated reverse thunk + // code unlike the member variable 'Code', which IS the address of the Thunk + // code. + // + UINT32 LowReverseThunkStart; + + // + // Data for the code (cs releative) + // + DESCRIPTOR32 GdtDesc; // Protected mode GDT + DESCRIPTOR32 IdtDesc; // Protected mode IDT + UINT32 FlatSs; + UINT32 FlatEsp; + + UINT32 LowCodeSelector; // Low code selector in GDT + UINT32 LowDataSelector; // Low data selector in GDT + UINT32 LowStack; + DESCRIPTOR32 RealModeIdtDesc; + + // + // real-mode GDT (temporary GDT with two real mode segment descriptors) + // + GDT32 RealModeGdt[NUM_REAL_GDT_ENTRIES]; + DESCRIPTOR32 RealModeGdtDesc; + + // + // Members specifically for the reverse thunk + // The RevReal* members are used to store the current state of real mode + // before performing the reverse thunk. The RevFlat* members must be set + // before calling the reverse thunk assembly code. + // + UINT16 RevRealDs; + UINT16 RevRealSs; + UINT32 RevRealEsp; + DESCRIPTOR32 RevRealIdtDesc; + UINT16 RevFlatDataSelector; // Flat data selector in GDT + UINT32 RevFlatStack; + + // + // A low memory stack + // + CHAR8 Stack[LOW_STACK_SIZE]; + + // + // Stack for flat mode after reverse thunk + // @bug - This may no longer be necessary if the reverse thunk interface + // is changed to have the flat stack in a different location. + // + CHAR8 RevThunkStack[LOW_STACK_SIZE]; + + // + // Legacy16 Init memory map info + // + EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable; + + EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable; + + CHAR8 InterruptRedirectionCode[32]; + EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; + EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; + BBS_TABLE BbsTable[MAX_BBS_ENTRIES]; +} LOW_MEMORY_THUNK; + +#elif defined (MDE_CPU_X64) + +typedef struct { + // + // Space for the code + // The address of Code is also the beginning of the relocated Thunk code + // + CHAR8 Code[4096]; // ? + + // + // Data for the code (cs releative) + // + DESCRIPTOR64 X64GdtDesc; // Protected mode GDT + DESCRIPTOR64 X64IdtDesc; // Protected mode IDT + UINTN X64Ss; + UINTN X64Esp; + + UINTN RealStack; + DESCRIPTOR32 RealModeIdtDesc; + DESCRIPTOR32 RealModeGdtDesc; + + // + // real-mode GDT (temporary GDT with two real mode segment descriptors) + // + GDT64 RealModeGdt[NUM_REAL_GDT_ENTRIES]; + UINT64 PageMapLevel4; + + // + // A low memory stack + // + CHAR8 Stack[LOW_STACK_SIZE]; + + // + // Legacy16 Init memory map info + // + EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable; + + EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable; + + CHAR8 InterruptRedirectionCode[32]; + EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; + EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; + BBS_TABLE BbsTable[MAX_BBS_ENTRIES]; +} LOW_MEMORY_THUNK; + +#elif defined (MDE_CPU_IPF) + +typedef struct { + // + // Space for the code + // The address of Code is also the beginning of the relocated Thunk code + // + CHAR8 Code[4096]; // ? + // + // The address of the Reverse Thunk code + // Note that this member CONTAINS the address of the relocated reverse thunk + // code unlike the member variable 'Code', which IS the address of the Thunk + // code. + // + UINT32 LowReverseThunkStart; + + // + // Data for the code (cs releative) + // + DESCRIPTOR32 GdtDesc; // Protected mode GDT + DESCRIPTOR32 IdtDesc; // Protected mode IDT + UINT32 FlatSs; + UINT32 FlatEsp; + + UINT32 LowCodeSelector; // Low code selector in GDT + UINT32 LowDataSelector; // Low data selector in GDT + UINT32 LowStack; + DESCRIPTOR32 RealModeIdtDesc; + + // + // real-mode GDT (temporary GDT with two real mode segment descriptors) + // + GDT32 RealModeGdt[NUM_REAL_GDT_ENTRIES]; + DESCRIPTOR32 RealModeGdtDesc; + + // + // Members specifically for the reverse thunk + // The RevReal* members are used to store the current state of real mode + // before performing the reverse thunk. The RevFlat* members must be set + // before calling the reverse thunk assembly code. + // + UINT16 RevRealDs; + UINT16 RevRealSs; + UINT32 RevRealEsp; + DESCRIPTOR32 RevRealIdtDesc; + UINT16 RevFlatDataSelector; // Flat data selector in GDT + UINT32 RevFlatStack; + + // + // A low memory stack + // + CHAR8 Stack[LOW_STACK_SIZE]; + + // + // Stack for flat mode after reverse thunk + // @bug - This may no longer be necessary if the reverse thunk interface + // is changed to have the flat stack in a different location. + // + CHAR8 RevThunkStack[LOW_STACK_SIZE]; + + // + // Legacy16 Init memory map info + // + EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable; + + EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable; + + CHAR8 InterruptRedirectionCode[32]; + EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; + EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; + BBS_TABLE BbsTable[MAX_BBS_ENTRIES]; +} LOW_MEMORY_THUNK; + +#endif + +// +// PnP Expansion Header +// +typedef struct { + UINT32 PnpSignature; + UINT8 Revision; + UINT8 Length; + UINT16 NextHeader; + UINT8 Reserved1; + UINT8 Checksum; + UINT32 DeviceId; + UINT16 MfgPointer; + UINT16 ProductNamePointer; + UINT8 Class; + UINT8 SubClass; + UINT8 Interface; + UINT8 DeviceIndicators; + UINT16 Bcv; + UINT16 DisconnectVector; + UINT16 Bev; + UINT16 Reserved2; + UINT16 StaticResourceVector; +} LEGACY_PNP_EXPANSION_HEADER; + +typedef struct { + UINT8 PciSegment; + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; + UINT16 Vid; + UINT16 Did; + UINT16 SysSid; + UINT16 SVid; + UINT8 Class; + UINT8 SubClass; + UINT8 Interface; + UINT8 Reserved; + UINTN RomStart; + UINTN ManufacturerString; + UINTN ProductNameString; +} LEGACY_ROM_AND_BBS_TABLE; + +// +// Structure how EFI has mapped a devices HDD drive numbers. +// Boot to EFI aware OS or shell requires this mapping when +// 16-bit CSM assigns drive numbers. +// This mapping is ignored booting to a legacy OS. +// +typedef struct { + UINT8 PciSegment; + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; + UINT8 StartDriveNumber; + UINT8 EndDriveNumber; +} LEGACY_EFI_HDD_TABLE; + +// +// This data is passed to Leacy16Boot +// +typedef enum { + EfiAcpiAddressRangeMemory = 1, + EfiAcpiAddressRangeReserved = 2, + EfiAcpiAddressRangeACPI = 3, + EfiAcpiAddressRangeNVS = 4, + EfiAddressRangePersistentMemory = 7 +} EFI_ACPI_MEMORY_TYPE; + +typedef struct { + UINT64 BaseAddr; + UINT64 Length; + EFI_ACPI_MEMORY_TYPE Type; +} EFI_E820_ENTRY64; + +typedef struct { + UINT32 BassAddrLow; + UINT32 BaseAddrHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + EFI_ACPI_MEMORY_TYPE Type; +} EFI_E820_ENTRY; + +#pragma pack() + +extern BBS_TABLE *mBbsTable; + +extern EFI_GENERIC_MEMORY_TEST_PROTOCOL *gGenMemoryTest; + +#define PORT_70 0x70 +#define PORT_71 0x71 + +#define CMOS_0A 0x0a ///< Status register A +#define CMOS_0D 0x0d ///< Status register D +#define CMOS_0E 0x0e ///< Diagnostic Status +#define CMOS_0F 0x0f ///< Shutdown status +#define CMOS_10 0x10 ///< Floppy type +#define CMOS_12 0x12 ///< IDE type +#define CMOS_14 0x14 ///< Same as BDA 40:10 +#define CMOS_15 0x15 ///< Low byte of base memory in 1k increments +#define CMOS_16 0x16 ///< High byte of base memory in 1k increments +#define CMOS_17 0x17 ///< Low byte of 1MB+ memory in 1k increments - max 15 MB +#define CMOS_18 0x18 ///< High byte of 1MB+ memory in 1k increments - max 15 MB +#define CMOS_19 0x19 ///< C: extended drive type +#define CMOS_1A 0x1a ///< D: extended drive type +#define CMOS_2E 0x2e ///< Most significient byte of standard checksum +#define CMOS_2F 0x2f ///< Least significient byte of standard checksum +#define CMOS_30 0x30 ///< CMOS 0x17 +#define CMOS_31 0x31 ///< CMOS 0x18 +#define CMOS_32 0x32 ///< Century byte + +// +// 8254 Timer registers +// +#define TIMER0_COUNT_PORT 0x40 +#define TIMER1_COUNT_PORT 0x41 +#define TIMER2_COUNT_PORT 0x42 +#define TIMER_CONTROL_PORT 0x43 + +// +// Timer 0, Read/Write LSB then MSB, Square wave output, binary count use. +// +#define TIMER0_CONTROL_WORD 0x36 + +#define LEGACY_BIOS_INSTANCE_SIGNATURE SIGNATURE_32 ('L', 'B', 'I', 'T') +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_LEGACY_BIOS_PROTOCOL LegacyBios; + + EFI_HANDLE ImageHandle; + + // + // CPU Architectural Protocol + // + EFI_CPU_ARCH_PROTOCOL *Cpu; + + // + // Timer Architectural Protocol + // + EFI_TIMER_ARCH_PROTOCOL *Timer; + BOOLEAN TimerUses8254; + + // + // Protocol to Lock and Unlock 0xc0000 - 0xfffff + // + EFI_LEGACY_REGION2_PROTOCOL *LegacyRegion; + + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + + // + // Interrupt control for thunk and PCI IRQ + // + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + + // + // PCI Interrupt PIRQ control + // + EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt; + + // + // Generic Memory Test + // + EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenericMemoryTest; + + // + // TRUE if PCI Interupt Line registers have been programmed. + // + BOOLEAN PciInterruptLine; + + // + // Code space below 1MB needed by thunker to transition to real mode. + // Contains stack and real mode code fragments + // + LOW_MEMORY_THUNK *IntThunk; + + // + // Starting shadow address of the Legacy BIOS + // + UINT32 BiosStart; + UINT32 LegacyBiosImageSize; + + // + // Start of variables used by CsmItp.mac ITP macro file and/os LegacyBios + // + UINT8 Dump[4]; + + // + // $EFI Legacy16 code entry info in memory < 1 MB; + // + EFI_COMPATIBILITY16_TABLE *Legacy16Table; + VOID *Legacy16InitPtr; + VOID *Legacy16BootPtr; + VOID *InternalIrqRoutingTable; + UINT32 NumberIrqRoutingEntries; + VOID *BbsTablePtr; + VOID *HddTablePtr; + UINT32 NumberHddControllers; + + // + // Cached copy of Legacy16 entry point + // + UINT16 Legacy16CallSegment; + UINT16 Legacy16CallOffset; + + // + // Returned from $EFI and passed in to OPROMS + // + UINT16 PnPInstallationCheckSegment; + UINT16 PnPInstallationCheckOffset; + + // + // E820 table + // + EFI_E820_ENTRY E820Table[EFI_MAX_E820_ENTRY]; + UINT32 NumberE820Entries; + + // + // True if legacy VGA INT 10h handler installed + // + BOOLEAN VgaInstalled; + + // + // Number of IDE drives + // + UINT8 IdeDriveCount; + + // + // Current Free Option ROM space. An option ROM must NOT go past + // BiosStart. + // + UINT32 OptionRom; + + // + // Save Legacy16 unexpected interrupt vector. Reprogram INT 68-6F from + // EFI values to legacy value just before boot. + // + UINT32 BiosUnexpectedInt; + UINT32 ThunkSavedInt[8]; + UINT16 ThunkSeg; + LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable; + UINT16 LegacyEfiHddTableIndex; + UINT8 DiskEnd; + UINT8 Disk4075; + UINT16 TraceIndex; + UINT16 Trace[0x200]; + + // + // Indicate that whether GenericLegacyBoot is entered or not + // + BOOLEAN LegacyBootEntered; + + // + // CSM16 PCI Interface Version + // + UINT16 Csm16PciInterfaceVersion; + +} LEGACY_BIOS_INSTANCE; + + +#pragma pack(1) + +/* + 40:00-01 Com1 + 40:02-03 Com2 + 40:04-05 Com3 + 40:06-07 Com4 + 40:08-09 Lpt1 + 40:0A-0B Lpt2 + 40:0C-0D Lpt3 + 40:0E-0E Ebda segment + 40:10-11 MachineConfig + 40:12 Bda12 - skip + 40:13-14 MemSize below 1MB + 40:15-16 Bda15_16 - skip + 40:17 Keyboard Shift status + 40:18-19 Bda18_19 - skip + 40:1A-1B Key buffer head + 40:1C-1D Key buffer tail + 40:1E-3D Bda1E_3D- key buffer -skip + 40:3E-3F FloppyData 3E = Calibration status 3F = Motor status + 40:40 FloppyTimeout + 40:41-74 Bda41_74 - skip + 40:75 Number of HDD drives + 40:76-77 Bda76_77 - skip + 40:78-79 78 = Lpt1 timeout, 79 = Lpt2 timeout + 40:7A-7B 7A = Lpt3 timeout, 7B = Lpt4 timeout + 40:7C-7D 7C = Com1 timeout, 7D = Com2 timeout + 40:7E-7F 7E = Com3 timeout, 7F = Com4 timeout + 40:80-81 Pointer to start of key buffer + 40:82-83 Pointer to end of key buffer + 40:84-87 Bda84_87 - skip + 40:88 HDD Data Xmit rate + 40:89-8f skip + 40:90 Floppy data rate + 40:91-95 skip + 40:96 Keyboard Status + 40:97 LED Status + 40:98-101 skip +*/ +typedef struct { + UINT16 Com1; + UINT16 Com2; + UINT16 Com3; + UINT16 Com4; + UINT16 Lpt1; + UINT16 Lpt2; + UINT16 Lpt3; + UINT16 Ebda; + UINT16 MachineConfig; + UINT8 Bda12; + UINT16 MemSize; + UINT8 Bda15_16[0x02]; + UINT8 ShiftStatus; + UINT8 Bda18_19[0x02]; + UINT16 KeyHead; + UINT16 KeyTail; + UINT16 Bda1E_3D[0x10]; + UINT16 FloppyData; + UINT8 FloppyTimeout; + UINT8 Bda41_74[0x34]; + UINT8 NumberOfDrives; + UINT8 Bda76_77[0x02]; + UINT16 Lpt1_2Timeout; + UINT16 Lpt3_4Timeout; + UINT16 Com1_2Timeout; + UINT16 Com3_4Timeout; + UINT16 KeyStart; + UINT16 KeyEnd; + UINT8 Bda84_87[0x4]; + UINT8 DataXmit; + UINT8 Bda89_8F[0x07]; + UINT8 FloppyXRate; + UINT8 Bda91_95[0x05]; + UINT8 KeyboardStatus; + UINT8 LedStatus; +} BDA_STRUC; +#pragma pack() + +#define LEGACY_BIOS_INSTANCE_FROM_THIS(this) CR (this, LEGACY_BIOS_INSTANCE, LegacyBios, LEGACY_BIOS_INSTANCE_SIGNATURE) + +/** + Thunk to 16-bit real mode and execute a software interrupt with a vector + of BiosInt. Regs will contain the 16-bit register context on entry and + exit. + + @param This Protocol instance pointer. + @param BiosInt Processor interrupt vector to invoke + @param Regs Register contexted passed into (and returned) from thunk to + 16-bit mode + + @retval FALSE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN EFI_IA32_REGISTER_SET *Regs + ); + + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and returned) from + thunk to 16-bit mode + @param Stack Caller allocated stack used to pass arguments + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS errors in + the target code. See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosFarCall86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ); + + +/** + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will + be loaded + @param RomImage Return the legacy PCI ROM for this device + @param RomSize Size of ROM Image + @param Flags Indicates if ROM found and if PC-AT. + + @retval EFI_SUCCESS Legacy Option ROM availible for this device + @retval EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosCheckPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *Flags + ); + + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + Note: BBS compliant drives ARE NOT available until this call by + either shell or EFI. + + @param This Protocol instance pointer. + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Drive numbers assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosPrepareToBootEfi ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ); + + +/** + To boot from an unconventional device like parties and/or execute + HDD diagnostics. + + @param This Protocol instance pointer. + @param Attributes How to interpret the other input parameters + @param BbsEntry The 0-based index into the BbsTable for the parent + device. + @param BeerData Pointer to the 128 bytes of ram BEER data. + @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. + The caller must provide a pointer to the specific + Service Area and not the start all Service Areas. + EFI_INVALID_PARAMETER if error. Does NOT return if no error. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosBootUnconventionalDevice ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UDC_ATTRIBUTES Attributes, + IN UINTN BbsEntry, + IN VOID *BeerData, + IN VOID *ServiceAreaData + ); + + +/** + Load a legacy PC-AT OPROM on the PciHandle device. Return information + about how many disks were added by the OPROM and the shadow address and + size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will + be loaded. This value is NULL if RomImage is + non-NULL. This is the normal case. + @param RomImage A PCI PC-AT ROM image. This argument is non-NULL + if there is no hardware associated with the ROM + and thus no PciHandle, otherwise is must be NULL. + Example is PXE base code. + @param Flags Indicates if ROM found and if PC-AT. + @param DiskStart Disk number of first device hooked by the ROM. If + DiskStart is the same as DiskEnd no disked were + hooked. + @param DiskEnd Disk number of the last device hooked by the ROM. + @param RomShadowAddress Shadow address of PC-AT ROM + @param RomShadowedSize Size of RomShadowAddress in bytes + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_INVALID_PARAMETER PciHandle not found + @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no onboard + ROM + +**/ +EFI_STATUS +EFIAPI +LegacyBiosInstallPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL * This, + IN EFI_HANDLE PciHandle, + IN VOID **RomImage, + OUT UINTN *Flags, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINT32 *RomShadowedSize OPTIONAL + ); + + +/** + Fill in the standard BDA for Keyboard LEDs + + @param This Protocol instance pointer. + @param Leds Current LED status + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosUpdateKeyboardLedStatus ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 Leds + ); + + +/** + Get all BBS info + + @param This Protocol instance pointer. + @param HddCount Number of HDD_INFO structures + @param HddInfo Onboard IDE controller information + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Tables returned + @retval EFI_NOT_FOUND resource not found + @retval EFI_DEVICE_ERROR can not get BBS table + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetBbsInfo ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *HddCount, + OUT HDD_INFO **HddInfo, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ); + + +/** + Shadow all legacy16 OPROMs that haven't been shadowed. + Warning: Use this with caution. This routine disconnects all EFI + drivers. If used externally then caller must re-connect EFI + drivers. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS OPROMs shadowed + +**/ +EFI_STATUS +EFIAPI +LegacyBiosShadowAllLegacyOproms ( + IN EFI_LEGACY_BIOS_PROTOCOL *This + ); + + +/** + Attempt to legacy boot the BootOption. If the EFI contexted has been + compromised this function will not return. + + @param This Protocol instance pointer. + @param BbsDevicePath EFI Device Path from BootXXXX variable. + @param LoadOptionsSize Size of LoadOption in size. + @param LoadOptions LoadOption from BootXXXX variable + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +EFIAPI +LegacyBiosLegacyBoot ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions + ); + + +/** + Allocate memory < 1 MB and copy the thunker code into low memory. Se up + all the descriptors. + + @param Private Private context for Legacy BIOS + + @retval EFI_SUCCESS Should only pass. + +**/ +EFI_STATUS +LegacyBiosInitializeThunk ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Fill in the standard BDA and EBDA stuff before Legacy16 load + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosInitBda ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Collect IDE Inquiry data from the IDE disks + + @param Private Legacy BIOS Instance data + @param HddInfo Hdd Information + @param Flag Reconnect IdeController or not + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildIdeData ( + IN LEGACY_BIOS_INSTANCE *Private, + IN HDD_INFO **HddInfo, + IN UINT16 Flag + ); + + +/** + Enable ide controller. This gets disabled when LegacyBoot.c is about + to run the Option ROMs. + + @param Private Legacy BIOS Instance data + + +**/ +VOID +EnableIdeController ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + If the IDE channel is in compatibility (legacy) mode, remove all + PCI I/O BAR addresses from the controller. + + @param IdeController The handle of target IDE controller + + +**/ +VOID +InitLegacyIdeController ( + IN EFI_HANDLE IdeController + ); + + +/** + Program the interrupt routing register in all the PCI devices. On a PC AT system + this register contains the 8259 IRQ vector that matches it's PCI interrupt. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Succeed. + @retval EFI_ALREADY_STARTED All PCI devices have been processed. + +**/ +EFI_STATUS +PciProgramAllInterruptLineRegisters ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Collect EFI Info about legacy devices. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildSioData ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol + to chose the order. Skip any devices that have already have legacy + BIOS run. + + @param Private Protocol instance pointer. + + @retval EFI_SUCCESS Succeed. + @retval EFI_UNSUPPORTED Cannot get VGA device handle. + +**/ +EFI_STATUS +PciShadowRoms ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Fill in the standard BDA and EBDA stuff prior to legacy Boot + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosCompleteBdaBeforeBoot ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Fill in the standard CMOS stuff before Legacy16 load + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosInitCmos ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Fill in the standard CMOS stuff prior to legacy Boot + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosCompleteStandardCmosBeforeBoot ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Contains the code that is copied into low memory (below 640K). + This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. + This template must be copied into low memory, and the IDT entries + 0x68-0x6F must be point to the low memory copy of this code. Each + entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily + computed. + +**/ +VOID +InterruptRedirectionTemplate ( + VOID + ); + + +/** + Build the E820 table. + + @param Private Legacy BIOS Instance data + @param Size Size of E820 Table + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildE820 ( + IN LEGACY_BIOS_INSTANCE *Private, + OUT UINTN *Size + ); + +/** + This function is to put all AP in halt state. + + @param Private Legacy BIOS Instance data + +**/ +VOID +ShutdownAPs ( + IN LEGACY_BIOS_INSTANCE *Private + ); + +/** + Worker function for LegacyBiosGetFlatDescs, retrieving content of + specific registers. + + @param IntThunk Pointer to IntThunk of Legacy BIOS context. + +**/ +VOID +GetRegisters ( + LOW_MEMORY_THUNK *IntThunk + ); + +/** + Routine for calling real thunk code. + + @param RealCode The address of thunk code. + @param BiosInt The Bios interrupt vector number. + @param CallAddress The address of 16-bit mode call. + + @return Status returned by real thunk code + +**/ +UINTN +CallRealThunkCode ( + UINT8 *RealCode, + UINT8 BiosInt, + UINT32 CallAddress + ); + +/** + Routine for generating soft interrupt. + + @param Vector The interrupt vector number. + +**/ +VOID +GenerateSoftInit ( + UINT8 Vector + ); + +/** + Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode + memory. + + @param AllocateType Allocated Legacy Memory Type + @param StartPageAddress Start address of range + @param Pages Number of pages to allocate + @param Result Result of allocation + + @retval EFI_SUCCESS Legacy16 code loaded + @retval Other No protocol installed, unload driver. + +**/ +EFI_STATUS +AllocateLegacyMemory ( + IN EFI_ALLOCATE_TYPE AllocateType, + IN EFI_PHYSICAL_ADDRESS StartPageAddress, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Result + ); + +/** + Get a region from the LegacyBios for Tiano usage. Can only be invoked once. + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of required region + @param Region Region to use. 00 = Either 0xE0000 or 0xF0000 + block Bit0 = 1 0xF0000 block Bit1 = 1 0xE0000 + block + @param Alignment Address alignment. Bit mapped. First non-zero + bit from right is alignment. + @param LegacyMemoryAddress Region Assigned + + @retval EFI_SUCCESS Region assigned + @retval EFI_ACCESS_DENIED Procedure previously invoked + @retval Other Region not assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN UINTN Region, + IN UINTN Alignment, + OUT VOID **LegacyMemoryAddress + ); + +/** + Get a region from the LegacyBios for Tiano usage. Can only be invoked once. + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of data to copy + @param LegacyMemoryAddress Legacy Region destination address Note: must + be in region assigned by + LegacyBiosGetLegacyRegion + @param LegacyMemorySourceAddress Source of data + + @retval EFI_SUCCESS Region assigned + @retval EFI_ACCESS_DENIED Destination outside assigned region + +**/ +EFI_STATUS +EFIAPI +LegacyBiosCopyLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN VOID *LegacyMemoryAddress, + IN VOID *LegacyMemorySourceAddress + ); + +/** + Find Legacy16 BIOS image in the FLASH device and shadow it into memory. Find + the $EFI table in the shadow area. Thunk into the Legacy16 code after it had + been shadowed. + + @param Private Legacy BIOS context data + + @retval EFI_SUCCESS Legacy16 code loaded + @retval Other No protocol installed, unload driver. + +**/ +EFI_STATUS +ShadowAndStartLegacy16 ( + IN LEGACY_BIOS_INSTANCE *Private + ); + +/** + Checks the state of the floppy and if media is inserted. + + This routine checks the state of the floppy and if media is inserted. + There are 3 cases: + No floppy present - Set BBS entry to ignore + Floppy present & no media - Set BBS entry to lowest priority. We cannot + set it to ignore since 16-bit CSM will + indicate no floppy and thus drive A: is + unusable. CSM-16 will not try floppy since + lowest priority and thus not incur boot + time penality. + Floppy present & media - Set BBS entry to some priority. + + @return State of floppy media + +**/ +UINT8 +HasMediaInFloppy ( + VOID + ); + +/** + Identify drive data must be updated to actual parameters before boot. + This requires updating the checksum, if it exists. + + @param IdentifyDriveData ATA Identify Data + @param Checksum checksum of the ATA Identify Data + + @retval EFI_SUCCESS checksum calculated + @retval EFI_SECURITY_VIOLATION IdentifyData invalid + +**/ +EFI_STATUS +CalculateIdentifyDriveChecksum ( + IN UINT8 *IdentifyDriveData, + OUT UINT8 *Checksum + ); + +/** + Identify drive data must be updated to actual parameters before boot. + + @param IdentifyDriveData ATA Identify Data + +**/ +VOID +UpdateIdentifyDriveData ( + IN UINT8 *IdentifyDriveData + ); + +/** + Complete build of BBS TABLE. + + @param Private Legacy BIOS Instance data + @param BbsTable BBS Table passed to 16-bit code + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +LegacyBiosBuildBbs ( + IN LEGACY_BIOS_INSTANCE *Private, + IN BBS_TABLE *BbsTable + ); + +/** + Read CMOS register through index/data port. + + @param[in] Index The index of the CMOS register to read. + + @return The data value from the CMOS register specified by Index. + +**/ +UINT8 +LegacyReadStandardCmos ( + IN UINT8 Index + ); + +/** + Write CMOS register through index/data port. + + @param[in] Index The index of the CMOS register to write. + @param[in] Value The value of CMOS register to write. + + @return The value written to the CMOS register specified by Index. + +**/ +UINT8 +LegacyWriteStandardCmos ( + IN UINT8 Index, + IN UINT8 Value + ); + +/** + Calculate the new standard CMOS checksum and write it. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Calculate 16-bit checksum successfully + +**/ +EFI_STATUS +LegacyCalculateWriteStandardCmosChecksum ( + VOID + ); + +/** + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param[in] This Protocol instance pointer. + @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded + @param[out] RomImage Return the legacy PCI ROM for this device + @param[out] RomSize Size of ROM Image + @param[out] RuntimeImageLength Runtime size of ROM Image + @param[out] Flags Indicates if ROM found and if PC-AT. + @param[out] OpromRevision Revision of the PCI Rom + @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header + + @return EFI_SUCCESS Legacy Option ROM availible for this device + @return EFI_ALREADY_STARTED This device is already managed by its Oprom + @return EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ +EFI_STATUS +LegacyBiosCheckPciRomEx ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *RuntimeImageLength, OPTIONAL + OUT UINTN *Flags, OPTIONAL + OUT UINT8 *OpromRevision, OPTIONAL + OUT VOID **ConfigUtilityCodeHeader OPTIONAL + ); + +/** + Relocate this image under 4G memory for IPF. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Image successfully relocated. + @retval EFI_ABORTED Failed to relocate image. + +**/ +EFI_STATUS +RelocateImageUnder4GIfNeeded ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and returned) from thunk to + 16-bit mode + @param Stack Caller allocated stack used to pass arguments + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +InternalLegacyBiosFarCall ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ); + +/** + Load a legacy PC-AT OpROM for VGA controller. + + @param Private Driver private data. + + @retval EFI_SUCCESS Legacy ROM successfully installed for this device. + @retval EFI_DEVICE_ERROR No VGA device handle found, or native EFI video + driver cannot be successfully disconnected, or VGA + thunk driver cannot be successfully connected. + +**/ +EFI_STATUS +LegacyBiosInstallVgaRom ( + IN LEGACY_BIOS_INSTANCE *Private + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c new file mode 100644 index 0000000000..52bcae2d13 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c @@ -0,0 +1,2165 @@ +/** @file + +Copyright (c) 2006 - 2015, Intel 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 "LegacyBiosInterface.h" +#include + +#define BOOT_LEGACY_OS 0 +#define BOOT_EFI_OS 1 +#define BOOT_UNCONVENTIONAL_DEVICE 2 + +UINT32 mLoadOptionsSize = 0; +UINTN mBootMode = BOOT_LEGACY_OS; +VOID *mLoadOptions = NULL; +BBS_BBS_DEVICE_PATH *mBbsDevicePathPtr = NULL; +BBS_BBS_DEVICE_PATH mBbsDevicePathNode; +UDC_ATTRIBUTES mAttributes = { 0, 0, 0, 0 }; +UINTN mBbsEntry = 0; +VOID *mBeerData = NULL; +VOID *mServiceAreaData = NULL; +UINT64 mLowWater = 0xffffffffffffffffULL; + +extern BBS_TABLE *mBbsTable; + +extern VOID *mRuntimeSmbiosEntryPoint; +extern EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint; +extern EFI_PHYSICAL_ADDRESS mStructureTableAddress; + +/** + Print the BBS Table. + + @param BbsTable The BBS table. + + +**/ +VOID +PrintBbsTable ( + IN BBS_TABLE *BbsTable + ) +{ + UINT16 Index; + UINT16 SubIndex; + CHAR8 *String; + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs mfgs:mfgo dess:deso\n")); + DEBUG ((EFI_D_INFO, "=================================================================\n")); + for (Index = 0; Index < MAX_BBS_ENTRIES; Index++) { + // + // Filter + // + if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) { + continue; + } + + DEBUG (( + EFI_D_INFO, + " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x", + (UINTN) Index, + (UINTN) BbsTable[Index].BootPriority, + (UINTN) BbsTable[Index].Bus, + (UINTN) BbsTable[Index].Device, + (UINTN) BbsTable[Index].Function, + (UINTN) BbsTable[Index].Class, + (UINTN) BbsTable[Index].SubClass, + (UINTN) BbsTable[Index].DeviceType, + (UINTN) * (UINT16 *) &BbsTable[Index].StatusFlags + )); + DEBUG (( + EFI_D_INFO, + " %04x:%04x %04x:%04x %04x:%04x", + (UINTN) BbsTable[Index].BootHandlerSegment, + (UINTN) BbsTable[Index].BootHandlerOffset, + (UINTN) BbsTable[Index].MfgStringSegment, + (UINTN) BbsTable[Index].MfgStringOffset, + (UINTN) BbsTable[Index].DescStringSegment, + (UINTN) BbsTable[Index].DescStringOffset + )); + + // + // Print DescString + // + String = (CHAR8 *)(UINTN)((BbsTable[Index].DescStringSegment << 4) + BbsTable[Index].DescStringOffset); + if (String != NULL) { + DEBUG ((EFI_D_INFO," (")); + for (SubIndex = 0; String[SubIndex] != 0; SubIndex++) { + DEBUG ((EFI_D_INFO, "%c", String[SubIndex])); + } + DEBUG ((EFI_D_INFO,")")); + } + DEBUG ((EFI_D_INFO,"\n")); + } + + DEBUG ((EFI_D_INFO, "\n")); + + return ; +} + +/** + Print the BBS Table. + + @param HddInfo The HddInfo table. + + +**/ +VOID +PrintHddInfo ( + IN HDD_INFO *HddInfo + ) +{ + UINTN Index; + + DEBUG ((EFI_D_INFO, "\n")); + for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) { + DEBUG ((EFI_D_INFO, "Index - %04x\n", Index)); + DEBUG ((EFI_D_INFO, " Status - %04x\n", (UINTN)HddInfo[Index].Status)); + DEBUG ((EFI_D_INFO, " B/D/F - %02x/%02x/%02x\n", (UINTN)HddInfo[Index].Bus, (UINTN)HddInfo[Index].Device, (UINTN)HddInfo[Index].Function)); + DEBUG ((EFI_D_INFO, " Command - %04x\n", HddInfo[Index].CommandBaseAddress)); + DEBUG ((EFI_D_INFO, " Control - %04x\n", HddInfo[Index].ControlBaseAddress)); + DEBUG ((EFI_D_INFO, " BusMaster - %04x\n", HddInfo[Index].BusMasterAddress)); + DEBUG ((EFI_D_INFO, " HddIrq - %02x\n", HddInfo[Index].HddIrq)); + DEBUG ((EFI_D_INFO, " IdentifyDrive[0].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[0].Raw[0])); + DEBUG ((EFI_D_INFO, " IdentifyDrive[1].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[1].Raw[0])); + } + + DEBUG ((EFI_D_INFO, "\n")); + + return ; +} + +/** + Print the PCI Interrupt Line and Interrupt Pin registers. +**/ +VOID +PrintPciInterruptRegister ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE *Handles; + UINTN HandleNum; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Interrupt[2]; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleNum, + &Handles + ); + + Bus = 0; + Device = 0; + Function = 0; + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, " bb/dd/ff interrupt line interrupt pin\n")); + DEBUG ((EFI_D_INFO, "======================================\n")); + for (Index = 0; Index < HandleNum; Index++) { + Status = gBS->HandleProtocol (Handles[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo); + if (!EFI_ERROR (Status)) { + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_INT_LINE_OFFSET, + 2, + Interrupt + ); + } + if (!EFI_ERROR (Status)) { + Status = PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + } + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, " %02x/%02x/%02x 0x%02x 0x%02x\n", + Bus, Device, Function, Interrupt[0], Interrupt[1])); + } + } + DEBUG ((EFI_D_INFO, "\n")); + + if (Handles != NULL) { + FreePool (Handles); + } +} + +/** + Identify drive data must be updated to actual parameters before boot. + + @param IdentifyDriveData ATA Identify Data + +**/ +VOID +UpdateIdentifyDriveData ( + IN UINT8 *IdentifyDriveData + ); + +/** + Update SIO data. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +UpdateSioData ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN Index1; + UINT8 LegacyInterrupts[16]; + EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable; + UINTN RoutingTableEntries; + EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY *IrqPriorityTable; + UINTN NumberPriorityEntries; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + UINT8 HddIrq; + UINT16 LegacyInt; + UINT16 LegMask; + UINT32 Register; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_ISA_IO_PROTOCOL *IsaIo; + + LegacyInt = 0; + HandleBuffer = NULL; + + EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; + LegacyBiosBuildSioData (Private); + SetMem (LegacyInterrupts, sizeof (LegacyInterrupts), 0); + + // + // Create list of legacy interrupts. + // + for (Index = 0; Index < 4; Index++) { + LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Serial[Index].Irq; + } + + for (Index = 4; Index < 7; Index++) { + LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Parallel[Index - 4].Irq; + } + + LegacyInterrupts[7] = EfiToLegacy16BootTable->SioData.Floppy.Irq; + + // + // Get Legacy Hdd IRQs. If native mode treat as PCI + // + for (Index = 0; Index < 2; Index++) { + HddIrq = EfiToLegacy16BootTable->HddInfo[Index].HddIrq; + if ((HddIrq != 0) && ((HddIrq == 15) || (HddIrq == 14))) { + LegacyInterrupts[Index + 8] = HddIrq; + } + } + + Private->LegacyBiosPlatform->GetRoutingTable ( + Private->LegacyBiosPlatform, + (VOID *) &RoutingTable, + &RoutingTableEntries, + NULL, + NULL, + (VOID **) &IrqPriorityTable, + &NumberPriorityEntries + ); + // + // Remove legacy interrupts from the list of PCI interrupts available. + // + for (Index = 0; Index <= 0x0b; Index++) { + for (Index1 = 0; Index1 <= NumberPriorityEntries; Index1++) { + if (LegacyInterrupts[Index] != 0) { + LegacyInt = (UINT16) (LegacyInt | (1 << LegacyInterrupts[Index])); + if (LegacyInterrupts[Index] == IrqPriorityTable[Index1].Irq) { + IrqPriorityTable[Index1].Used = LEGACY_USED; + } + } + } + } + + Private->Legacy8259->GetMask ( + Private->Legacy8259, + &LegMask, + NULL, + NULL, + NULL + ); + + // + // Set SIO interrupts and disable mouse. Let mouse driver + // re-enable it. + // + LegMask = (UINT16) ((LegMask &~LegacyInt) | 0x1000); + Private->Legacy8259->SetMask ( + Private->Legacy8259, + &LegMask, + NULL, + NULL, + NULL + ); + + // + // Disable mouse in keyboard controller + // + Register = 0xA7; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIsaIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo + ); + ASSERT_EFI_ERROR (Status); + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, 0x64, 1, &Register); + + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; + +} + +/** + Identify drive data must be updated to actual parameters before boot. + This requires updating the checksum, if it exists. + + @param IdentifyDriveData ATA Identify Data + @param Checksum checksum of the ATA Identify Data + + @retval EFI_SUCCESS checksum calculated + @retval EFI_SECURITY_VIOLATION IdentifyData invalid + +**/ +EFI_STATUS +CalculateIdentifyDriveChecksum ( + IN UINT8 *IdentifyDriveData, + OUT UINT8 *Checksum + ) +{ + UINTN Index; + UINT8 LocalChecksum; + LocalChecksum = 0; + *Checksum = 0; + if (IdentifyDriveData[510] != 0xA5) { + return EFI_SECURITY_VIOLATION; + } + + for (Index = 0; Index < 512; Index++) { + LocalChecksum = (UINT8) (LocalChecksum + IdentifyDriveData[Index]); + } + + *Checksum = LocalChecksum; + return EFI_SUCCESS; +} + + +/** + Identify drive data must be updated to actual parameters before boot. + + @param IdentifyDriveData ATA Identify Data + + +**/ +VOID +UpdateIdentifyDriveData ( + IN UINT8 *IdentifyDriveData + ) +{ + UINT16 NumberCylinders; + UINT16 NumberHeads; + UINT16 NumberSectorsTrack; + UINT32 CapacityInSectors; + UINT8 OriginalChecksum; + UINT8 FinalChecksum; + EFI_STATUS Status; + ATAPI_IDENTIFY *ReadInfo; + + // + // Status indicates if Integrity byte is correct. Checksum should be + // 0 if valid. + // + ReadInfo = (ATAPI_IDENTIFY *) IdentifyDriveData; + Status = CalculateIdentifyDriveChecksum (IdentifyDriveData, &OriginalChecksum); + if (OriginalChecksum != 0) { + Status = EFI_SECURITY_VIOLATION; + } + // + // If NumberCylinders = 0 then do data(Controller present but don drive attached). + // + NumberCylinders = ReadInfo->Raw[1]; + if (NumberCylinders != 0) { + ReadInfo->Raw[54] = NumberCylinders; + + NumberHeads = ReadInfo->Raw[3]; + ReadInfo->Raw[55] = NumberHeads; + + NumberSectorsTrack = ReadInfo->Raw[6]; + ReadInfo->Raw[56] = NumberSectorsTrack; + + // + // Copy Multisector info and set valid bit. + // + ReadInfo->Raw[59] = (UINT16) (ReadInfo->Raw[47] + 0x100); + CapacityInSectors = (UINT32) ((UINT32) (NumberCylinders) * (UINT32) (NumberHeads) * (UINT32) (NumberSectorsTrack)); + ReadInfo->Raw[57] = (UINT16) (CapacityInSectors >> 16); + ReadInfo->Raw[58] = (UINT16) (CapacityInSectors & 0xffff); + if (Status == EFI_SUCCESS) { + // + // Forece checksum byte to 0 and get new checksum. + // + ReadInfo->Raw[255] &= 0xff; + CalculateIdentifyDriveChecksum (IdentifyDriveData, &FinalChecksum); + + // + // Force new checksum such that sum is 0. + // + FinalChecksum = (UINT8) ((UINT8)0 - FinalChecksum); + ReadInfo->Raw[255] = (UINT16) (ReadInfo->Raw[255] | (FinalChecksum << 8)); + } + } +} + +/** + Identify drive data must be updated to actual parameters before boot. + Do for all drives. + + @param Private Legacy BIOS Instance data + + +**/ +VOID +UpdateAllIdentifyDriveData ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + UINTN Index; + HDD_INFO *HddInfo; + + HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; + + for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) { + // + // Each controller can have 2 devices. Update for each device + // + if ((HddInfo[Index].Status & HDD_MASTER_IDE) != 0) { + UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[0].Raw[0])); + } + + if ((HddInfo[Index].Status & HDD_SLAVE_IDE) != 0) { + UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[1].Raw[0])); + } + } +} + +/** + Enable ide controller. This gets disabled when LegacyBoot.c is about + to run the Option ROMs. + + @param Private Legacy BIOS Instance data + + +**/ +VOID +EnableIdeController ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + EFI_HANDLE IdeController; + UINT8 ByteBuffer; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + + Status = Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if (!EFI_ERROR (Status)) { + IdeController = HandleBuffer[0]; + Status = gBS->HandleProtocol ( + IdeController, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ByteBuffer = 0x1f; + if (!EFI_ERROR (Status)) { + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x04, 1, &ByteBuffer); + } + } +} + + +/** + Enable ide controller. This gets disabled when LegacyBoot.c is about + to run the Option ROMs. + + @param Private Legacy BIOS Instance data + + +**/ +VOID +EnableAllControllers ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE01 PciConfigHeader; + EFI_STATUS Status; + + // + // + // + EnableIdeController (Private); + + // + // Assumption is table is built from low bus to high bus numbers. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + // + // We do not enable PPB here. This is for HotPlug Consideration. + // The Platform HotPlug Driver is responsible for Padding enough hot plug + // resources. It is also responsible for enable this bridge. If it + // does not pad it. It will cause some early Windows fail to installation. + // If the platform driver does not pad resource for PPB, PPB should be in + // un-enabled state to let Windows know that this PPB is not configured by + // BIOS. So Windows will allocate default resource for PPB. + // + // The reason for why we enable the command register is: + // The CSM will use the IO bar to detect some IRQ status, if the command + // is disabled, the IO resource will be out of scope. + // For example: + // We installed a legacy IRQ handle for a PCI IDE controller. When IRQ + // comes up, the handle will check the IO space to identify is the + // controller generated the IRQ source. + // If the IO command is not enabled, the IRQ handler will has wrong + // information. It will cause IRQ storm when the correctly IRQ handler fails + // to run. + // + if (!(IS_PCI_VGA (&PciConfigHeader) || + IS_PCI_OLD_VGA (&PciConfigHeader) || + IS_PCI_IDE (&PciConfigHeader) || + IS_PCI_P2P (&PciConfigHeader) || + IS_PCI_P2P_SUB (&PciConfigHeader) || + IS_PCI_LPC (&PciConfigHeader) )) { + + PciConfigHeader.Hdr.Command |= 0x1f; + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 4, 1, &PciConfigHeader.Hdr.Command); + } + } +} + +/** + The following routines are identical in operation, so combine + for code compaction: + EfiGetPlatformBinaryGetMpTable + EfiGetPlatformBinaryGetOemIntData + EfiGetPlatformBinaryGetOem32Data + EfiGetPlatformBinaryGetOem16Data + + @param This Protocol instance pointer. + @param Id Table/Data identifier + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER Invalid ID + @retval EFI_OUT_OF_RESOURCES no resource to get data or table + +**/ +EFI_STATUS +LegacyGetDataOrTable ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_GET_PLATFORM_INFO_MODE Id + ) +{ + VOID *Table; + UINT32 TablePtr; + UINTN TableSize; + UINTN Alignment; + UINTN Location; + EFI_STATUS Status; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + EFI_COMPATIBILITY16_TABLE *Legacy16Table; + EFI_IA32_REGISTER_SET Regs; + LEGACY_BIOS_INSTANCE *Private; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + + LegacyBiosPlatform = Private->LegacyBiosPlatform; + Legacy16Table = Private->Legacy16Table; + + // + // Phase 1 - get an address allocated in 16-bit code + // + while (TRUE) { + switch (Id) { + case EfiGetPlatformBinaryMpTable: + case EfiGetPlatformBinaryOemIntData: + case EfiGetPlatformBinaryOem32Data: + case EfiGetPlatformBinaryOem16Data: + { + Status = LegacyBiosPlatform->GetPlatformInfo ( + LegacyBiosPlatform, + Id, + (VOID *) &Table, + &TableSize, + &Location, + &Alignment, + 0, + 0 + ); + DEBUG ((EFI_D_INFO, "LegacyGetDataOrTable - ID: %x, %r\n", (UINTN)Id, Status)); + DEBUG ((EFI_D_INFO, " Table - %x, Size - %x, Location - %x, Alignment - %x\n", (UINTN)Table, (UINTN)TableSize, (UINTN)Location, (UINTN)Alignment)); + break; + } + + default: + { + return EFI_INVALID_PARAMETER; + } + } + + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16GetTableAddress; + Regs.X.CX = (UINT16) TableSize; + Regs.X.BX = (UINT16) Location; + Regs.X.DX = (UINT16) Alignment; + Private->LegacyBios.FarCall86 ( + This, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + if (Regs.X.AX != 0) { + DEBUG ((EFI_D_ERROR, "Table ID %x length insufficient\n", Id)); + return EFI_OUT_OF_RESOURCES; + } else { + break; + } + } + // + // Phase 2 Call routine second time with address to allow address adjustment + // + Status = LegacyBiosPlatform->GetPlatformInfo ( + LegacyBiosPlatform, + Id, + (VOID *) &Table, + &TableSize, + &Location, + &Alignment, + Regs.X.DS, + Regs.X.BX + ); + switch (Id) { + case EfiGetPlatformBinaryMpTable: + { + Legacy16Table->MpTablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + Legacy16Table->MpTableLength = (UINT32)TableSize; + DEBUG ((EFI_D_INFO, "MP table in legacy region - %x\n", (UINTN)Legacy16Table->MpTablePtr)); + break; + } + + case EfiGetPlatformBinaryOemIntData: + { + + Legacy16Table->OemIntSegment = Regs.X.DS; + Legacy16Table->OemIntOffset = Regs.X.BX; + DEBUG ((EFI_D_INFO, "OemInt table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->OemIntSegment, (UINTN)Legacy16Table->OemIntOffset)); + break; + } + + case EfiGetPlatformBinaryOem32Data: + { + Legacy16Table->Oem32Segment = Regs.X.DS; + Legacy16Table->Oem32Offset = Regs.X.BX; + DEBUG ((EFI_D_INFO, "Oem32 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem32Segment, (UINTN)Legacy16Table->Oem32Offset)); + break; + } + + case EfiGetPlatformBinaryOem16Data: + { + // + // Legacy16Table->Oem16Segment = Regs.X.DS; + // Legacy16Table->Oem16Offset = Regs.X.BX; + DEBUG ((EFI_D_INFO, "Oem16 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem16Segment, (UINTN)Legacy16Table->Oem16Offset)); + break; + } + + default: + { + return EFI_INVALID_PARAMETER; + } + } + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Phase 3 Copy table to final location + // + TablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + + CopyMem ( + (VOID *) (UINTN)TablePtr, + Table, + TableSize + ); + + return EFI_SUCCESS; +} + +/** + Copy SMBIOS table to EfiReservedMemoryType of memory for legacy boot. + +**/ +VOID +CreateSmbiosTableInReservedMemory ( + VOID + ) +{ + SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; + + if ((mRuntimeSmbiosEntryPoint == NULL) || + (mReserveSmbiosEntryPoint == 0) || + (mStructureTableAddress == 0)) { + return; + } + + EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint; + + // + // Copy SMBIOS Entry Point Structure + // + CopyMem ( + (VOID *)(UINTN) mReserveSmbiosEntryPoint, + EntryPointStructure, + EntryPointStructure->EntryPointLength + ); + + // + // Copy SMBIOS Structure Table into EfiReservedMemoryType memory + // + CopyMem ( + (VOID *)(UINTN) mStructureTableAddress, + (VOID *)(UINTN) EntryPointStructure->TableAddress, + EntryPointStructure->TableLength + ); + + // + // Update TableAddress in Entry Point Structure + // + EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN) mReserveSmbiosEntryPoint; + EntryPointStructure->TableAddress = (UINT32)(UINTN) mStructureTableAddress; + + // + // Fixup checksums in the Entry Point Structure + // + EntryPointStructure->IntermediateChecksum = 0; + EntryPointStructure->EntryPointStructureChecksum = 0; + + EntryPointStructure->IntermediateChecksum = + CalculateCheckSum8 ( + (UINT8 *) EntryPointStructure + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString), + EntryPointStructure->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString) + ); + EntryPointStructure->EntryPointStructureChecksum = + CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure->EntryPointLength); +} + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + Note: BBS compliant drives ARE NOT available until this call by + either shell or EFI. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS Drive numbers assigned + +**/ +EFI_STATUS +GenericLegacyBoot ( + IN EFI_LEGACY_BIOS_PROTOCOL *This + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + EFI_IA32_REGISTER_SET Regs; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + UINTN CopySize; + VOID *AcpiPtr; + HDD_INFO *HddInfo; + HDD_INFO *LocalHddInfo; + UINTN Index; + EFI_COMPATIBILITY16_TABLE *Legacy16Table; + UINT32 *BdaPtr; + UINT16 HddCount; + UINT16 BbsCount; + BBS_TABLE *LocalBbsTable; + UINT32 *BaseVectorMaster; + EFI_TIME BootTime; + UINT32 LocalTime; + EFI_HANDLE IdeController; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + VOID *AcpiTable; + UINTN ShadowAddress; + UINT32 Granularity; + + LocalHddInfo = NULL; + HddCount = 0; + BbsCount = 0; + LocalBbsTable = NULL; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + DEBUG_CODE ( + DEBUG ((EFI_D_ERROR, "Start of legacy boot\n")); + ); + + Legacy16Table = Private->Legacy16Table; + EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; + HddInfo = &EfiToLegacy16BootTable->HddInfo[0]; + + LegacyBiosPlatform = Private->LegacyBiosPlatform; + + EfiToLegacy16BootTable->MajorVersion = EFI_TO_LEGACY_MAJOR_VERSION; + EfiToLegacy16BootTable->MinorVersion = EFI_TO_LEGACY_MINOR_VERSION; + + // + // If booting to a legacy OS then force HDD drives to the appropriate + // boot mode by calling GetIdeHandle. + // A reconnect -r can force all HDDs back to native mode. + // + IdeController = NULL; + if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { + Status = LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if (!EFI_ERROR (Status)) { + IdeController = HandleBuffer[0]; + } + } + // + // Unlock the Legacy BIOS region + // + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + + // + // Reconstruct the Legacy16 boot memory map + // + LegacyBiosBuildE820 (Private, &CopySize); + if (CopySize > Private->Legacy16Table->E820Length) { + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16GetTableAddress; + Regs.X.CX = (UINT16) CopySize; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16Table->Compatibility16CallSegment, + Private->Legacy16Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + Private->Legacy16Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + Private->Legacy16Table->E820Length = (UINT32) CopySize; + if (Regs.X.AX != 0) { + DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n")); + } else { + CopyMem ( + (VOID *)(UINTN) Private->Legacy16Table->E820Pointer, + Private->E820Table, + CopySize + ); + } + } else { + CopyMem ( + (VOID *)(UINTN) Private->Legacy16Table->E820Pointer, + Private->E820Table, + CopySize + ); + Private->Legacy16Table->E820Length = (UINT32) CopySize; + } + + // + // We do not ASSERT if SmbiosTable not found. It is possbile that a platform does not produce SmbiosTable. + // + if (mReserveSmbiosEntryPoint == 0) { + DEBUG ((EFI_D_INFO, "Smbios table is not found!\n")); + } + CreateSmbiosTableInReservedMemory (); + EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)mReserveSmbiosEntryPoint; + + AcpiTable = NULL; + Status = EfiGetSystemConfigurationTable ( + &gEfiAcpi20TableGuid, + &AcpiTable + ); + if (EFI_ERROR (Status)) { + Status = EfiGetSystemConfigurationTable ( + &gEfiAcpi10TableGuid, + &AcpiTable + ); + } + // + // We do not ASSERT if AcpiTable not found. It is possbile that a platform does not produce AcpiTable. + // + if (AcpiTable == NULL) { + DEBUG ((EFI_D_INFO, "ACPI table is not found!\n")); + } + EfiToLegacy16BootTable->AcpiTable = (UINT32)(UINTN)AcpiTable; + + // + // Get RSD Ptr table rev at offset 15 decimal + // Rev = 0 Length is 20 decimal + // Rev != 0 Length is UINT32 at offset 20 decimal + // + if (AcpiTable != NULL) { + + AcpiPtr = AcpiTable; + if (*((UINT8 *) AcpiPtr + 15) == 0) { + CopySize = 20; + } else { + AcpiPtr = ((UINT8 *) AcpiPtr + 20); + CopySize = (*(UINT32 *) AcpiPtr); + } + + CopyMem ( + (VOID *)(UINTN) Private->Legacy16Table->AcpiRsdPtrPointer, + AcpiTable, + CopySize + ); + } + // + // Make sure all PCI Interrupt Line register are programmed to match 8259 + // + PciProgramAllInterruptLineRegisters (Private); + + // + // Unlock the Legacy BIOS region as PciProgramAllInterruptLineRegisters + // can lock it. + // + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + Private->BiosStart, + Private->LegacyBiosImageSize, + &Granularity + ); + + // + // Configure Legacy Device Magic + // + // Only do this code if booting legacy OS + // + if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { + UpdateSioData (Private); + } + // + // Setup BDA and EBDA standard areas before Legacy Boot + // + LegacyBiosCompleteBdaBeforeBoot (Private); + LegacyBiosCompleteStandardCmosBeforeBoot (Private); + + // + // We must build IDE data, if it hasn't been done, before PciShadowRoms + // to insure EFI drivers are connected. + // + LegacyBiosBuildIdeData (Private, &HddInfo, 1); + UpdateAllIdentifyDriveData (Private); + + // + // Clear IO BAR, if IDE controller in legacy mode. + // + InitLegacyIdeController (IdeController); + + // + // Generate number of ticks since midnight for BDA. DOS requires this + // for its time. We have to make assumptions as to how long following + // code takes since after PciShadowRoms PciIo is gone. Place result in + // 40:6C-6F + // + // Adjust value by 1 second. + // + gRT->GetTime (&BootTime, NULL); + LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second; + LocalTime += 1; + + // + // Multiply result by 18.2 for number of ticks since midnight. + // Use 182/10 to avoid floating point math. + // + LocalTime = (LocalTime * 182) / 10; + BdaPtr = (UINT32 *) (UINTN)0x46C; + *BdaPtr = LocalTime; + + // + // Shadow PCI ROMs. We must do this near the end since this will kick + // of Native EFI drivers that may be needed to collect info for Legacy16 + // + // WARNING: PciIo is gone after this call. + // + PciShadowRoms (Private); + + // + // Shadow PXE base code, BIS etc. + // + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity); + ShadowAddress = Private->OptionRom; + Private->LegacyBiosPlatform->PlatformHooks ( + Private->LegacyBiosPlatform, + EfiPlatformHookShadowServiceRoms, + 0, + 0, + &ShadowAddress, + Legacy16Table, + NULL + ); + Private->OptionRom = (UINT32)ShadowAddress; + // + // Register Legacy SMI Handler + // + LegacyBiosPlatform->SmmInit ( + LegacyBiosPlatform, + EfiToLegacy16BootTable + ); + + // + // Let platform code know the boot options + // + LegacyBiosGetBbsInfo ( + This, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + DEBUG_CODE ( + PrintPciInterruptRegister (); + PrintBbsTable (LocalBbsTable); + PrintHddInfo (LocalHddInfo); + ); + // + // If drive wasn't spun up then BuildIdeData may have found new drives. + // Need to update BBS boot priority. + // + for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) { + if ((LocalHddInfo[Index].IdentifyDrive[0].Raw[0] != 0) && + (LocalBbsTable[2 * Index + 1].BootPriority == BBS_IGNORE_ENTRY) + ) { + LocalBbsTable[2 * Index + 1].BootPriority = BBS_UNPRIORITIZED_ENTRY; + } + + if ((LocalHddInfo[Index].IdentifyDrive[1].Raw[0] != 0) && + (LocalBbsTable[2 * Index + 2].BootPriority == BBS_IGNORE_ENTRY) + ) { + LocalBbsTable[2 * Index + 2].BootPriority = BBS_UNPRIORITIZED_ENTRY; + } + } + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xc0000, + 0x40000, + &Granularity + ); + + LegacyBiosPlatform->PrepareToBoot ( + LegacyBiosPlatform, + mBbsDevicePathPtr, + mBbsTable, + mLoadOptionsSize, + mLoadOptions, + (VOID *) &Private->IntThunk->EfiToLegacy16BootTable + ); + + // + // If no boot device return to BDS + // + if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { + for (Index = 0; Index < BbsCount; Index++){ + if ((LocalBbsTable[Index].BootPriority != BBS_DO_NOT_BOOT_FROM) && + (LocalBbsTable[Index].BootPriority != BBS_UNPRIORITIZED_ENTRY) && + (LocalBbsTable[Index].BootPriority != BBS_IGNORE_ENTRY)) { + break; + } + } + if (Index == BbsCount) { + return EFI_DEVICE_ERROR; + } + } + // + // Let the Legacy16 code know the device path type for legacy boot + // + EfiToLegacy16BootTable->DevicePathType = mBbsDevicePathPtr->DeviceType; + + // + // Copy MP table, if it exists. + // + LegacyGetDataOrTable (This, EfiGetPlatformBinaryMpTable); + + if (!Private->LegacyBootEntered) { + // + // Copy OEM INT Data, if it exists. Note: This code treats any data + // as a bag of bits and knows nothing of the contents nor cares. + // Contents are IBV specific. + // + LegacyGetDataOrTable (This, EfiGetPlatformBinaryOemIntData); + + // + // Copy OEM16 Data, if it exists.Note: This code treats any data + // as a bag of bits and knows nothing of the contents nor cares. + // Contents are IBV specific. + // + LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem16Data); + + // + // Copy OEM32 Data, if it exists.Note: This code treats any data + // as a bag of bits and knows nothing of the contents nor cares. + // Contents are IBV specific. + // + LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem32Data); + } + + // + // Call into Legacy16 code to prepare for INT 19h + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16PrepareToBoot; + + // + // Pass in handoff data + // + Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINTN)EfiToLegacy16BootTable); + Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINTN)EfiToLegacy16BootTable); + + Private->LegacyBios.FarCall86 ( + This, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + if (Regs.X.AX != 0) { + return EFI_DEVICE_ERROR; + } + // + // Lock the Legacy BIOS region + // + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xc0000, + 0x40000, + &Granularity + ); + + if ((Private->Legacy16Table->TableLength >= OFFSET_OF (EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) && + ((Private->Legacy16Table->UmaAddress != 0) && (Private->Legacy16Table->UmaSize != 0))) { + // + // Here we could reduce UmaAddress down as far as Private->OptionRom, taking into + // account the granularity of the access control. + // + DEBUG((EFI_D_INFO, "Unlocking UMB RAM region 0x%x-0x%x\n", Private->Legacy16Table->UmaAddress, + Private->Legacy16Table->UmaAddress + Private->Legacy16Table->UmaSize)); + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + Private->Legacy16Table->UmaAddress, + Private->Legacy16Table->UmaSize, + &Granularity + ); + } + + // + // Lock attributes of the Legacy Region if chipset supports + // + Private->LegacyRegion->BootLock ( + Private->LegacyRegion, + 0xc0000, + 0x40000, + &Granularity + ); + + // + // Call into Legacy16 code to do the INT 19h + // + EnableAllControllers (Private); + if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { + + // + // Signal all the events that are waiting on EVT_SIGNAL_LEGACY_BOOT + // + EfiSignalEventLegacyBoot (); + + // + // Report Status Code to indicate legacy boot event was signalled + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT) + ); + + DEBUG ((EFI_D_INFO, "Legacy INT19 Boot...\n")); + + // + // Disable DXE Timer while executing in real mode + // + Private->Timer->SetTimerPeriod (Private->Timer, 0); + + // + // Save and disable interrupt of debug timer + // + SaveAndSetDebugTimerInterrupt (FALSE); + + + // + // Put the 8259 into its legacy mode by reprogramming the vector bases + // + Private->Legacy8259->SetVectorBase (Private->Legacy8259, LEGACY_MODE_BASE_VECTOR_MASTER, LEGACY_MODE_BASE_VECTOR_SLAVE); + // + // PC History + // The original PC used INT8-F for master PIC. Since these mapped over + // processor exceptions TIANO moved the master PIC to INT68-6F. + // We need to set these back to the Legacy16 unexpected interrupt(saved + // in LegacyBios.c) since some OS see that these have values different from + // what is expected and invoke them. Since the legacy OS corrupts EFI + // memory, there is no handler for these interrupts and OS blows up. + // + // We need to save the TIANO values for the rare case that the Legacy16 + // code cannot boot but knows memory hasn't been destroyed. + // + // To compound the problem, video takes over one of these INTS and must be + // be left. + // @bug - determine if video hooks INT(in which case we must find new + // set of TIANO vectors) or takes it over. + // + // + BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER); + for (Index = 0; Index < 8; Index++) { + Private->ThunkSavedInt[Index] = BaseVectorMaster[Index]; + if (Private->ThunkSeg == (UINT16) (BaseVectorMaster[Index] >> 16)) { + BaseVectorMaster[Index] = (UINT32) (Private->BiosUnexpectedInt); + } + } + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16Boot; + + Private->LegacyBios.FarCall86 ( + This, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER); + for (Index = 0; Index < 8; Index++) { + BaseVectorMaster[Index] = Private->ThunkSavedInt[Index]; + } + } + Private->LegacyBootEntered = TRUE; + if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { + // + // Should never return unless never passed control to 0:7c00(first stage + // OS loader) and only then if no bootable device found. + // + return EFI_DEVICE_ERROR; + } else { + // + // If boot to EFI then expect to return to caller + // + return EFI_SUCCESS; + } +} + + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + Note: BBS compliant drives ARE NOT available until this call by + either shell or EFI. + + @param This Protocol instance pointer. + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Drive numbers assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosPrepareToBootEfi ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ) +{ + EFI_STATUS Status; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + LEGACY_BIOS_INSTANCE *Private; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; + mBootMode = BOOT_EFI_OS; + mBbsDevicePathPtr = NULL; + Status = GenericLegacyBoot (This); + *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; + *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); + return Status; +} + +/** + To boot from an unconventional device like parties and/or execute HDD diagnostics. + + @param This Protocol instance pointer. + @param Attributes How to interpret the other input parameters + @param BbsEntry The 0-based index into the BbsTable for the parent + device. + @param BeerData Pointer to the 128 bytes of ram BEER data. + @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. The + caller must provide a pointer to the specific Service + Area and not the start all Service Areas. + + @retval EFI_INVALID_PARAMETER if error. Does NOT return if no error. + +***/ +EFI_STATUS +EFIAPI +LegacyBiosBootUnconventionalDevice ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UDC_ATTRIBUTES Attributes, + IN UINTN BbsEntry, + IN VOID *BeerData, + IN VOID *ServiceAreaData + ) +{ + EFI_STATUS Status; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + LEGACY_BIOS_INSTANCE *Private; + UD_TABLE *UcdTable; + UINTN Index; + UINT16 BootPriority; + BBS_TABLE *BbsTable; + + BootPriority = 0; + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + mBootMode = BOOT_UNCONVENTIONAL_DEVICE; + mBbsDevicePathPtr = &mBbsDevicePathNode; + mAttributes = Attributes; + mBbsEntry = BbsEntry; + mBeerData = BeerData, mServiceAreaData = ServiceAreaData; + + EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; + + // + // Do input parameter checking + // + if ((Attributes.DirectoryServiceValidity == 0) && + (Attributes.RabcaUsedFlag == 0) && + (Attributes.ExecuteHddDiagnosticsFlag == 0) + ) { + return EFI_INVALID_PARAMETER; + } + + if (((Attributes.DirectoryServiceValidity != 0) && (ServiceAreaData == NULL)) || + (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag) != 0) && (BeerData == NULL)) + ) { + return EFI_INVALID_PARAMETER; + } + + UcdTable = (UD_TABLE *) AllocatePool ( + sizeof (UD_TABLE) + ); + if (NULL == UcdTable) { + return EFI_OUT_OF_RESOURCES; + } + + EfiToLegacy16BootTable->UnconventionalDeviceTable = (UINT32)(UINTN)UcdTable; + UcdTable->Attributes = Attributes; + UcdTable->BbsTableEntryNumberForParentDevice = (UINT8) BbsEntry; + // + // Force all existing BBS entries to DoNotBoot. This allows 16-bit CSM + // to assign drive numbers but bot boot from. Only newly created entries + // will be valid. + // + BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; + for (Index = 0; Index < EfiToLegacy16BootTable->NumberBbsEntries; Index++) { + BbsTable[Index].BootPriority = BBS_DO_NOT_BOOT_FROM; + } + // + // If parent is onboard IDE then assign controller & device number + // else they are 0. + // + if (BbsEntry < MAX_IDE_CONTROLLER * 2) { + UcdTable->DeviceNumber = (UINT8) ((BbsEntry - 1) % 2); + } + + if (BeerData != NULL) { + CopyMem ( + (VOID *) UcdTable->BeerData, + BeerData, + (UINTN) 128 + ); + } + + if (ServiceAreaData != NULL) { + CopyMem ( + (VOID *) UcdTable->ServiceAreaData, + ServiceAreaData, + (UINTN) 64 + ); + } + // + // For each new entry do the following: + // 1. Increment current number of BBS entries + // 2. Copy parent entry to new entry. + // 3. Zero out BootHandler Offset & segment + // 4. Set appropriate device type. BEV(0x80) for HDD diagnostics + // and Floppy(0x01) for PARTIES boot. + // 5. Assign new priority. + // + if ((Attributes.ExecuteHddDiagnosticsFlag) != 0) { + EfiToLegacy16BootTable->NumberBbsEntries += 1; + + CopyMem ( + (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority, + (VOID *) &BbsTable[BbsEntry].BootPriority, + sizeof (BBS_TABLE) + ); + + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = 0; + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0; + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = 0x80; + + UcdTable->BbsTableEntryNumberForHddDiag = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1); + + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority; + BootPriority += 1; + + // + // Set device type as BBS_TYPE_DEV for PARTIES diagnostic + // + mBbsDevicePathNode.DeviceType = BBS_TYPE_BEV; + } + + if (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag)) != 0) { + EfiToLegacy16BootTable->NumberBbsEntries += 1; + CopyMem ( + (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority, + (VOID *) &BbsTable[BbsEntry].BootPriority, + sizeof (BBS_TABLE) + ); + + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = 0; + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0; + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = 0x01; + UcdTable->BbsTableEntryNumberForBoot = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1); + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority; + + // + // Set device type as BBS_TYPE_FLOPPY for PARTIES boot as floppy + // + mBbsDevicePathNode.DeviceType = BBS_TYPE_FLOPPY; + } + // + // Build the BBS Device Path for this boot selection + // + mBbsDevicePathNode.Header.Type = BBS_DEVICE_PATH; + mBbsDevicePathNode.Header.SubType = BBS_BBS_DP; + SetDevicePathNodeLength (&mBbsDevicePathNode.Header, sizeof (BBS_BBS_DEVICE_PATH)); + mBbsDevicePathNode.StatusFlag = 0; + mBbsDevicePathNode.String[0] = 0; + + Status = GenericLegacyBoot (This); + return Status; +} + +/** + Attempt to legacy boot the BootOption. If the EFI contexted has been + compromised this function will not return. + + @param This Protocol instance pointer. + @param BbsDevicePath EFI Device Path from BootXXXX variable. + @param LoadOptionsSize Size of LoadOption in size. + @param LoadOptions LoadOption from BootXXXX variable + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +EFIAPI +LegacyBiosLegacyBoot ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions + ) +{ + EFI_STATUS Status; + + mBbsDevicePathPtr = BbsDevicePath; + mLoadOptionsSize = LoadOptionsSize; + mLoadOptions = LoadOptions; + mBootMode = BOOT_LEGACY_OS; + Status = GenericLegacyBoot (This); + + return Status; +} + +/** + Convert EFI Memory Type to E820 Memory Type. + + @param Type EFI Memory Type + + @return ACPI Memory Type for EFI Memory Type + +**/ +EFI_ACPI_MEMORY_TYPE +EfiMemoryTypeToE820Type ( + IN UINT32 Type + ) +{ + switch (Type) { + case EfiLoaderCode: + case EfiLoaderData: + case EfiBootServicesCode: + case EfiBootServicesData: + case EfiConventionalMemory: + // + // The memory of EfiRuntimeServicesCode and EfiRuntimeServicesData are + // usable memory for legacy OS, because legacy OS is not aware of EFI runtime concept. + // In ACPI specification, EfiRuntimeServiceCode and EfiRuntimeServiceData + // should be mapped to AddressRangeReserved. This statement is for UEFI OS, not for legacy OS. + // + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + return EfiAcpiAddressRangeMemory; + + case EfiPersistentMemory: + return EfiAddressRangePersistentMemory; + + case EfiACPIReclaimMemory: + return EfiAcpiAddressRangeACPI; + + case EfiACPIMemoryNVS: + return EfiAcpiAddressRangeNVS; + + // + // All other types map to reserved. + // Adding the code just waists FLASH space. + // + // case EfiReservedMemoryType: + // case EfiUnusableMemory: + // case EfiMemoryMappedIO: + // case EfiMemoryMappedIOPortSpace: + // case EfiPalCode: + // + default: + return EfiAcpiAddressRangeReserved; + } +} + +/** + Build the E820 table. + + @param Private Legacy BIOS Instance data + @param Size Size of E820 Table + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildE820 ( + IN LEGACY_BIOS_INSTANCE *Private, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_E820_ENTRY64 *E820Table; + EFI_MEMORY_DESCRIPTOR *EfiMemoryMap; + EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd; + EFI_MEMORY_DESCRIPTOR *EfiEntry; + EFI_MEMORY_DESCRIPTOR *NextEfiEntry; + EFI_MEMORY_DESCRIPTOR TempEfiEntry; + UINTN EfiMemoryMapSize; + UINTN EfiMapKey; + UINTN EfiDescriptorSize; + UINT32 EfiDescriptorVersion; + UINTN Index; + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + UINTN TempIndex; + UINTN IndexSort; + UINTN TempNextIndex; + EFI_E820_ENTRY64 TempE820; + EFI_ACPI_MEMORY_TYPE TempType; + BOOLEAN ChangedFlag; + UINTN Above1MIndex; + UINT64 MemoryBlockLength; + + E820Table = (EFI_E820_ENTRY64 *) Private->E820Table; + + // + // Get the EFI memory map. + // + EfiMemoryMapSize = 0; + EfiMemoryMap = NULL; + Status = gBS->GetMemoryMap ( + &EfiMemoryMapSize, + EfiMemoryMap, + &EfiMapKey, + &EfiDescriptorSize, + &EfiDescriptorVersion + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + do { + // + // Use size returned back plus 1 descriptor for the AllocatePool. + // We don't just multiply by 2 since the "for" loop below terminates on + // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize + // we process bogus entries and create bogus E820 entries. + // + EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapSize); + ASSERT (EfiMemoryMap != NULL); + Status = gBS->GetMemoryMap ( + &EfiMemoryMapSize, + EfiMemoryMap, + &EfiMapKey, + &EfiDescriptorSize, + &EfiDescriptorVersion + ); + if (EFI_ERROR (Status)) { + FreePool (EfiMemoryMap); + } + } while (Status == EFI_BUFFER_TOO_SMALL); + + ASSERT_EFI_ERROR (Status); + + // + // Punch in the E820 table for memory less than 1 MB. + // Assume ZeroMem () has been done on data structure. + // + // + // First entry is 0 to (640k - EBDA) + // + E820Table[0].BaseAddr = 0; + E820Table[0].Length = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4); + E820Table[0].Type = EfiAcpiAddressRangeMemory; + + // + // Second entry is (640k - EBDA) to 640k + // + E820Table[1].BaseAddr = E820Table[0].Length; + E820Table[1].Length = (UINT64) ((640 * 1024) - E820Table[0].Length); + E820Table[1].Type = EfiAcpiAddressRangeReserved; + + // + // Third Entry is legacy BIOS + // DO NOT CLAIM region from 0xA0000-0xDFFFF. OS can use free areas + // to page in memory under 1MB. + // Omit region from 0xE0000 to start of BIOS, if any. This can be + // used for a multiple reasons including OPROMS. + // + + // + // The CSM binary image size is not the actually size that CSM binary used, + // to avoid memory corrupt, we declare the 0E0000 - 0FFFFF is used by CSM binary. + // + E820Table[2].BaseAddr = 0xE0000; + E820Table[2].Length = 0x20000; + E820Table[2].Type = EfiAcpiAddressRangeReserved; + + Above1MIndex = 2; + + // + // Process the EFI map to produce E820 map; + // + + // + // Sort memory map from low to high + // + EfiEntry = EfiMemoryMap; + NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); + EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize); + while (EfiEntry < EfiMemoryMapEnd) { + while (NextEfiEntry < EfiMemoryMapEnd) { + if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) { + CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); + CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); + CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); + } + + NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptorSize); + } + + EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); + NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); + } + + EfiEntry = EfiMemoryMap; + EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize); + for (Index = Above1MIndex; (EfiEntry < EfiMemoryMapEnd) && (Index < EFI_MAX_E820_ENTRY - 1); ) { + MemoryBlockLength = (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12)); + if ((EfiEntry->PhysicalStart + MemoryBlockLength) < 0x100000) { + // + // Skip the memory block is under 1MB + // + } else { + if (EfiEntry->PhysicalStart < 0x100000) { + // + // When the memory block spans below 1MB, ensure the memory block start address is at least 1MB + // + MemoryBlockLength -= 0x100000 - EfiEntry->PhysicalStart; + EfiEntry->PhysicalStart = 0x100000; + } + + // + // Convert memory type to E820 type + // + TempType = EfiMemoryTypeToE820Type (EfiEntry->Type); + + if ((E820Table[Index].Type == TempType) && (EfiEntry->PhysicalStart == (E820Table[Index].BaseAddr + E820Table[Index].Length))) { + // + // Grow an existing entry + // + E820Table[Index].Length += MemoryBlockLength; + } else { + // + // Make a new entry + // + ++Index; + E820Table[Index].BaseAddr = EfiEntry->PhysicalStart; + E820Table[Index].Length = MemoryBlockLength; + E820Table[Index].Type = TempType; + } + } + EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); + } + + FreePool (EfiMemoryMap); + + // + // Process the reserved memory map to produce E820 map ; + // + for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + if (Hob.Raw != NULL && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + ResourceHob = Hob.ResourceDescriptor; + if (((ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_MAPPED_IO) || + (ResourceHob->ResourceType == EFI_RESOURCE_FIRMWARE_DEVICE) || + (ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) ) && + (ResourceHob->PhysicalStart > 0x100000) && + (Index < EFI_MAX_E820_ENTRY - 1)) { + ++Index; + E820Table[Index].BaseAddr = ResourceHob->PhysicalStart; + E820Table[Index].Length = ResourceHob->ResourceLength; + E820Table[Index].Type = EfiAcpiAddressRangeReserved; + } + } + } + + Index ++; + Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index; + Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index; + Private->NumberE820Entries = (UINT32)Index; + *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64)); + + // + // Sort E820Table from low to high + // + for (TempIndex = 0; TempIndex < Index; TempIndex++) { + ChangedFlag = FALSE; + for (TempNextIndex = 1; TempNextIndex < Index - TempIndex; TempNextIndex++) { + if (E820Table[TempNextIndex - 1].BaseAddr > E820Table[TempNextIndex].BaseAddr) { + ChangedFlag = TRUE; + TempE820.BaseAddr = E820Table[TempNextIndex - 1].BaseAddr; + TempE820.Length = E820Table[TempNextIndex - 1].Length; + TempE820.Type = E820Table[TempNextIndex - 1].Type; + + E820Table[TempNextIndex - 1].BaseAddr = E820Table[TempNextIndex].BaseAddr; + E820Table[TempNextIndex - 1].Length = E820Table[TempNextIndex].Length; + E820Table[TempNextIndex - 1].Type = E820Table[TempNextIndex].Type; + + E820Table[TempNextIndex].BaseAddr = TempE820.BaseAddr; + E820Table[TempNextIndex].Length = TempE820.Length; + E820Table[TempNextIndex].Type = TempE820.Type; + } + } + + if (!ChangedFlag) { + break; + } + } + + // + // Remove the overlap range + // + for (TempIndex = 1; TempIndex < Index; TempIndex++) { + if (E820Table[TempIndex - 1].BaseAddr <= E820Table[TempIndex].BaseAddr && + ((E820Table[TempIndex - 1].BaseAddr + E820Table[TempIndex - 1].Length) >= + (E820Table[TempIndex].BaseAddr +E820Table[TempIndex].Length))) { + // + //Overlap range is found + // + ASSERT (E820Table[TempIndex - 1].Type == E820Table[TempIndex].Type); + + if (TempIndex == Index - 1) { + E820Table[TempIndex].BaseAddr = 0; + E820Table[TempIndex].Length = 0; + E820Table[TempIndex].Type = (EFI_ACPI_MEMORY_TYPE) 0; + Index--; + break; + } else { + for (IndexSort = TempIndex; IndexSort < Index - 1; IndexSort ++) { + E820Table[IndexSort].BaseAddr = E820Table[IndexSort + 1].BaseAddr; + E820Table[IndexSort].Length = E820Table[IndexSort + 1].Length; + E820Table[IndexSort].Type = E820Table[IndexSort + 1].Type; + } + Index--; + } + } + } + + + + Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index; + Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index; + Private->NumberE820Entries = (UINT32)Index; + *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64)); + + // + // Determine OS usable memory above 1Mb + // + Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb = 0x0000; + for (TempIndex = Above1MIndex; TempIndex < Index; TempIndex++) { + if (E820Table[TempIndex].BaseAddr >= 0x100000 && E820Table[TempIndex].BaseAddr < 0x100000000ULL) { // not include above 4G memory + // + // ACPIReclaimMemory is also usable memory for ACPI OS, after OS dumps all ACPI tables. + // + if ((E820Table[TempIndex].Type == EfiAcpiAddressRangeMemory) || (E820Table[TempIndex].Type == EfiAcpiAddressRangeACPI)) { + Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb += (UINT32) (E820Table[TempIndex].Length); + } else { + break; // break at first not normal memory, because SMM may use reserved memory. + } + } + } + + Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb = Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb; + + // + // Print DEBUG information + // + for (TempIndex = 0; TempIndex < Index; TempIndex++) { + DEBUG((EFI_D_INFO, "E820[%2d]: 0x%16lx ---- 0x%16lx, Type = 0x%x \n", + TempIndex, + E820Table[TempIndex].BaseAddr, + (E820Table[TempIndex].BaseAddr + E820Table[TempIndex].Length), + E820Table[TempIndex].Type + )); + } + + return EFI_SUCCESS; +} + + +/** + Fill in the standard BDA and EBDA stuff prior to legacy Boot + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosCompleteBdaBeforeBoot ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + BDA_STRUC *Bda; + UINT16 MachineConfig; + DEVICE_PRODUCER_DATA_HEADER *SioPtr; + + Bda = (BDA_STRUC *) ((UINTN) 0x400); + MachineConfig = 0; + + SioPtr = &(Private->IntThunk->EfiToLegacy16BootTable.SioData); + Bda->Com1 = SioPtr->Serial[0].Address; + Bda->Com2 = SioPtr->Serial[1].Address; + Bda->Com3 = SioPtr->Serial[2].Address; + Bda->Com4 = SioPtr->Serial[3].Address; + + if (SioPtr->Serial[0].Address != 0x00) { + MachineConfig += 0x200; + } + + if (SioPtr->Serial[1].Address != 0x00) { + MachineConfig += 0x200; + } + + if (SioPtr->Serial[2].Address != 0x00) { + MachineConfig += 0x200; + } + + if (SioPtr->Serial[3].Address != 0x00) { + MachineConfig += 0x200; + } + + Bda->Lpt1 = SioPtr->Parallel[0].Address; + Bda->Lpt2 = SioPtr->Parallel[1].Address; + Bda->Lpt3 = SioPtr->Parallel[2].Address; + + if (SioPtr->Parallel[0].Address != 0x00) { + MachineConfig += 0x4000; + } + + if (SioPtr->Parallel[1].Address != 0x00) { + MachineConfig += 0x4000; + } + + if (SioPtr->Parallel[2].Address != 0x00) { + MachineConfig += 0x4000; + } + + Bda->NumberOfDrives = (UINT8) (Bda->NumberOfDrives + Private->IdeDriveCount); + if (SioPtr->Floppy.NumberOfFloppy != 0x00) { + MachineConfig = (UINT16) (MachineConfig + 0x01 + (SioPtr->Floppy.NumberOfFloppy - 1) * 0x40); + Bda->FloppyXRate = 0x07; + } + + Bda->Lpt1_2Timeout = 0x1414; + Bda->Lpt3_4Timeout = 0x1414; + Bda->Com1_2Timeout = 0x0101; + Bda->Com3_4Timeout = 0x0101; + + // + // Force VGA and Coprocessor, indicate 101/102 keyboard + // + MachineConfig = (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr->MousePresent * 0x04)); + Bda->MachineConfig = MachineConfig; + + return EFI_SUCCESS; +} + +/** + Fill in the standard BDA for Keyboard LEDs + + @param This Protocol instance pointer. + @param Leds Current LED status + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosUpdateKeyboardLedStatus ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 Leds + ) +{ + LEGACY_BIOS_INSTANCE *Private; + BDA_STRUC *Bda; + UINT8 LocalLeds; + EFI_IA32_REGISTER_SET Regs; + + Bda = (BDA_STRUC *) ((UINTN) 0x400); + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + LocalLeds = Leds; + Bda->LedStatus = (UINT8) ((Bda->LedStatus &~0x07) | LocalLeds); + LocalLeds = (UINT8) (LocalLeds << 4); + Bda->ShiftStatus = (UINT8) ((Bda->ShiftStatus &~0x70) | LocalLeds); + LocalLeds = (UINT8) (Leds & 0x20); + Bda->KeyboardStatus = (UINT8) ((Bda->KeyboardStatus &~0x20) | LocalLeds); + // + // Call into Legacy16 code to allow it to do any processing + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX = Legacy16SetKeyboardLeds; + Regs.H.CL = Leds; + + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16Table->Compatibility16CallSegment, + Private->Legacy16Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + return EFI_SUCCESS; +} + + +/** + Fill in the standard CMOS stuff prior to legacy Boot + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosCompleteStandardCmosBeforeBoot ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + UINT8 Bda; + UINT8 Floppy; + UINT32 Size; + + // + // Update CMOS locations + // 10 floppy + // 12,19,1A - ignore as OS don't use them and there is no standard due + // to large capacity drives + // CMOS 14 = BDA 40:10 plus bit 3(display enabled) + // + Bda = (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3); + + // + // Force display enabled + // + Floppy = 0x00; + if ((Bda & BIT0) != 0) { + Floppy = BIT6; + } + + // + // Check if 2.88MB floppy set + // + if ((Bda & (BIT7 | BIT6)) != 0) { + Floppy = (UINT8)(Floppy | BIT1); + } + + LegacyWriteStandardCmos (CMOS_10, Floppy); + LegacyWriteStandardCmos (CMOS_14, Bda); + + // + // Force Status Register A to set rate selection bits and divider + // + LegacyWriteStandardCmos (CMOS_0A, 0x26); + + // + // redo memory size since it can change + // + Size = (15 * SIZE_1MB) >> 10; + if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) { + Size = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10; + } + + LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF)); + LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF)); + LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8)); + LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8)); + + LegacyCalculateWriteStandardCmosChecksum (); + + return EFI_SUCCESS; +} + +/** + Relocate this image under 4G memory for IPF. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Image successfully relocated. + @retval EFI_ABORTED Failed to relocate image. + +**/ +EFI_STATUS +RelocateImageUnder4GIfNeeded ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c new file mode 100644 index 0000000000..0fbf902813 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c @@ -0,0 +1,124 @@ +/** @file + This code fills in standard CMOS values and updates the standard CMOS + checksum. The Legacy16 code or LegacyBiosPlatform.c is responsible for + non-standard CMOS locations and non-standard checksums. + +Copyright (c) 2006 - 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 "LegacyBiosInterface.h" + +/** + Read CMOS register through index/data port. + + @param[in] Index The index of the CMOS register to read. + + @return The data value from the CMOS register specified by Index. + +**/ +UINT8 +LegacyReadStandardCmos ( + IN UINT8 Index + ) +{ + IoWrite8 (PORT_70, Index); + return IoRead8 (PORT_71); +} + +/** + Write CMOS register through index/data port. + + @param[in] Index The index of the CMOS register to write. + @param[in] Value The value of CMOS register to write. + + @return The value written to the CMOS register specified by Index. + +**/ +UINT8 +LegacyWriteStandardCmos ( + IN UINT8 Index, + IN UINT8 Value + ) +{ + IoWrite8 (PORT_70, Index); + return IoWrite8 (PORT_71, Value); +} + +/** + Calculate the new standard CMOS checksum and write it. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Calculate 16-bit checksum successfully + +**/ +EFI_STATUS +LegacyCalculateWriteStandardCmosChecksum ( + VOID + ) +{ + UINT8 Register; + UINT16 Checksum; + + for (Checksum = 0, Register = 0x10; Register < 0x2e; Register++) { + Checksum = (UINT16)(Checksum + LegacyReadStandardCmos (Register)); + } + LegacyWriteStandardCmos (CMOS_2E, (UINT8)(Checksum >> 8)); + LegacyWriteStandardCmos (CMOS_2F, (UINT8)(Checksum & 0xff)); + return EFI_SUCCESS; +} + + +/** + Fill in the standard CMOS stuff before Legacy16 load + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosInitCmos ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + UINT32 Size; + + // + // Clear all errors except RTC lost power + // + LegacyWriteStandardCmos (CMOS_0E, (UINT8)(LegacyReadStandardCmos (CMOS_0E) & BIT7)); + + // + // Update CMOS locations 15,16,17,18,30,31 and 32 + // CMOS 16,15 = 640Kb = 0x280 + // CMOS 18,17 = 31,30 = 15Mb max in 1Kb increments =0x3C00 max + // CMOS 32 = 0x20 + // + LegacyWriteStandardCmos (CMOS_15, 0x80); + LegacyWriteStandardCmos (CMOS_16, 0x02); + + Size = 15 * SIZE_1MB; + if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) { + Size = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10; + } + + LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF)); + LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF)); + LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8)); + LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8)); + + LegacyCalculateWriteStandardCmosChecksum (); + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c new file mode 100644 index 0000000000..4d520f8a32 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c @@ -0,0 +1,317 @@ +/** @file + Collect IDE information from Native EFI Driver + +Copyright (c) 2006 - 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 "LegacyBiosInterface.h" + +BOOLEAN mIdeDataBuiltFlag = FALSE; + +/** + Collect IDE Inquiry data from the IDE disks + + @param Private Legacy BIOS Instance data + @param HddInfo Hdd Information + @param Flag Reconnect IdeController or not + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildIdeData ( + IN LEGACY_BIOS_INSTANCE *Private, + IN HDD_INFO **HddInfo, + IN UINT16 Flag + ) +{ + EFI_STATUS Status; + EFI_HANDLE IdeController; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_DISK_INFO_PROTOCOL *DiskInfo; + UINT32 IdeChannel; + UINT32 IdeDevice; + UINT32 Size; + UINT8 *InquiryData; + UINT32 InquiryDataSize; + HDD_INFO *LocalHddInfo; + UINT32 PciIndex; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode; + PCI_DEVICE_PATH *PciDevicePath; + + // + // Only build data once + // We have a problem with GetBbsInfo in that it can be invoked two + // places. Once in BDS, when all EFI drivers are connected and once in + // LegacyBoot after all EFI drivers are disconnected causing this routine + // to hang. In LegacyBoot this function is also called before EFI drivers + // are disconnected. + // Cases covered + // GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored. + // GetBbsInfo not invoked in BDS. First invocation of this function + // proceeds normally and second via GetBbsInfo ignored. + // + PciDevicePath = NULL; + LocalHddInfo = *HddInfo; + Status = Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &HandleBuffer, + &HandleCount, + (VOID *) &LocalHddInfo + ); + if (!EFI_ERROR (Status)) { + IdeController = HandleBuffer[0]; + // + // Force IDE drive spin up! + // + if (Flag != 0) { + gBS->DisconnectController ( + IdeController, + NULL, + NULL + ); + } + + gBS->ConnectController (IdeController, NULL, NULL, FALSE); + + // + // Do GetIdeHandle twice since disconnect/reconnect will switch to native mode + // And GetIdeHandle will switch to Legacy mode, if required. + // + Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &HandleBuffer, + &HandleCount, + (VOID *) &LocalHddInfo + ); + } + + mIdeDataBuiltFlag = TRUE; + + // + // Get Identity command from all drives + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDiskInfoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + Private->IdeDriveCount = (UINT8) HandleCount; + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDiskInfoProtocolGuid, + (VOID **) &DiskInfo + ); + ASSERT_EFI_ERROR (Status); + + if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) { + // + // Locate which PCI device + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID *) &DevicePath + ); + ASSERT_EFI_ERROR (Status); + + DevicePathNode = DevicePath; + while (!IsDevicePathEnd (DevicePathNode)) { + TempDevicePathNode = NextDevicePathNode (DevicePathNode); + if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) && + ( DevicePathSubType (DevicePathNode) == HW_PCI_DP) && + ( DevicePathType(TempDevicePathNode) == MESSAGING_DEVICE_PATH) && + ( DevicePathSubType(TempDevicePathNode) == MSG_ATAPI_DP) ) { + PciDevicePath = (PCI_DEVICE_PATH *) DevicePathNode; + break; + } + DevicePathNode = NextDevicePathNode (DevicePathNode); + } + + if (PciDevicePath == NULL) { + continue; + } + + // + // Find start of PCI device in HddInfo. The assumption of the data + // structure is 2 controllers(channels) per PCI device and each + // controller can have 2 drives(devices). + // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master + // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave + // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master + // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave + // @bug eventually need to pass in max number of entries + // for end of for loop + // + for (PciIndex = 0; PciIndex < 8; PciIndex++) { + if ((PciDevicePath->Device == LocalHddInfo[PciIndex].Device) && + (PciDevicePath->Function == LocalHddInfo[PciIndex].Function) + ) { + break; + } + } + + if (PciIndex == 8) { + continue; + } + + Status = DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice); + if (!EFI_ERROR (Status)) { + Size = sizeof (ATAPI_IDENTIFY); + DiskInfo->Identify ( + DiskInfo, + &LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[IdeDevice], + &Size + ); + if (IdeChannel == 0) { + LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_PRIMARY; + } else if (IdeChannel == 1) { + LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SECONDARY; + } + + InquiryData = NULL; + InquiryDataSize = 0; + Status = DiskInfo->Inquiry ( + DiskInfo, + NULL, + &InquiryDataSize + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + InquiryData = (UINT8 *) AllocatePool ( + InquiryDataSize + ); + if (InquiryData != NULL) { + Status = DiskInfo->Inquiry ( + DiskInfo, + InquiryData, + &InquiryDataSize + ); + } + } else { + Status = EFI_DEVICE_ERROR; + } + + // + // If ATAPI device then Inquiry will pass and ATA fail. + // + if (!EFI_ERROR (Status)) { + ASSERT (InquiryData != NULL); + // + // If IdeDevice = 0 then set master bit, else slave bit + // + if (IdeDevice == 0) { + if ((InquiryData[0] & 0x1f) == 0x05) { + LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_CDROM; + } else if ((InquiryData[0] & 0x1f) == 0x00) { + LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_ZIPDISK; + } + } else { + if ((InquiryData[0] & 0x1f) == 0x05) { + LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_CDROM; + } else if ((InquiryData[0] & 0x1f) == 0x00) { + LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_ZIPDISK; + } + } + FreePool (InquiryData); + } else { + if (IdeDevice == 0) { + LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_IDE; + } else { + LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_IDE; + } + } + } + } + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + + +/** + If the IDE channel is in compatibility (legacy) mode, remove all + PCI I/O BAR addresses from the controller. + + @param IdeController The handle of target IDE controller + + +**/ +VOID +InitLegacyIdeController ( + IN EFI_HANDLE IdeController + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 IOBarClear; + EFI_STATUS Status; + PCI_TYPE00 PciData; + + // + // If the IDE channel is in compatibility (legacy) mode, remove all + // PCI I/O BAR addresses from the controller. Some software gets + // confused if an IDE controller is in compatibility (legacy) mode + // and has PCI I/O resources allocated + // + Status = gBS->HandleProtocol ( + IdeController, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (EFI_ERROR (Status)) { + return ; + } + + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (PciData), &PciData); + if (EFI_ERROR (Status)) { + return ; + } + + // + // Check whether this is IDE + // + if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) || + (PciData.Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) { + return ; + } + + // + // Clear bar for legacy IDE + // + IOBarClear = 0x00; + if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_PNE) == 0) { + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear); + } + if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_SNE) == 0) { + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear); + } + + return ; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c new file mode 100644 index 0000000000..9d84ab0000 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c @@ -0,0 +1,3007 @@ +/** @file + +Copyright (c) 2006 - 2015, Intel 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 "LegacyBiosInterface.h" +#include + +#define PCI_START_ADDRESS(x) (((x) + 0x7ff) & ~0x7ff) + +#define MAX_BRIDGE_INDEX 0x20 +typedef struct { + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + UINT8 PrimaryBus; + UINT8 SecondaryBus; + UINT8 SubordinateBus; +} BRIDGE_TABLE; + +#define ROM_MAX_ENTRIES 24 +BRIDGE_TABLE Bridges[MAX_BRIDGE_INDEX]; +UINTN SortedBridgeIndex[MAX_BRIDGE_INDEX]; +UINTN NumberOfBridges; +LEGACY_PNP_EXPANSION_HEADER *mBasePnpPtr; +UINT16 mBbsRomSegment; +UINTN mHandleCount; +EFI_HANDLE mVgaHandle; +BOOLEAN mIgnoreBbsUpdateFlag; +BOOLEAN mVgaInstallationInProgress = FALSE; +UINT32 mRomCount = 0x00; +ROM_INSTANCE_ENTRY mRomEntry[ROM_MAX_ENTRIES]; + + +/** + Query shadowed legacy ROM parameters registered by RomShadow() previously. + + @param PciHandle PCI device whos ROM has been shadowed + @param DiskStart DiskStart value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom + @param DiskEnd DiskEnd value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom + @param RomShadowAddress Address where ROM was shadowed + @param ShadowedSize Runtime size of ROM + + @retval EFI_SUCCESS Query Logging successful. + @retval EFI_NOT_FOUND No logged data found about PciHandle. + +**/ +EFI_STATUS +GetShadowedRomParameters ( + IN EFI_HANDLE PciHandle, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINTN *ShadowedSize OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + + // + // Get the PCI I/O Protocol on PciHandle + // + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the location of the PCI device + // + PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + + for(Index = 0; Index < mRomCount; Index++) { + if ((mRomEntry[Index].PciSegment == PciSegment) && + (mRomEntry[Index].PciBus == PciBus) && + (mRomEntry[Index].PciDevice == PciDevice) && + (mRomEntry[Index].PciFunction == PciFunction)) { + break; + } + } + + if (Index == mRomCount) { + return EFI_NOT_FOUND; + } + + if (DiskStart != NULL) { + *DiskStart = mRomEntry[Index].DiskStart; + } + + if (DiskEnd != NULL) { + *DiskEnd = mRomEntry[Index].DiskEnd; + } + + if (RomShadowAddress != NULL) { + *RomShadowAddress = (VOID *)(UINTN)mRomEntry[Index].ShadowAddress; + } + + if (ShadowedSize != NULL) { + *ShadowedSize = mRomEntry[Index].ShadowedSize; + } + + return EFI_SUCCESS; +} + +/** + Every legacy ROM that is shadowed by the Legacy BIOS driver will be + registered into this API so that the policy code can know what has + happend + + @param PciHandle PCI device whos ROM is being shadowed + @param ShadowAddress Address that ROM was shadowed + @param ShadowedSize Runtime size of ROM + @param DiskStart DiskStart value from + EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom + @param DiskEnd DiskEnd value from + EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom + + @retval EFI_SUCCESS Logging successful. + @retval EFI_OUT_OF_RESOURCES No remaining room for registering another option + ROM. + +**/ +EFI_STATUS +RomShadow ( + IN EFI_HANDLE PciHandle, + IN UINT32 ShadowAddress, + IN UINT32 ShadowedSize, + IN UINT8 DiskStart, + IN UINT8 DiskEnd + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // See if there is room to register another option ROM + // + if (mRomCount >= ROM_MAX_ENTRIES) { + return EFI_OUT_OF_RESOURCES; + } + // + // Get the PCI I/O Protocol on PciHandle + // + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the location of the PCI device + // + PciIo->GetLocation ( + PciIo, + &mRomEntry[mRomCount].PciSegment, + &mRomEntry[mRomCount].PciBus, + &mRomEntry[mRomCount].PciDevice, + &mRomEntry[mRomCount].PciFunction + ); + mRomEntry[mRomCount].ShadowAddress = ShadowAddress; + mRomEntry[mRomCount].ShadowedSize = ShadowedSize; + mRomEntry[mRomCount].DiskStart = DiskStart; + mRomEntry[mRomCount].DiskEnd = DiskEnd; + + mRomCount++; + + return EFI_SUCCESS; +} + + +/** + Return EFI_SUCCESS if PciHandle has had a legacy BIOS ROM shadowed. This + information represents every call to RomShadow () + + @param PciHandle PCI device to get status for + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_NOT_FOUND No Legacy ROM loaded for this device + +**/ +EFI_STATUS +IsLegacyRom ( + IN EFI_HANDLE PciHandle + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + + // + // Get the PCI I/O Protocol on PciHandle + // + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the location of the PCI device + // + PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + + // + // See if the option ROM from PciHandle has been previously posted + // + for (Index = 0; Index < mRomCount; Index++) { + if (mRomEntry[Index].PciSegment == Segment && + mRomEntry[Index].PciBus == Bus && + mRomEntry[Index].PciDevice == Device && + mRomEntry[Index].PciFunction == Function + ) { + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Find the PC-AT ROM Image in the raw PCI Option ROM. Also return the + related information from the header. + + @param Csm16Revision The PCI interface version of underlying CSM16 + @param VendorId Vendor ID of the PCI device + @param DeviceId Device ID of the PCI device + @param Rom On input pointing to beginning of the raw PCI OpROM + On output pointing to the first legacy PCI OpROM + @param ImageSize On input is the size of Raw PCI Rom + On output is the size of the first legacy PCI ROM + @param MaxRuntimeImageLength The max runtime image length only valid if OpRomRevision >= 3 + @param OpRomRevision Revision of the PCI Rom + @param ConfigUtilityCodeHeader Pointer to Configuration Utility Code Header + + @retval EFI_SUCCESS Successfully find the legacy PCI ROM + @retval EFI_NOT_FOUND Failed to find the legacy PCI ROM + +**/ +EFI_STATUS +GetPciLegacyRom ( + IN UINT16 Csm16Revision, + IN UINT16 VendorId, + IN UINT16 DeviceId, + IN OUT VOID **Rom, + IN OUT UINTN *ImageSize, + OUT UINTN *MaxRuntimeImageLength, OPTIONAL + OUT UINT8 *OpRomRevision, OPTIONAL + OUT VOID **ConfigUtilityCodeHeader OPTIONAL + ) +{ + BOOLEAN Match; + UINT16 *DeviceIdList; + EFI_PCI_ROM_HEADER RomHeader; + PCI_3_0_DATA_STRUCTURE *Pcir; + VOID *BackupImage; + VOID *BestImage; + + + if (*ImageSize < sizeof (EFI_PCI_ROM_HEADER)) { + return EFI_NOT_FOUND; + } + + BestImage = NULL; + BackupImage = NULL; + RomHeader.Raw = *Rom; + while (RomHeader.Generic->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + if (RomHeader.Generic->PcirOffset == 0 || + (RomHeader.Generic->PcirOffset & 3) !=0 || + *ImageSize < RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->PcirOffset + sizeof (PCI_DATA_STRUCTURE)) { + break; + } + + Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset); + // + // Check signature in the PCI Data Structure. + // + if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + break; + } + + if ((UINTN)(RomHeader.Raw - (UINT8 *) *Rom) + Pcir->ImageLength * 512 > *ImageSize) { + break; + } + + if (Pcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) { + Match = FALSE; + if (Pcir->VendorId == VendorId) { + if (Pcir->DeviceId == DeviceId) { + Match = TRUE; + } else if ((Pcir->Revision >= 3) && (Pcir->DeviceListOffset != 0)) { + DeviceIdList = (UINT16 *)(((UINT8 *) Pcir) + Pcir->DeviceListOffset); + // + // Checking the device list + // + while (*DeviceIdList != 0) { + if (*DeviceIdList == DeviceId) { + Match = TRUE; + break; + } + DeviceIdList ++; + } + } + } + + if (Match) { + if (Csm16Revision >= 0x0300) { + // + // Case 1: CSM16 3.0 + // + if (Pcir->Revision >= 3) { + // + // case 1.1: meets OpRom 3.0 + // Perfect!!! + // + BestImage = RomHeader.Raw; + break; + } else { + // + // case 1.2: meets OpRom 2.x + // Store it and try to find the OpRom 3.0 + // + BackupImage = RomHeader.Raw; + } + } else { + // + // Case 2: CSM16 2.x + // + if (Pcir->Revision >= 3) { + // + // case 2.1: meets OpRom 3.0 + // Store it and try to find the OpRom 2.x + // + BackupImage = RomHeader.Raw; + } else { + // + // case 2.2: meets OpRom 2.x + // Perfect!!! + // + BestImage = RomHeader.Raw; + break; + } + } + } else { + DEBUG ((EFI_D_ERROR, "GetPciLegacyRom - OpRom not match (%04x-%04x)\n", (UINTN)VendorId, (UINTN)DeviceId)); + } + } + + if ((Pcir->Indicator & 0x80) == 0x80) { + break; + } else { + RomHeader.Raw += 512 * Pcir->ImageLength; + } + } + + if (BestImage == NULL) { + if (BackupImage == NULL) { + return EFI_NOT_FOUND; + } + // + // The versions of CSM16 and OpRom don't match exactly + // + BestImage = BackupImage; + } + RomHeader.Raw = BestImage; + Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset); + *Rom = BestImage; + *ImageSize = Pcir->ImageLength * 512; + + if (MaxRuntimeImageLength != NULL) { + if (Pcir->Revision < 3) { + *MaxRuntimeImageLength = 0; + } else { + *MaxRuntimeImageLength = Pcir->MaxRuntimeImageLength * 512; + } + } + + if (OpRomRevision != NULL) { + // + // Optional return PCI Data Structure revision + // + if (Pcir->Length >= 0x1C) { + *OpRomRevision = Pcir->Revision; + } else { + *OpRomRevision = 0; + } + } + + if (ConfigUtilityCodeHeader != NULL) { + // + // Optional return ConfigUtilityCodeHeaderOffset supported by the PC-AT ROM + // + if ((Pcir->Revision < 3) || (Pcir->ConfigUtilityCodeHeaderOffset == 0)) { + *ConfigUtilityCodeHeader = NULL; + } else { + *ConfigUtilityCodeHeader = RomHeader.Raw + Pcir->ConfigUtilityCodeHeaderOffset; + } + } + + return EFI_SUCCESS; +} + +/** + Build a table of bridge info for PIRQ translation. + + @param RoutingTable RoutingTable obtained from Platform. + @param RoutingTableEntries Number of RoutingTable entries. + + @retval EFI_SUCCESS New Subordinate bus. + @retval EFI_NOT_FOUND No more Subordinate busses. + +**/ +EFI_STATUS +CreateBridgeTable ( + IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, + IN UINTN RoutingTableEntries + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN BridgeIndex; + UINTN Index; + UINTN Index1; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE01 PciConfigHeader; + BRIDGE_TABLE SlotBridges[MAX_BRIDGE_INDEX]; + UINTN SlotBridgeIndex; + + BridgeIndex = 0x00; + SlotBridgeIndex = 0x00; + + // + // Assumption is table is built from low bus to high bus numbers. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + if (IS_PCI_P2P (&PciConfigHeader) && (BridgeIndex < MAX_BRIDGE_INDEX)) { + PciIo->GetLocation ( + PciIo, + &Bridges[BridgeIndex].PciSegment, + &Bridges[BridgeIndex].PciBus, + &Bridges[BridgeIndex].PciDevice, + &Bridges[BridgeIndex].PciFunction + ); + + Bridges[BridgeIndex].PrimaryBus = PciConfigHeader.Bridge.PrimaryBus; + + Bridges[BridgeIndex].SecondaryBus = PciConfigHeader.Bridge.SecondaryBus; + + Bridges[BridgeIndex].SubordinateBus = PciConfigHeader.Bridge.SubordinateBus; + + for (Index1 = 0; Index1 < RoutingTableEntries; Index1++){ + // + // Test whether we have found the Bridge in the slot, must be the one that directly interfaced to the board + // Once we find one, store it in the SlotBridges[] + // + if ((RoutingTable[Index1].Slot != 0) && (Bridges[BridgeIndex].PrimaryBus == RoutingTable[Index1].Bus) + && ((Bridges[BridgeIndex].PciDevice << 3) == RoutingTable[Index1].Device)) { + CopyMem (&SlotBridges[SlotBridgeIndex], &Bridges[BridgeIndex], sizeof (BRIDGE_TABLE)); + SlotBridgeIndex++; + + break; + } + } + + ++BridgeIndex; + } + } + + // + // Pack up Bridges by removing those useless ones + // + for (Index = 0; Index < BridgeIndex;){ + for (Index1 = 0; Index1 < SlotBridgeIndex; Index1++) { + if (((Bridges[Index].PciBus == SlotBridges[Index1].PrimaryBus) && (Bridges[Index].PciDevice == SlotBridges[Index1].PciDevice)) || + ((Bridges[Index].PciBus >= SlotBridges[Index1].SecondaryBus) && (Bridges[Index].PciBus <= SlotBridges[Index1].SubordinateBus))) { + // + // We have found one that meets our criteria + // + Index++; + break; + } + } + + // + // This one doesn't meet criteria, pack it + // + if (Index1 >= SlotBridgeIndex) { + for (Index1 = Index; BridgeIndex > 1 && Index1 < BridgeIndex - 1 ; Index1++) { + CopyMem (&Bridges[Index1], &Bridges[Index1 + 1], sizeof (BRIDGE_TABLE)); + } + + BridgeIndex--; + } + } + + NumberOfBridges = BridgeIndex; + + // + // Sort bridges low to high by Secondary bus followed by subordinate bus + // + if (NumberOfBridges > 1) { + Index = 0; + do { + SortedBridgeIndex[Index] = Index; + ++Index; + } while (Index < NumberOfBridges); + + for (Index = 0; Index < NumberOfBridges - 1; Index++) { + for (Index1 = Index + 1; Index1 < NumberOfBridges; Index1++) { + if (Bridges[Index].SecondaryBus > Bridges[Index1].SecondaryBus) { + SortedBridgeIndex[Index] = Index1; + SortedBridgeIndex[Index1] = Index; + } + + if ((Bridges[Index].SecondaryBus == Bridges[Index1].SecondaryBus) && + (Bridges[Index].SubordinateBus > Bridges[Index1].SubordinateBus) + ) { + SortedBridgeIndex[Index] = Index1; + SortedBridgeIndex[Index1] = Index; + } + } + } + } + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +/** + Find base Bridge for device. + + @param Private Legacy BIOS Instance data + @param PciBus Input = Bus of device. + @param PciDevice Input = Device. + @param RoutingTable The platform specific routing table + @param RoutingTableEntries Number of entries in table + + @retval EFI_SUCCESS At base bus. + @retval EFI_NOT_FOUND Behind a bridge. + +**/ +EFI_STATUS +GetBaseBus ( + IN LEGACY_BIOS_INSTANCE *Private, + IN UINTN PciBus, + IN UINTN PciDevice, + IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, + IN UINTN RoutingTableEntries + ) +{ + UINTN Index; + for (Index = 0; Index < RoutingTableEntries; Index++) { + if ((RoutingTable[Index].Bus == PciBus) && (RoutingTable[Index].Device == (PciDevice << 3))) { + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Translate PIRQ through busses + + @param Private Legacy BIOS Instance data + @param PciBus Input = Bus of device. Output = Translated Bus + @param PciDevice Input = Device. Output = Translated Device + @param PciFunction Input = Function. Output = Translated Function + @param PirqIndex Input = Original PIRQ index. If single function + device then 0, otherwise 0-3. + Output = Translated Index + + @retval EFI_SUCCESS Pirq successfully translated. + @retval EFI_NOT_FOUND The device is not behind any known bridge. + +**/ +EFI_STATUS +TranslateBusPirq ( + IN LEGACY_BIOS_INSTANCE *Private, + IN OUT UINTN *PciBus, + IN OUT UINTN *PciDevice, + IN OUT UINTN *PciFunction, + IN OUT UINT8 *PirqIndex + ) +{ + /* + This routine traverses the PCI busses from base slot + and translates the PIRQ register to the appropriate one. + + Example: + + Bus 0, Device 1 is PCI-PCI bridge that all PCI slots reside on. + Primary bus# = 0 + Secondary bus # = 1 + Subordinate bus # is highest bus # behind this bus + Bus 1, Device 0 is Slot 0 and is not a bridge. + Bus 1, Device 1 is Slot 1 and is a bridge. + Slot PIRQ routing is A,B,C,D. + Primary bus # = 1 + Secondary bus # = 2 + Subordinate bus # = 5 + Bus 2, Device 6 is a bridge. It has no bridges behind it. + Primary bus # = 2 + Secondary bus # = 3 + Subordinate bus # = 3 + Bridge PIRQ routing is C,D,A,B + Bus 2, Device 7 is a bridge. It has 1 bridge behind it. + Primary bus # = 2 + Secondary bus = 4 Device 6 takes bus 2. + Subordinate bus = 5. + Bridge PIRQ routing is D,A,B,C + Bus 4, Device 2 is a bridge. It has no bridges behind it. + Primary bus # = 4 + Secondary bus # = 5 + Subordinate bus = 5 + Bridge PIRQ routing is B,C,D,A + Bus 5, Device 1 is to be programmed. + Device PIRQ routing is C,D,A,B + + +Search busses starting from slot bus for final bus >= Secondary bus and +final bus <= Suborninate bus. Assumption is bus entries increase in bus +number. +Starting PIRQ is A,B,C,D. +Bus 2, Device 7 satisfies search criteria. Rotate (A,B,C,D) left by device + 7 modulo 4 giving (D,A,B,C). +Bus 4, Device 2 satisfies search criteria. Rotate (D,A,B,C) left by 2 giving + (B,C,D,A). +No other busses match criteria. Device to be programmed is Bus 5, Device 1. +Rotate (B,C,D,A) by 1 giving C,D,A,B. Translated PIRQ is C. + +*/ + UINTN LocalBus; + UINTN LocalDevice; + UINTN BaseBus; + UINTN BaseDevice; + UINTN BaseFunction; + UINT8 LocalPirqIndex; + BOOLEAN BaseIndexFlag; + UINTN BridgeIndex; + UINTN SBridgeIndex; + BaseIndexFlag = FALSE; + BridgeIndex = 0x00; + + LocalPirqIndex = *PirqIndex; + LocalBus = *PciBus; + LocalDevice = *PciDevice; + BaseBus = *PciBus; + BaseDevice = *PciDevice; + BaseFunction = *PciFunction; + + // + // LocalPirqIndex list PIRQs in rotated fashion + // = 0 A,B,C,D + // = 1 B,C,D,A + // = 2 C,D,A,B + // = 3 D,A,B,C + // + + for (BridgeIndex = 0; BridgeIndex < NumberOfBridges; BridgeIndex++) { + SBridgeIndex = SortedBridgeIndex[BridgeIndex]; + // + // Check if device behind this bridge + // + if ((LocalBus >= Bridges[SBridgeIndex].SecondaryBus) && (LocalBus <= Bridges[SBridgeIndex].SubordinateBus)) { + // + // If BaseIndexFlag = FALSE then have found base bridge, i.e + // bridge in slot. Save info for use by IRQ routing table. + // + if (!BaseIndexFlag) { + BaseBus = Bridges[SBridgeIndex].PciBus; + BaseDevice = Bridges[SBridgeIndex].PciDevice; + BaseFunction = Bridges[SBridgeIndex].PciFunction; + BaseIndexFlag = TRUE; + } else { + LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8)Bridges[SBridgeIndex].PciDevice)%4); + } + + // + // Check if at device. If not get new PCI location & PIRQ + // + if (Bridges[SBridgeIndex].SecondaryBus == (UINT8) LocalBus) { + // + // Translate PIRQ + // + LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8) (LocalDevice)) % 4); + break; + } + } + } + + // + // In case we fail to find the Bridge just above us, this is some potential error and we want to warn the user + // + if(BridgeIndex >= NumberOfBridges){ + DEBUG ((EFI_D_ERROR, "Cannot Find IRQ Routing for Bus %d, Device %d, Function %d\n", *PciBus, *PciDevice, *PciFunction)); + } + + *PirqIndex = LocalPirqIndex; + *PciBus = BaseBus; + *PciDevice = BaseDevice; + *PciFunction = BaseFunction; + + return EFI_SUCCESS; +} + + +/** + Copy the $PIR table as required. + + @param Private Legacy BIOS Instance data + @param RoutingTable Pointer to IRQ routing table + @param RoutingTableEntries IRQ routing table entries + @param PirqTable Pointer to $PIR table + @param PirqTableSize Length of table + +**/ +VOID +CopyPirqTable ( + IN LEGACY_BIOS_INSTANCE *Private, + IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, + IN UINTN RoutingTableEntries, + IN EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable, + IN UINTN PirqTableSize + ) +{ + EFI_IA32_REGISTER_SET Regs; + UINT32 Granularity; + + // + // Copy $PIR table, if it exists. + // + if (PirqTable != NULL) { + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + + Private->InternalIrqRoutingTable = RoutingTable; + Private->NumberIrqRoutingEntries = (UINT16) (RoutingTableEntries); + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + Regs.X.AX = Legacy16GetTableAddress; + Regs.X.CX = (UINT16) PirqTableSize; + // + // Allocate at F segment according to PCI IRQ Routing Table Specification + // + Regs.X.BX = (UINT16) 0x1; + // + // 16-byte boundary alignment requirement according to + // PCI IRQ Routing Table Specification + // + Regs.X.DX = 0x10; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + Private->Legacy16Table->IrqRoutingTablePointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + if (Regs.X.AX != 0) { + DEBUG ((EFI_D_ERROR, "PIRQ table length insufficient - %x\n", PirqTableSize)); + } else { + DEBUG ((EFI_D_INFO, "PIRQ table in legacy region - %x\n", Private->Legacy16Table->IrqRoutingTablePointer)); + Private->Legacy16Table->IrqRoutingTableLength = (UINT32)PirqTableSize; + CopyMem ( + (VOID *) (UINTN)Private->Legacy16Table->IrqRoutingTablePointer, + PirqTable, + PirqTableSize + ); + } + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + } + + Private->PciInterruptLine = TRUE; + mHandleCount = 0; +} + +/** + Dump EFI_LEGACY_INSTALL_PCI_HANDLER structure information. + + @param PciHandle The pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure + +**/ +VOID +DumpPciHandle ( + IN EFI_LEGACY_INSTALL_PCI_HANDLER *PciHandle + ) +{ + DEBUG ((EFI_D_INFO, "PciBus - %02x\n", (UINTN)PciHandle->PciBus)); + DEBUG ((EFI_D_INFO, "PciDeviceFun - %02x\n", (UINTN)PciHandle->PciDeviceFun)); + DEBUG ((EFI_D_INFO, "PciSegment - %02x\n", (UINTN)PciHandle->PciSegment)); + DEBUG ((EFI_D_INFO, "PciClass - %02x\n", (UINTN)PciHandle->PciClass)); + DEBUG ((EFI_D_INFO, "PciSubclass - %02x\n", (UINTN)PciHandle->PciSubclass)); + DEBUG ((EFI_D_INFO, "PciInterface - %02x\n", (UINTN)PciHandle->PciInterface)); + + DEBUG ((EFI_D_INFO, "PrimaryIrq - %02x\n", (UINTN)PciHandle->PrimaryIrq)); + DEBUG ((EFI_D_INFO, "PrimaryReserved - %02x\n", (UINTN)PciHandle->PrimaryReserved)); + DEBUG ((EFI_D_INFO, "PrimaryControl - %04x\n", (UINTN)PciHandle->PrimaryControl)); + DEBUG ((EFI_D_INFO, "PrimaryBase - %04x\n", (UINTN)PciHandle->PrimaryBase)); + DEBUG ((EFI_D_INFO, "PrimaryBusMaster - %04x\n", (UINTN)PciHandle->PrimaryBusMaster)); + + DEBUG ((EFI_D_INFO, "SecondaryIrq - %02x\n", (UINTN)PciHandle->SecondaryIrq)); + DEBUG ((EFI_D_INFO, "SecondaryReserved - %02x\n", (UINTN)PciHandle->SecondaryReserved)); + DEBUG ((EFI_D_INFO, "SecondaryControl - %04x\n", (UINTN)PciHandle->SecondaryControl)); + DEBUG ((EFI_D_INFO, "SecondaryBase - %04x\n", (UINTN)PciHandle->SecondaryBase)); + DEBUG ((EFI_D_INFO, "SecondaryBusMaster - %04x\n", (UINTN)PciHandle->SecondaryBusMaster)); + return; +} + +/** + Copy the $PIR table as required. + + @param Private Legacy BIOS Instance data + @param PciIo Pointer to PCI_IO protocol + @param PciIrq Pci IRQ number + @param PciConfigHeader Type00 Pci configuration header + +**/ +VOID +InstallLegacyIrqHandler ( + IN LEGACY_BIOS_INSTANCE *Private, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 PciIrq, + IN PCI_TYPE00 *PciConfigHeader + ) +{ + EFI_IA32_REGISTER_SET Regs; + UINT16 LegMask; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + UINT16 PrimaryMaster; + UINT16 SecondaryMaster; + UINTN TempData; + UINTN RegisterAddress; + UINT32 Granularity; + + PrimaryMaster = 0; + SecondaryMaster = 0; + Legacy8259 = Private->Legacy8259; + // + // Disable interrupt in PIC, in case shared, to prevent an + // interrupt from occuring. + // + Legacy8259->GetMask ( + Legacy8259, + &LegMask, + NULL, + NULL, + NULL + ); + + LegMask = (UINT16) (LegMask | (UINT16) (1 << PciIrq)); + + Legacy8259->SetMask ( + Legacy8259, + &LegMask, + NULL, + NULL, + NULL + ); + + PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + Private->IntThunk->PciHandler.PciBus = (UINT8) PciBus; + Private->IntThunk->PciHandler.PciDeviceFun = (UINT8) ((PciDevice << 3) + PciFunction); + Private->IntThunk->PciHandler.PciSegment = (UINT8) PciSegment; + Private->IntThunk->PciHandler.PciClass = PciConfigHeader->Hdr.ClassCode[2]; + Private->IntThunk->PciHandler.PciSubclass = PciConfigHeader->Hdr.ClassCode[1]; + Private->IntThunk->PciHandler.PciInterface = PciConfigHeader->Hdr.ClassCode[0]; + + // + // Use native mode base address registers in two cases: + // 1. Programming Interface (PI) register indicates Primary Controller is + // in native mode OR + // 2. PCI device Sub Class Code is not IDE + // + Private->IntThunk->PciHandler.PrimaryBusMaster = (UINT16)(PciConfigHeader->Device.Bar[4] & 0xfffc); + if (((PciConfigHeader->Hdr.ClassCode[0] & 0x01) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) { + Private->IntThunk->PciHandler.PrimaryIrq = PciIrq; + Private->IntThunk->PciHandler.PrimaryBase = (UINT16) (PciConfigHeader->Device.Bar[0] & 0xfffc); + Private->IntThunk->PciHandler.PrimaryControl = (UINT16) ((PciConfigHeader->Device.Bar[1] & 0xfffc) + 2); + } else { + Private->IntThunk->PciHandler.PrimaryIrq = 14; + Private->IntThunk->PciHandler.PrimaryBase = 0x1f0; + Private->IntThunk->PciHandler.PrimaryControl = 0x3f6; + } + // + // Secondary controller data + // + if (Private->IntThunk->PciHandler.PrimaryBusMaster != 0) { + Private->IntThunk->PciHandler.SecondaryBusMaster = (UINT16) ((PciConfigHeader->Device.Bar[4] & 0xfffc) + 8); + PrimaryMaster = (UINT16) (Private->IntThunk->PciHandler.PrimaryBusMaster + 2); + SecondaryMaster = (UINT16) (Private->IntThunk->PciHandler.SecondaryBusMaster + 2); + + // + // Clear pending interrupts in Bus Master registers + // + IoWrite16 (PrimaryMaster, 0x04); + IoWrite16 (SecondaryMaster, 0x04); + + } + + // + // Use native mode base address registers in two cases: + // 1. Programming Interface (PI) register indicates Secondary Controller is + // in native mode OR + // 2. PCI device Sub Class Code is not IDE + // + if (((PciConfigHeader->Hdr.ClassCode[0] & 0x04) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) { + Private->IntThunk->PciHandler.SecondaryIrq = PciIrq; + Private->IntThunk->PciHandler.SecondaryBase = (UINT16) (PciConfigHeader->Device.Bar[2] & 0xfffc); + Private->IntThunk->PciHandler.SecondaryControl = (UINT16) ((PciConfigHeader->Device.Bar[3] & 0xfffc) + 2); + } else { + + Private->IntThunk->PciHandler.SecondaryIrq = 15; + Private->IntThunk->PciHandler.SecondaryBase = 0x170; + Private->IntThunk->PciHandler.SecondaryControl = 0x376; + } + + // + // Clear pending interrupts in IDE Command Block Status reg before we + // Thunk to CSM16 below. Don't want a pending Interrupt before we + // install the handlers as wierd corruption would occur and hang system. + // + // + // Read IDE CMD blk status reg to clear out any pending interrupts. + // Do here for Primary and Secondary IDE channels + // + RegisterAddress = (UINT16)Private->IntThunk->PciHandler.PrimaryBase + 0x07; + IoRead8 (RegisterAddress); + RegisterAddress = (UINT16)Private->IntThunk->PciHandler.SecondaryBase + 0x07; + IoRead8 (RegisterAddress); + + Private->IntThunk->PciHandler.PrimaryReserved = 0; + Private->IntThunk->PciHandler.SecondaryReserved = 0; + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + + Regs.X.AX = Legacy16InstallPciHandler; + TempData = (UINTN) &Private->IntThunk->PciHandler; + Regs.X.ES = EFI_SEGMENT ((UINT32) TempData); + Regs.X.BX = EFI_OFFSET ((UINT32) TempData); + + DumpPciHandle (&Private->IntThunk->PciHandler); + + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + +} + + +/** + Program the interrupt routing register in all the PCI devices. On a PC AT system + this register contains the 8259 IRQ vector that matches it's PCI interrupt. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Succeed. + @retval EFI_ALREADY_STARTED All PCI devices have been processed. + +**/ +EFI_STATUS +PciProgramAllInterruptLineRegisters ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + UINT8 InterruptPin; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN MassStorageHandleCount; + EFI_HANDLE *MassStorageHandleBuffer; + UINTN MassStorageHandleIndex; + UINT8 PciIrq; + UINT16 Command; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable; + UINTN RoutingTableEntries; + UINT16 LegMask; + UINT16 LegEdgeLevel; + PCI_TYPE00 PciConfigHeader; + EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable; + UINTN PirqTableSize; + UINTN Flags; + HDD_INFO *HddInfo; + UINT64 Supports; + + // + // Note - This routine use to return immediately if Private->PciInterruptLine + // was true. Routine changed since resets etc can cause not all + // PciIo protocols to be registered the first time through. + // New algorithm is to do the copy $PIR table on first pass and save + // HandleCount on first pass. If subsequent passes LocateHandleBuffer gives + // a larger handle count then proceed with body of function else return + // EFI_ALREADY_STARTED. In addition check if PCI device InterruptLine != 0. + // If zero then function unprogrammed else skip function. + // + Legacy8259 = Private->Legacy8259; + LegacyInterrupt = Private->LegacyInterrupt; + LegacyBiosPlatform = Private->LegacyBiosPlatform; + + LegacyBiosPlatform->GetRoutingTable ( + Private->LegacyBiosPlatform, + (VOID *) &RoutingTable, + &RoutingTableEntries, + (VOID *) &PirqTable, + &PirqTableSize, + NULL, + NULL + ); + CreateBridgeTable (RoutingTable, RoutingTableEntries); + + if (!Private->PciInterruptLine) { + CopyPirqTable ( + Private, + RoutingTable, + RoutingTableEntries, + PirqTable, + PirqTableSize + ); + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + if (HandleCount == mHandleCount) { + FreePool (HandleBuffer); + return EFI_ALREADY_STARTED; + } + + if (mHandleCount == 0x00) { + mHandleCount = HandleCount; + } + + for (Index = 0; Index < HandleCount; Index++) { + // + // If VGA then only do VGA to allow drives fore time to spin up + // otherwise assign PCI IRQs to all potential devices. + // + if ((mVgaInstallationInProgress) && (HandleBuffer[Index] != mVgaHandle)) { + continue; + } else { + // + // Force code to go through all handles next time called if video. + // This will catch case where HandleCount doesn't change but want + // to get drive info etc. + // + mHandleCount = 0x00; + } + + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Test whether the device can be enabled or not. + // If it can't be enabled, then just skip it to avoid further operation. + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + Command = PciConfigHeader.Hdr.Command; + + // + // Note PciIo->Attributes does not program the PCI command register + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x04, 1, &Command); + + if (EFI_ERROR (Status)) { + continue; + } + + InterruptPin = PciConfigHeader.Device.InterruptPin; + + if ((InterruptPin != 0) && (PciConfigHeader.Device.InterruptLine == PCI_INT_LINE_UNKNOWN)) { + PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + // + // Translate PIRQ index back thru busses to slot bus with InterruptPin + // zero based + // + InterruptPin -= 1; + + Status = GetBaseBus ( + Private, + PciBus, + PciDevice, + RoutingTable, + RoutingTableEntries + ); + + if (Status == EFI_NOT_FOUND) { + TranslateBusPirq ( + Private, + &PciBus, + &PciDevice, + &PciFunction, + &InterruptPin + ); + } + // + // Translate InterruptPin(0-3) into PIRQ + // + Status = LegacyBiosPlatform->TranslatePirq ( + LegacyBiosPlatform, + PciBus, + (PciDevice << 3), + PciFunction, + &InterruptPin, + &PciIrq + ); + // + // TranslatePirq() should never fail or we are in trouble + // If it does return failure status, check your PIRQ routing table to see if some item is missing or incorrect + // + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Translate Pirq Failed - Status = %r\n ", Status)); + continue; + } + + LegacyInterrupt->WritePirq ( + LegacyInterrupt, + InterruptPin, + PciIrq + ); + + // + // Check if device has an OPROM associated with it. + // If not invoke special 16-bit function, to allow 16-bit + // code to install an interrupt handler. + // + Status = LegacyBiosCheckPciRom ( + &Private->LegacyBios, + HandleBuffer[Index], + NULL, + NULL, + &Flags + ); + if ((EFI_ERROR (Status)) && (PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE)) { + // + // Device has no OPROM associated with it and is a mass storage + // device. It needs to have an PCI IRQ handler installed. To + // correctly install the handler we need to insure device is + // connected. The device may just have register itself but not + // been connected. Re-read PCI config space after as it can + // change + // + // + // Get IDE Handle. If matches handle then skip ConnectController + // since ConnectController may force native mode and we don't + // want that for primary IDE controller + // + MassStorageHandleCount = 0; + MassStorageHandleBuffer = NULL; + LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &MassStorageHandleBuffer, + &MassStorageHandleCount, + NULL + ); + + HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; + + LegacyBiosBuildIdeData (Private, &HddInfo, 0); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + for (MassStorageHandleIndex = 0; MassStorageHandleIndex < MassStorageHandleCount; MassStorageHandleIndex++) { + if (MassStorageHandleBuffer[MassStorageHandleIndex] == HandleBuffer[Index]) { + // + // InstallLegacyIrqHandler according to Platform requirement + // + InstallLegacyIrqHandler ( + Private, + PciIo, + PciIrq, + &PciConfigHeader + ); + break; + } + } + } + // + // Write InterruptPin and enable 8259. + // + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint8, + 0x3c, + 1, + &PciIrq + ); + Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask = (UINT16) (Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask | (UINT16) (1 << PciIrq)); + + Legacy8259->GetMask ( + Legacy8259, + &LegMask, + &LegEdgeLevel, + NULL, + NULL + ); + + LegMask = (UINT16) (LegMask & (UINT16)~(1 << PciIrq)); + LegEdgeLevel = (UINT16) (LegEdgeLevel | (UINT16) (1 << PciIrq)); + Legacy8259->SetMask ( + Legacy8259, + &LegMask, + &LegEdgeLevel, + NULL, + NULL + ); + } + } + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +/** + Find & verify PnP Expansion header in ROM image + + @param Private Protocol instance pointer. + @param FirstHeader 1 = Find first header, 0 = Find successive headers + @param PnpPtr Input Rom start if FirstHeader =1, Current Header + otherwise Output Next header, if it exists + + @retval EFI_SUCCESS Next Header found at BasePnpPtr + @retval EFI_NOT_FOUND No more headers + +**/ +EFI_STATUS +FindNextPnpExpansionHeader ( + IN LEGACY_BIOS_INSTANCE *Private, + IN BOOLEAN FirstHeader, + IN OUT LEGACY_PNP_EXPANSION_HEADER **PnpPtr + + ) +{ + UINTN TempData; + LEGACY_PNP_EXPANSION_HEADER *LocalPnpPtr; + LocalPnpPtr = *PnpPtr; + if (FirstHeader == FIRST_INSTANCE) { + mBasePnpPtr = LocalPnpPtr; + mBbsRomSegment = (UINT16) ((UINTN) mBasePnpPtr >> 4); + // + // Offset 0x1a gives offset to PnP expansion header for the first + // instance, there after the structure gives the offset to the next + // structure + // + LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) ((UINT8 *) LocalPnpPtr + 0x1a); + TempData = (*((UINT16 *) LocalPnpPtr)); + } else { + TempData = (UINT16) LocalPnpPtr->NextHeader; + } + + LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) (((UINT8 *) mBasePnpPtr + TempData)); + + // + // Search for PnP table in Shadowed ROM + // + *PnpPtr = LocalPnpPtr; + if (*(UINT32 *) LocalPnpPtr == SIGNATURE_32 ('$', 'P', 'n', 'P')) { + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } +} + + +/** + Update list of Bev or BCV table entries. + + @param Private Protocol instance pointer. + @param RomStart Table of ROM start address in RAM/ROM. PciIo _ + Handle to PCI IO for this device + @param PciIo Instance of PCI I/O Protocol + + @retval EFI_SUCCESS Always should succeed. + +**/ +EFI_STATUS +UpdateBevBcvTable ( + IN LEGACY_BIOS_INSTANCE *Private, + IN EFI_LEGACY_EXPANSION_ROM_HEADER *RomStart, + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + VOID *RomEnd; + BBS_TABLE *BbsTable; + UINTN BbsIndex; + EFI_LEGACY_EXPANSION_ROM_HEADER *PciPtr; + LEGACY_PNP_EXPANSION_HEADER *PnpPtr; + BOOLEAN Instance; + EFI_STATUS Status; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + UINT8 Class; + UINT16 DeviceType; + Segment = 0; + Bus = 0; + Device = 0; + Function = 0; + Class = 0; + DeviceType = BBS_UNKNOWN; + + // + // Skip floppy and 2*onboard IDE controller entries(Master/Slave per + // controller). + // + BbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; + + BbsTable = (BBS_TABLE*)(UINTN) Private->IntThunk->EfiToLegacy16BootTable.BbsTable; + PnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) RomStart; + PciPtr = (EFI_LEGACY_EXPANSION_ROM_HEADER *) RomStart; + + RomEnd = (VOID *) (PciPtr->Size512 * 512 + (UINTN) PciPtr); + Instance = FIRST_INSTANCE; + // + // OPROMs like PXE may not be tied to a piece of hardware and thus + // don't have a PciIo associated with them + // + if (PciIo != NULL) { + PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + 0x0b, + 1, + &Class + ); + + if (Class == PCI_CLASS_MASS_STORAGE) { + DeviceType = BBS_HARDDISK; + } else { + if (Class == PCI_CLASS_NETWORK) { + DeviceType = BBS_EMBED_NETWORK; + } + } + } + + while (TRUE) { + Status = FindNextPnpExpansionHeader (Private, Instance, &PnpPtr); + Instance = NOT_FIRST_INSTANCE; + if (EFI_ERROR (Status)) { + break; + } + // + // There can be additional $PnP headers within the OPROM. + // Example: SCSI can have one per drive. + // + BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY; + BbsTable[BbsIndex].DeviceType = DeviceType; + BbsTable[BbsIndex].Bus = (UINT32) Bus; + BbsTable[BbsIndex].Device = (UINT32) Device; + BbsTable[BbsIndex].Function = (UINT32) Function; + BbsTable[BbsIndex].StatusFlags.OldPosition = 0; + BbsTable[BbsIndex].StatusFlags.Reserved1 = 0; + BbsTable[BbsIndex].StatusFlags.Enabled = 0; + BbsTable[BbsIndex].StatusFlags.Failed = 0; + BbsTable[BbsIndex].StatusFlags.MediaPresent = 0; + BbsTable[BbsIndex].StatusFlags.Reserved2 = 0; + BbsTable[BbsIndex].Class = PnpPtr->Class; + BbsTable[BbsIndex].SubClass = PnpPtr->SubClass; + BbsTable[BbsIndex].DescStringOffset = PnpPtr->ProductNamePointer; + BbsTable[BbsIndex].DescStringSegment = mBbsRomSegment; + BbsTable[BbsIndex].MfgStringOffset = PnpPtr->MfgPointer; + BbsTable[BbsIndex].MfgStringSegment = mBbsRomSegment; + BbsTable[BbsIndex].BootHandlerSegment = mBbsRomSegment; + + // + // Have seen case where PXE base code have PnP expansion ROM + // header but no Bcv or Bev vectors. + // + if (PnpPtr->Bcv != 0) { + BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bcv; + ++BbsIndex; + } + + if (PnpPtr->Bev != 0) { + BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bev; + BbsTable[BbsIndex].DeviceType = BBS_BEV_DEVICE; + ++BbsIndex; + } + + if ((PnpPtr == (LEGACY_PNP_EXPANSION_HEADER *) PciPtr) || (PnpPtr > (LEGACY_PNP_EXPANSION_HEADER *) RomEnd)) { + break; + } + } + + BbsTable[BbsIndex].BootPriority = BBS_IGNORE_ENTRY; + Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT32) BbsIndex; + return EFI_SUCCESS; +} + + +/** + Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol + to chose the order. Skip any devices that have already have legacy + BIOS run. + + @param Private Protocol instance pointer. + + @retval EFI_SUCCESS Succeed. + @retval EFI_UNSUPPORTED Cannot get VGA device handle. + +**/ +EFI_STATUS +PciShadowRoms ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_HANDLE VgaHandle; + EFI_HANDLE FirstHandle; + VOID **RomStart; + UINTN Flags; + PCI_TYPE00 PciConfigHeader; + UINT16 *Command; + UINT64 Supports; + + // + // Make the VGA device first + // + Status = Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + VgaHandle = HandleBuffer[0]; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Place the VGA handle as first. + // + for (Index = 0; Index < HandleCount; Index++) { + if (HandleBuffer[Index] == VgaHandle) { + FirstHandle = HandleBuffer[0]; + HandleBuffer[0] = HandleBuffer[Index]; + HandleBuffer[Index] = FirstHandle; + break; + } + } + // + // Allocate memory to save Command WORD from each device. We do this + // to restore devices to same state as EFI after switching to legacy. + // + Command = (UINT16 *) AllocatePool ( + sizeof (UINT16) * (HandleCount + 1) + ); + if (NULL == Command) { + FreePool (HandleBuffer); + return EFI_OUT_OF_RESOURCES; + } + // + // Disconnect all EFI devices first. This covers cases where alegacy BIOS + // may control multiple PCI devices. + // + for (Index = 0; Index < HandleCount; Index++) { + + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Save command register for "connect" loop + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + Command[Index] = PciConfigHeader.Hdr.Command; + // + // Skip any device that already has a legacy ROM run + // + Status = IsLegacyRom (HandleBuffer[Index]); + if (!EFI_ERROR (Status)) { + continue; + } + // + // Stop EFI Drivers with oprom. + // + gBS->DisconnectController ( + HandleBuffer[Index], + NULL, + NULL + ); + } + // + // For every device that has not had a legacy ROM started. Start a legacy ROM. + // + for (Index = 0; Index < HandleCount; Index++) { + + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + + ASSERT_EFI_ERROR (Status); + + // + // Here make sure if one VGA have been shadowed, + // then wil not shadowed another one. + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + + // + // Only one Video OPROM can be given control in BIOS phase. If there are multiple Video devices, + // one will work in legacy mode (OPROM will be given control) and + // other Video devices will work in native mode (OS driver will handle these devices). + // + if (IS_PCI_DISPLAY (&Pci) && Index != 0) { + continue; + } + // + // Skip any device that already has a legacy ROM run + // + Status = IsLegacyRom (HandleBuffer[Index]); + if (!EFI_ERROR (Status)) { + continue; + } + + // + // If legacy VBIOS Oprom has not been dispatched before, install legacy VBIOS here. + // + if (IS_PCI_DISPLAY (&Pci) && Index == 0) { + Status = LegacyBiosInstallVgaRom (Private); + // + // A return status of EFI_NOT_FOUND is considered valid (No EFI + // driver is controlling video). + // + ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)); + continue; + } + + // + // Install legacy ROM + // + Status = LegacyBiosInstallPciRom ( + &Private->LegacyBios, + HandleBuffer[Index], + NULL, + &Flags, + NULL, + NULL, + (VOID **) &RomStart, + NULL + ); + if (EFI_ERROR (Status)) { + if (!((Status == EFI_UNSUPPORTED) && (Flags == NO_ROM))) { + continue; + } + } + // + // Restore Command register so legacy has same devices enabled or disabled + // as EFI. + // If Flags = NO_ROM use command register as is. This covers the + // following cases: + // Device has no ROMs associated with it. + // Device has ROM associated with it but was already + // installed. + // = ROM_FOUND but not VALID_LEGACY_ROM, disable it. + // = ROM_FOUND and VALID_LEGACY_ROM, enable it. + // + if ((Flags & ROM_FOUND) == ROM_FOUND) { + if ((Flags & VALID_LEGACY_ROM) == 0) { + Command[Index] = 0; + } else { + // + // For several VGAs, only one of them can be enabled. + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } + if (!EFI_ERROR (Status)) { + Command[Index] = 0x1f; + } + } + } + + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x04, + 1, + &Command[Index] + ); + } + + FreePool (Command); + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +/** + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will + be loaded + @param RomImage Return the legacy PCI ROM for this device + @param RomSize Size of ROM Image + @param Flags Indicates if ROM found and if PC-AT. + + @retval EFI_SUCCESS Legacy Option ROM availible for this device + @retval EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosCheckPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *Flags + ) +{ + return LegacyBiosCheckPciRomEx ( + This, + PciHandle, + RomImage, + RomSize, + NULL, + Flags, + NULL, + NULL + ); + +} + +/** + + Routine Description: + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param[in] This Protocol instance pointer. + @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded + @param[out] RomImage Return the legacy PCI ROM for this device + @param[out] RomSize Size of ROM Image + @param[out] RuntimeImageLength Runtime size of ROM Image + @param[out] Flags Indicates if ROM found and if PC-AT. + @param[out] OpromRevision Revision of the PCI Rom + @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header + + @return EFI_SUCCESS Legacy Option ROM availible for this device + @return EFI_ALREADY_STARTED This device is already managed by its Oprom + @return EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ +EFI_STATUS +LegacyBiosCheckPciRomEx ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *RuntimeImageLength, OPTIONAL + OUT UINTN *Flags, OPTIONAL + OUT UINT8 *OpromRevision, OPTIONAL + OUT VOID **ConfigUtilityCodeHeader OPTIONAL + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN LocalRomSize; + VOID *LocalRomImage; + PCI_TYPE00 PciConfigHeader; + VOID *LocalConfigUtilityCodeHeader; + + LocalConfigUtilityCodeHeader = NULL; + *Flags = NO_ROM; + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // See if the option ROM for PciHandle has already been executed + // + Status = IsLegacyRom (PciHandle); + if (!EFI_ERROR (Status)) { + *Flags |= (UINTN)(ROM_FOUND | VALID_LEGACY_ROM); + return EFI_SUCCESS; + } + // + // Check for PCI ROM Bar + // + LocalRomSize = (UINTN) PciIo->RomSize; + LocalRomImage = PciIo->RomImage; + if (LocalRomSize != 0) { + *Flags |= ROM_FOUND; + } + + // + // PCI specification states you should check VendorId and Device Id. + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + Status = GetPciLegacyRom ( + Private->Csm16PciInterfaceVersion, + PciConfigHeader.Hdr.VendorId, + PciConfigHeader.Hdr.DeviceId, + &LocalRomImage, + &LocalRomSize, + RuntimeImageLength, + OpromRevision, + &LocalConfigUtilityCodeHeader + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + *Flags |= VALID_LEGACY_ROM; + + // + // See if Configuration Utility Code Header valid + // + if (LocalConfigUtilityCodeHeader != NULL) { + *Flags |= ROM_WITH_CONFIG; + } + + if (ConfigUtilityCodeHeader != NULL) { + *ConfigUtilityCodeHeader = LocalConfigUtilityCodeHeader; + } + + if (RomImage != NULL) { + *RomImage = LocalRomImage; + } + + if (RomSize != NULL) { + *RomSize = LocalRomSize; + } + + return EFI_SUCCESS; +} + +/** + Load a legacy PC-AT OPROM on the PciHandle device. Return information + about how many disks were added by the OPROM and the shadow address and + size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_NOT_FOUND No PS2 Keyboard found + +**/ +EFI_STATUS +EnablePs2Keyboard ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + EFI_ISA_IO_PROTOCOL *IsaIo; + UINTN Index; + + // + // Get SimpleTextIn and find PS2 controller + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextInProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + for (Index = 0; Index < HandleCount; Index++) { + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + NULL, + HandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + // + // Use the ISA I/O Protocol to see if Controller is the Keyboard + // controller + // + if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) { + Status = EFI_UNSUPPORTED; + } + + gBS->CloseProtocol ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + NULL, + HandleBuffer[Index] + ); + } + + if (!EFI_ERROR (Status)) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); + } + } + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +/** + Load a legacy PC-AT OpROM for VGA controller. + + @param Private Driver private data. + + @retval EFI_SUCCESS Legacy ROM successfully installed for this device. + @retval EFI_DEVICE_ERROR No VGA device handle found, or native EFI video + driver cannot be successfully disconnected, or VGA + thunk driver cannot be successfully connected. + +**/ +EFI_STATUS +LegacyBiosInstallVgaRom ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_HANDLE VgaHandle; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_HANDLE *ConnectHandleBuffer; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 PciConfigHeader; + UINT64 Supports; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; + VOID *Interface; + + // + // EfiLegacyBiosGuild attached to a device implies that there is a legacy + // BIOS associated with that device. + // + // There are 3 cases to consider. + // Case 1: No EFI driver is controlling the video. + // Action: Return EFI_SUCCESS from DisconnectController, search + // video thunk driver, and connect it. + // Case 2: EFI driver is controlling the video and EfiLegacyBiosGuid is + // not on the image handle. + // Action: Disconnect EFI driver. + // ConnectController for video thunk + // Case 3: EFI driver is controlling the video and EfiLegacyBiosGuid is + // on the image handle. + // Action: Do nothing and set Private->VgaInstalled = TRUE. + // Then this routine is not called any more. + // + // + // Get the VGA device. + // + Status = Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + VgaHandle = HandleBuffer[0]; + + // + // Check whether video thunk driver already starts. + // + Status = gBS->OpenProtocolInformation ( + VgaHandle, + &gEfiPciIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + Status = gBS->HandleProtocol ( + OpenInfoBuffer[Index].AgentHandle, + &gEfiLegacyBiosGuid, + (VOID **) &Interface + ); + if (!EFI_ERROR (Status)) { + // + // This should be video thunk driver which is managing video device + // So it need not start again + // + DEBUG ((EFI_D_INFO, "Video thunk driver already start! Return!\n")); + Private->VgaInstalled = TRUE; + return EFI_SUCCESS; + } + } + } + + // + // Kick off the native EFI driver + // + Status = gBS->DisconnectController ( + VgaHandle, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + if (Status != EFI_NOT_FOUND) { + return EFI_DEVICE_ERROR; + } else { + return Status; + } + } + // + // Find all the Thunk Driver + // + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLegacyBiosGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + ConnectHandleBuffer = (EFI_HANDLE *) AllocatePool (sizeof (EFI_HANDLE) * (HandleCount + 1)); + ASSERT (ConnectHandleBuffer != NULL); + + CopyMem ( + ConnectHandleBuffer, + HandleBuffer, + sizeof (EFI_HANDLE) * HandleCount + ); + ConnectHandleBuffer[HandleCount] = NULL; + + FreePool (HandleBuffer); + + // + // Enable the device and make sure VGA cycles are being forwarded to this VGA device + // + Status = gBS->HandleProtocol ( + VgaHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &= (UINT64)(EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \ + EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16); + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } + + if (Status == EFI_SUCCESS) { + Private->VgaInstalled = TRUE; + + // + // Attach the VGA thunk driver. + // Assume the video is installed. This prevents potential of infinite recursion. + // + Status = gBS->ConnectController ( + VgaHandle, + ConnectHandleBuffer, + NULL, + TRUE + ); + } + + FreePool (ConnectHandleBuffer); + + if (EFI_ERROR (Status)) { + + Private->VgaInstalled = FALSE; + + // + // Reconnect the EFI VGA driver. + // + gBS->ConnectController (VgaHandle, NULL, NULL, TRUE); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Load a legacy PC-AT OpROM. + + @param This Protocol instance pointer. + @param Private Driver's private data. + @param PciHandle The EFI handle for the PCI device. It could be + NULL if the OpROM image is not associated with + any device. + @param OpromRevision The revision of PCI PC-AT ROM image. + @param RomImage Pointer to PCI PC-AT ROM image header. It must not + be NULL. + @param ImageSize Size of the PCI PC-AT ROM image. + @param RuntimeImageLength On input is the max runtime image length indicated by the PCIR structure + On output is the actual runtime image length + @param DiskStart Disk number of first device hooked by the ROM. If + DiskStart is the same as DiskEnd no disked were + hooked. + @param DiskEnd Disk number of the last device hooked by the ROM. + @param RomShadowAddress Shadow address of PC-AT ROM + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_OUT_OF_RESOURCES No more space for this ROM + +**/ +EFI_STATUS +EFIAPI +LegacyBiosInstallRom ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN LEGACY_BIOS_INSTANCE *Private, + IN EFI_HANDLE PciHandle, + IN UINT8 OpromRevision, + IN VOID *RomImage, + IN UINTN ImageSize, + IN OUT UINTN *RuntimeImageLength, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_STATUS PciEnableStatus; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 LocalDiskStart; + UINT8 LocalDiskEnd; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + EFI_IA32_REGISTER_SET Regs; + UINT8 VideoMode; + EFI_TIME BootTime; + UINT32 *BdaPtr; + UINT32 LocalTime; + UINT32 StartBbsIndex; + UINT32 EndBbsIndex; + UINT32 MaxRomAddr; + UINTN TempData; + UINTN InitAddress; + UINTN RuntimeAddress; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINT32 Granularity; + + PciIo = NULL; + LocalDiskStart = 0; + LocalDiskEnd = 0; + Segment = 0; + Bus = 0; + Device = 0; + Function = 0; + VideoMode = 0; + PhysicalAddress = 0; + MaxRomAddr = PcdGet32 (PcdEndOpromShadowAddress); + + if ((Private->Legacy16Table->TableLength >= OFFSET_OF(EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) && + (Private->Legacy16Table->UmaAddress != 0) && + (Private->Legacy16Table->UmaSize != 0) && + (MaxRomAddr > (Private->Legacy16Table->UmaAddress))) { + MaxRomAddr = Private->Legacy16Table->UmaAddress; + } + + + PciProgramAllInterruptLineRegisters (Private); + + if ((OpromRevision >= 3) && (Private->Csm16PciInterfaceVersion >= 0x0300)) { + // + // CSM16 3.0 meets PCI 3.0 OpROM + // first test if there is enough space for its INIT code + // + PhysicalAddress = CONVENTIONAL_MEMORY_TOP; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesCode, + EFI_SIZE_TO_PAGES (ImageSize), + &PhysicalAddress + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__)); + // + // Report Status Code to indicate that there is no enough space for OpROM + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE) + ); + return EFI_OUT_OF_RESOURCES; + } + InitAddress = (UINTN) PhysicalAddress; + // + // then test if there is enough space for its RT code + // + RuntimeAddress = Private->OptionRom; + if (RuntimeAddress + *RuntimeImageLength > MaxRomAddr) { + DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__)); + gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize)); + // + // Report Status Code to indicate that there is no enough space for OpROM + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE) + ); + return EFI_OUT_OF_RESOURCES; + } + } else { + // CSM16 3.0 meets PCI 2.x OpROM + // CSM16 2.x meets PCI 2.x/3.0 OpROM + // test if there is enough space for its INIT code + // + InitAddress = PCI_START_ADDRESS (Private->OptionRom); + if (InitAddress + ImageSize > MaxRomAddr) { + DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__)); + // + // Report Status Code to indicate that there is no enough space for OpROM + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE) + ); + return EFI_OUT_OF_RESOURCES; + } + + RuntimeAddress = InitAddress; + } + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + (UINT32) RuntimeAddress, + (UINT32) ImageSize, + &Granularity + ); + + DEBUG ((EFI_D_INFO, " Shadowing OpROM init/runtime/isize = %x/%x/%x\n", InitAddress, RuntimeAddress, ImageSize)); + + CopyMem ((VOID *) InitAddress, RomImage, ImageSize); + + // + // Read the highest disk number "installed: and assume a new disk will + // show up on the first drive past the current value. + // There are several considerations here: + // 1. Non-BBS compliant drives will change 40:75 but 16-bit CSM will undo + // the change until boot selection time frame. + // 2. BBS compliants drives will not change 40:75 until boot time. + // 3. Onboard IDE controllers will change 40:75 + // + LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80); + if ((Private->Disk4075 + 0x80) < LocalDiskStart) { + // + // Update table since onboard IDE drives found + // + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = 0xff; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = 0xff; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = 0xff; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = 0xff; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = (UINT8) (Private->Disk4075 + 0x80); + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = LocalDiskStart; + Private->LegacyEfiHddTableIndex ++; + Private->Disk4075 = (UINT8) (LocalDiskStart & 0x7f); + Private->DiskEnd = LocalDiskStart; + } + + if (PciHandle != mVgaHandle) { + + EnablePs2Keyboard (); + + // + // Store current mode settings since PrepareToScanRom may change mode. + // + VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE)); + } + // + // Notify the platform that we are about to scan the ROM + // + Status = Private->LegacyBiosPlatform->PlatformHooks ( + Private->LegacyBiosPlatform, + EfiPlatformHookPrepareToScanRom, + 0, + PciHandle, + &InitAddress, + NULL, + NULL + ); + + // + // If Status returned is EFI_UNSUPPORTED then abort due to platform + // policy. + // + if (Status == EFI_UNSUPPORTED) { + goto Done; + } + + // + // Report corresponding status code + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_CSM_LEGACY_ROM_INIT) + ); + + // + // Generate number of ticks since midnight for BDA. Some OPROMs require + // this. Place result in 40:6C-6F + // + gRT->GetTime (&BootTime, NULL); + LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second; + + // + // Multiply result by 18.2 for number of ticks since midnight. + // Use 182/10 to avoid floating point math. + // + LocalTime = (LocalTime * 182) / 10; + BdaPtr = (UINT32 *) ((UINTN) 0x46C); + *BdaPtr = LocalTime; + + // + // Pass in handoff data + // + PciEnableStatus = EFI_UNSUPPORTED; + ZeroMem (&Regs, sizeof (Regs)); + if (PciHandle != NULL) { + + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Enable command register. + // + PciEnableStatus = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + + PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + DEBUG ((EFI_D_INFO, "Shadowing OpROM on the PCI device %x/%x/%x\n", Bus, Device, Function)); + } + + mIgnoreBbsUpdateFlag = FALSE; + Regs.X.AX = Legacy16DispatchOprom; + + // + // Generate DispatchOpRomTable data + // + Private->IntThunk->DispatchOpromTable.PnPInstallationCheckSegment = Private->Legacy16Table->PnPInstallationCheckSegment; + Private->IntThunk->DispatchOpromTable.PnPInstallationCheckOffset = Private->Legacy16Table->PnPInstallationCheckOffset; + Private->IntThunk->DispatchOpromTable.OpromSegment = (UINT16) (InitAddress >> 4); + Private->IntThunk->DispatchOpromTable.PciBus = (UINT8) Bus; + Private->IntThunk->DispatchOpromTable.PciDeviceFunction = (UINT8) ((Device << 3) | Function); + Private->IntThunk->DispatchOpromTable.NumberBbsEntries = (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; + Private->IntThunk->DispatchOpromTable.BbsTablePointer = (UINT32) (UINTN) Private->BbsTablePtr; + Private->IntThunk->DispatchOpromTable.RuntimeSegment = (UINT16)((OpromRevision < 3) ? 0xffff : (RuntimeAddress >> 4)); + TempData = (UINTN) &Private->IntThunk->DispatchOpromTable; + Regs.X.ES = EFI_SEGMENT ((UINT32) TempData); + Regs.X.BX = EFI_OFFSET ((UINT32) TempData); + // + // Skip dispatching ROM for those PCI devices that can not be enabled by PciIo->Attributes + // Otherwise, it may cause the system to hang in some cases + // + if (!EFI_ERROR (PciEnableStatus)) { + DEBUG ((EFI_D_INFO, " Legacy16DispatchOprom - %02x/%02x/%02x\n", Bus, Device, Function)); + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + } else { + Regs.X.BX = 0; + } + + if (Private->IntThunk->DispatchOpromTable.NumberBbsEntries != (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries) { + Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT8) Private->IntThunk->DispatchOpromTable.NumberBbsEntries; + mIgnoreBbsUpdateFlag = TRUE; + } + // + // Check if non-BBS compliant drives found + // + if (Regs.X.BX != 0) { + LocalDiskEnd = (UINT8) (LocalDiskStart + Regs.H.BL); + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = (UINT8) Segment; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = (UINT8) Bus; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = (UINT8) Device; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = (UINT8) Function; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = Private->DiskEnd; + Private->DiskEnd = LocalDiskEnd; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd; + Private->LegacyEfiHddTableIndex += 1; + } + // + // Skip video mode set, if installing VGA + // + if (PciHandle != mVgaHandle) { + // + // Set mode settings since PrepareToScanRom may change mode + // + if (VideoMode != *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE))) { + // + // The active video mode is changed, restore it to original mode. + // + Regs.H.AH = 0x00; + Regs.H.AL = VideoMode; + Private->LegacyBios.Int86 (&Private->LegacyBios, 0x10, &Regs); + } + } + // + // Regs.X.AX from the adapter initializion is ignored since some adapters + // do not follow the standard of setting AX = 0 on success. + // + // + // The ROM could have updated it's size so we need to read again. + // + if (((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + // + // Now we check the signature (0xaa55) to judge whether the run-time code is truly generated by INIT function. + // If signature is not valid, that means the INIT function didn't copy the run-time code to RuntimeAddress. + // + *RuntimeImageLength = 0; + } else { + *RuntimeImageLength = ((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Size512 * 512; + } + + DEBUG ((EFI_D_INFO, " fsize = %x\n", *RuntimeImageLength)); + + // + // If OpROM runs in 2.0 mode + // + if (PhysicalAddress == 0) { + if (*RuntimeImageLength < ImageSize) { + // + // Make area from end of shadowed rom to end of original rom all ffs + // + gBS->SetMem ((VOID *) (InitAddress + *RuntimeImageLength), ImageSize - *RuntimeImageLength, 0xff); + } + } + + LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80); + + // + // Allow platform to perform any required actions after the + // OPROM has been initialized. + // + Status = Private->LegacyBiosPlatform->PlatformHooks ( + Private->LegacyBiosPlatform, + EfiPlatformHookAfterRomInit, + 0, + PciHandle, + &RuntimeAddress, + NULL, + NULL + ); + if (PciHandle != NULL) { + // + // If no PCI Handle then no header or Bevs. + // + if ((*RuntimeImageLength != 0) && (!mIgnoreBbsUpdateFlag)) { + StartBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; + TempData = RuntimeAddress; + UpdateBevBcvTable ( + Private, + (EFI_LEGACY_EXPANSION_ROM_HEADER *) TempData, + PciIo + ); + EndBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; + LocalDiskEnd = (UINT8) (LocalDiskStart + (UINT8) (EndBbsIndex - StartBbsIndex)); + if (LocalDiskEnd != LocalDiskStart) { + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = (UINT8) Segment; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = (UINT8) Bus; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = (UINT8) Device; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = (UINT8) Function; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = Private->DiskEnd; + Private->DiskEnd = LocalDiskEnd; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd; + Private->LegacyEfiHddTableIndex += 1; + } + } + // + // Mark PCI device as having a legacy BIOS ROM loaded. + // + RomShadow ( + PciHandle, + (UINT32) RuntimeAddress, + (UINT32) *RuntimeImageLength, + LocalDiskStart, + LocalDiskEnd + ); + } + + // + // Stuff caller's OPTIONAL return parameters. + // + if (RomShadowAddress != NULL) { + *RomShadowAddress = (VOID *) RuntimeAddress; + } + + if (DiskStart != NULL) { + *DiskStart = LocalDiskStart; + } + + if (DiskEnd != NULL) { + *DiskEnd = LocalDiskEnd; + } + + Private->OptionRom = (UINT32) (RuntimeAddress + *RuntimeImageLength); + + Status = EFI_SUCCESS; + +Done: + if (PhysicalAddress != 0) { + // + // Free pages when OpROM is 3.0 + // + gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize)); + } + + // + // Insure all shadowed areas are locked + // + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xC0000, + 0x40000, + &Granularity + ); + + return Status; +} + +/** + Load a legacy PC-AT OPROM on the PciHandle device. Return information + about how many disks were added by the OPROM and the shadow address and + size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will + be loaded. This value is NULL if RomImage is + non-NULL. This is the normal case. + @param RomImage A PCI PC-AT ROM image. This argument is non-NULL + if there is no hardware associated with the ROM + and thus no PciHandle, otherwise is must be NULL. + Example is PXE base code. + @param Flags Indicates if ROM found and if PC-AT. + @param DiskStart Disk number of first device hooked by the ROM. If + DiskStart is the same as DiskEnd no disked were + hooked. + @param DiskEnd Disk number of the last device hooked by the ROM. + @param RomShadowAddress Shadow address of PC-AT ROM + @param RomShadowedSize Size of RomShadowAddress in bytes + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_INVALID_PARAMETER PciHandle not found + @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no onboard + ROM + +**/ +EFI_STATUS +EFIAPI +LegacyBiosInstallPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL * This, + IN EFI_HANDLE PciHandle, + IN VOID **RomImage, + OUT UINTN *Flags, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINT32 *RomShadowedSize OPTIONAL + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + VOID *LocalRomImage; + UINTN ImageSize; + UINTN RuntimeImageLength; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE01 PciConfigHeader; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + UINTN LastBus; + UINTN Index; + UINT8 OpromRevision; + UINT32 Granularity; + PCI_3_0_DATA_STRUCTURE *Pcir; + + OpromRevision = 0; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + if (Private->Legacy16Table->LastPciBus == 0) { + // + // Get last bus number if not already found + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + LastBus = 0; + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + Status = PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + if (PciBus > LastBus) { + LastBus = PciBus; + } + } + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + Private->Legacy16Table->LastPciBus = (UINT8) LastBus; + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + } + + *Flags = 0; + if ((PciHandle != NULL) && (RomImage == NULL)) { + // + // If PciHandle has OpRom to Execute + // and OpRom are all associated with Hardware + // + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + + if (!EFI_ERROR (Status)) { + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + // + // if video installed & OPROM is video return + // + if ( + ( + ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_OLD) && + (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA)) + || + ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY) && + (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA)) + ) + && + (!Private->VgaInstalled) + ) { + mVgaInstallationInProgress = TRUE; + + // + // return EFI_UNSUPPORTED; + // + } + } + // + // To run any legacy image, the VGA needs to be installed first. + // if installing the video, then don't need the thunk as already installed. + // + Status = Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + + if (!EFI_ERROR (Status)) { + mVgaHandle = HandleBuffer[0]; + if ((!Private->VgaInstalled) && (PciHandle != mVgaHandle)) { + // + // A return status of EFI_NOT_FOUND is considered valid (No EFI + // driver is controlling video. + // + mVgaInstallationInProgress = TRUE; + Status = LegacyBiosInstallVgaRom (Private); + if (EFI_ERROR (Status)) { + if (Status != EFI_NOT_FOUND) { + mVgaInstallationInProgress = FALSE; + return Status; + } + } else { + mVgaInstallationInProgress = FALSE; + } + } + } + // + // See if the option ROM for PciHandle has already been executed + // + Status = IsLegacyRom (PciHandle); + + if (!EFI_ERROR (Status)) { + mVgaInstallationInProgress = FALSE; + GetShadowedRomParameters ( + PciHandle, + DiskStart, + DiskEnd, + RomShadowAddress, + (UINTN *) RomShadowedSize + ); + return EFI_SUCCESS; + } + + Status = LegacyBiosCheckPciRomEx ( + &Private->LegacyBios, + PciHandle, + &LocalRomImage, + &ImageSize, + &RuntimeImageLength, + Flags, + &OpromRevision, + NULL + ); + if (EFI_ERROR (Status)) { + // + // There is no PCI ROM in the ROM BAR or no onboard ROM + // + mVgaInstallationInProgress = FALSE; + return EFI_UNSUPPORTED; + } + } else { + if ((RomImage == NULL) || (*RomImage == NULL)) { + // + // If PciHandle is NULL, and no OpRom is to be associated + // + mVgaInstallationInProgress = FALSE; + return EFI_UNSUPPORTED; + } + + Status = Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if ((!EFI_ERROR (Status)) && (!Private->VgaInstalled)) { + // + // A return status of EFI_NOT_FOUND is considered valid (No EFI + // driver is controlling video. + // + mVgaInstallationInProgress = TRUE; + Status = LegacyBiosInstallVgaRom (Private); + if (EFI_ERROR (Status)) { + if (Status != EFI_NOT_FOUND) { + mVgaInstallationInProgress = FALSE; + return Status; + } + } else { + mVgaInstallationInProgress = FALSE; + } + } + + LocalRomImage = *RomImage; + if (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE || + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset == 0 || + (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset & 3 ) != 0) { + mVgaInstallationInProgress = FALSE; + return EFI_UNSUPPORTED; + } + + Pcir = (PCI_3_0_DATA_STRUCTURE *) + ((UINT8 *) LocalRomImage + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset); + + if ((Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) || (Pcir->CodeType != PCI_CODE_TYPE_PCAT_IMAGE)) { + mVgaInstallationInProgress = FALSE; + return EFI_UNSUPPORTED; + } + + ImageSize = Pcir->ImageLength * 512; + if (Pcir->Length >= 0x1C) { + OpromRevision = Pcir->Revision; + } else { + OpromRevision = 0; + } + if (Pcir->Revision < 3) { + RuntimeImageLength = 0; + } else { + RuntimeImageLength = Pcir->MaxRuntimeImageLength * 512; + } + } + // + // Shadow and initialize the OpROM. + // + ASSERT (Private->TraceIndex < 0x200); + Private->Trace[Private->TraceIndex] = LEGACY_PCI_TRACE_000; + Private->TraceIndex ++; + Private->TraceIndex = (UINT16) (Private->TraceIndex % 0x200); + Status = LegacyBiosInstallRom ( + This, + Private, + PciHandle, + OpromRevision, + LocalRomImage, + ImageSize, + &RuntimeImageLength, + DiskStart, + DiskEnd, + RomShadowAddress + ); + if (RomShadowedSize != NULL) { + *RomShadowedSize = (UINT32) RuntimeImageLength; + } + + mVgaInstallationInProgress = FALSE; + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c new file mode 100644 index 0000000000..f82121c607 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c @@ -0,0 +1,234 @@ +/** @file + Collect Sio information from Native EFI Drivers. + Sio is floppy, parallel, serial, ... hardware + +Copyright (c) 2006 - 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 "LegacyBiosInterface.h" + + +/** + Collect EFI Info about legacy devices. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildSioData ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + DEVICE_PRODUCER_DATA_HEADER *SioPtr; + DEVICE_PRODUCER_SERIAL *Sio1Ptr; + DEVICE_PRODUCER_PARALLEL *Sio2Ptr; + DEVICE_PRODUCER_FLOPPY *Sio3Ptr; + EFI_HANDLE IsaBusController; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + UINTN ResourceIndex; + UINTN ChildIndex; + EFI_ISA_IO_PROTOCOL *IsaIo; + EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; + EFI_ISA_ACPI_RESOURCE *IoResource; + EFI_ISA_ACPI_RESOURCE *DmaResource; + EFI_ISA_ACPI_RESOURCE *InterruptResource; + UINTN EntryCount; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + // + // Get the pointer to the SIO data structure + // + SioPtr = &Private->IntThunk->EfiToLegacy16BootTable.SioData; + + // + // Zero the data in the SIO data structure + // + gBS->SetMem (SioPtr, sizeof (DEVICE_PRODUCER_DATA_HEADER), 0); + + // + // Find the ISA Bus Controller used for legacy + // + Status = Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIsaBusHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + IsaBusController = HandleBuffer[0]; + if (!EFI_ERROR (Status)) { + // + // Force ISA Bus Controller to produce all ISA devices + // + gBS->ConnectController (IsaBusController, NULL, NULL, TRUE); + } + // + // Get the list of ISA controllers in the system + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIsaIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + // + // Collect legacy information from each of the ISA controllers in the system + // + for (Index = 0; Index < HandleCount; Index++) { + + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo); + if (EFI_ERROR (Status)) { + continue; + } + + ResourceList = IsaIo->ResourceList; + + if (ResourceList == NULL) { + continue; + } + // + // Collect the resource types neededto fill in the SIO data structure + // + IoResource = NULL; + DmaResource = NULL; + InterruptResource = NULL; + for (ResourceIndex = 0; + ResourceList->ResourceItem[ResourceIndex].Type != EfiIsaAcpiResourceEndOfList; + ResourceIndex++ + ) { + switch (ResourceList->ResourceItem[ResourceIndex].Type) { + case EfiIsaAcpiResourceIo: + IoResource = &ResourceList->ResourceItem[ResourceIndex]; + break; + + case EfiIsaAcpiResourceMemory: + break; + + case EfiIsaAcpiResourceDma: + DmaResource = &ResourceList->ResourceItem[ResourceIndex]; + break; + + case EfiIsaAcpiResourceInterrupt: + InterruptResource = &ResourceList->ResourceItem[ResourceIndex]; + break; + + default: + break; + } + } + // + // See if this is an ISA serial port + // + // Ignore DMA resource since it is always returned NULL + // + if (ResourceList->Device.HID == EISA_PNP_ID (0x500) || ResourceList->Device.HID == EISA_PNP_ID (0x501)) { + + if (ResourceList->Device.UID <= 3 && + IoResource != NULL && + InterruptResource != NULL + ) { + // + // Get the handle of the child device that has opened the ISA I/O Protocol + // + Status = gBS->OpenProtocolInformation ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + continue; + } + // + // We want resource for legacy even if no 32-bit driver installed + // + for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) { + Sio1Ptr = &SioPtr->Serial[ResourceList->Device.UID]; + Sio1Ptr->Address = (UINT16) IoResource->StartRange; + Sio1Ptr->Irq = (UINT8) InterruptResource->StartRange; + Sio1Ptr->Mode = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF; + } + + FreePool (OpenInfoBuffer); + } + } + // + // See if this is an ISA parallel port + // + // Ignore DMA resource since it is always returned NULL, port + // only used in output mode. + // + if (ResourceList->Device.HID == EISA_PNP_ID (0x400) || ResourceList->Device.HID == EISA_PNP_ID (0x401)) { + if (ResourceList->Device.UID <= 2 && + IoResource != NULL && + InterruptResource != NULL && + DmaResource != NULL + ) { + Sio2Ptr = &SioPtr->Parallel[ResourceList->Device.UID]; + Sio2Ptr->Address = (UINT16) IoResource->StartRange; + Sio2Ptr->Irq = (UINT8) InterruptResource->StartRange; + Sio2Ptr->Dma = (UINT8) DmaResource->StartRange; + Sio2Ptr->Mode = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY; + } + } + // + // See if this is an ISA floppy controller + // + if (ResourceList->Device.HID == EISA_PNP_ID (0x604)) { + if (IoResource != NULL && InterruptResource != NULL && DmaResource != NULL) { + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); + if (!EFI_ERROR (Status)) { + Sio3Ptr = &SioPtr->Floppy; + Sio3Ptr->Address = (UINT16) IoResource->StartRange; + Sio3Ptr->Irq = (UINT8) InterruptResource->StartRange; + Sio3Ptr->Dma = (UINT8) DmaResource->StartRange; + Sio3Ptr->NumberOfFloppy++; + } + } + } + // + // See if this is a mouse + // Always set mouse found so USB hot plug will work + // + // Ignore lower byte of HID. Pnp0fxx is any type of mouse. + // + // Hid = ResourceList->Device.HID & 0xff00ffff; + // PnpId = EISA_PNP_ID(0x0f00); + // if (Hid == PnpId) { + // if (ResourceList->Device.UID == 1) { + // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer); + // if (!EFI_ERROR (Status)) { + // + SioPtr->MousePresent = 0x01; + // + // } + // } + // } + // + } + + FreePool (HandleBuffer); + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c new file mode 100644 index 0000000000..3d9a8b9649 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c @@ -0,0 +1,419 @@ +/** @file + Call into 16-bit BIOS code, Use AsmThunk16 function of BaseLib. + +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 "LegacyBiosInterface.h" + +THUNK_CONTEXT mThunkContext; + +/** + Sets the counter value for Timer #0 in a legacy 8254 timer. + + @param Count - The 16-bit counter value to program into Timer #0 of the legacy 8254 timer. + +**/ +VOID +SetPitCount ( + IN UINT16 Count + ) +{ + IoWrite8 (TIMER_CONTROL_PORT, TIMER0_CONTROL_WORD); + IoWrite8 (TIMER0_COUNT_PORT, (UINT8) (Count & 0xFF)); + IoWrite8 (TIMER0_COUNT_PORT, (UINT8) ((Count>>8) & 0xFF)); +} + +/** + Thunk to 16-bit real mode and execute a software interrupt with a vector + of BiosInt. Regs will contain the 16-bit register context on entry and + exit. + + @param This Protocol instance pointer. + @param BiosInt Processor interrupt vector to invoke + @param Regs Register contexted passed into (and returned) from thunk to + 16-bit mode + + @retval FALSE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN EFI_IA32_REGISTER_SET *Regs + ) +{ + UINT32 *VectorBase; + + Regs->X.Flags.Reserved1 = 1; + Regs->X.Flags.Reserved2 = 0; + Regs->X.Flags.Reserved3 = 0; + Regs->X.Flags.Reserved4 = 0; + Regs->X.Flags.IOPL = 3; + Regs->X.Flags.NT = 0; + Regs->X.Flags.IF = 0; + Regs->X.Flags.TF = 0; + Regs->X.Flags.CF = 0; + // + // The base address of legacy interrupt vector table is 0. + // We use this base address to get the legacy interrupt handler. + // + VectorBase = 0; + + return InternalLegacyBiosFarCall ( + This, + (UINT16) ((VectorBase)[BiosInt] >> 16), + (UINT16) (VectorBase)[BiosInt], + Regs, + &Regs->X.Flags, + sizeof (Regs->X.Flags) + ); +} + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and returned) from + thunk to 16-bit mode + @param Stack Caller allocated stack used to pass arguments + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS errors in + the target code. See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosFarCall86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ) +{ + Regs->X.Flags.Reserved1 = 1; + Regs->X.Flags.Reserved2 = 0; + Regs->X.Flags.Reserved3 = 0; + Regs->X.Flags.Reserved4 = 0; + Regs->X.Flags.IOPL = 3; + Regs->X.Flags.NT = 0; + Regs->X.Flags.IF = 1; + Regs->X.Flags.TF = 0; + Regs->X.Flags.CF = 0; + + return InternalLegacyBiosFarCall (This, Segment, Offset, Regs, Stack, StackSize); +} + +/** + Provide NULL interrupt handler which is used to check + if there is more than one HW interrupt registers with the CPU AP. + + @param InterruptType - The type of interrupt that occured + @param SystemContext - A pointer to the system context when the interrupt occured + +**/ +VOID +EFIAPI +LegacyBiosNullInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ +} + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and returned) from thunk to + 16-bit mode + @param Stack Caller allocated stack used to pass arguments + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +InternalLegacyBiosFarCall ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ) +{ + UINTN Status; + LEGACY_BIOS_INSTANCE *Private; + UINT16 *Stack16; + EFI_TPL OriginalTpl; + IA32_REGISTER_SET ThunkRegSet; + BOOLEAN InterruptState; + UINT64 TimerPeriod; + + Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); + + ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet)); + ThunkRegSet.X.DI = Regs->X.DI; + ThunkRegSet.X.SI = Regs->X.SI; + ThunkRegSet.X.BP = Regs->X.BP; + ThunkRegSet.X.BX = Regs->X.BX; + ThunkRegSet.X.DX = Regs->X.DX; + // + // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, AX = B10Dh is + // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to write. + // + ThunkRegSet.E.ECX = Regs->E.ECX; + ThunkRegSet.X.AX = Regs->X.AX; + ThunkRegSet.E.DS = Regs->X.DS; + ThunkRegSet.E.ES = Regs->X.ES; + + CopyMem (&(ThunkRegSet.E.EFLAGS.UintN), &(Regs->X.Flags), sizeof (Regs->X.Flags)); + + // + // Clear the error flag; thunk code may set it. Stack16 should be the high address + // Make Statk16 address the low 16 bit must be not zero. + // + Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16)); + + // + // Save current rate of DXE Timer + // + Private->Timer->GetTimerPeriod (Private->Timer, &TimerPeriod); + + // + // Disable DXE Timer while executing in real mode + // + Private->Timer->SetTimerPeriod (Private->Timer, 0); + + // + // Save and disable interrupt of debug timer + // + InterruptState = SaveAndSetDebugTimerInterrupt (FALSE); + + // + // The call to Legacy16 is a critical section to EFI + // + OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + // + // Check to see if there is more than one HW interrupt registers with the CPU AP. + // If there is, then ASSERT() since that is not compatible with the CSM because + // interupts other than the Timer interrupt that was disabled above can not be + // handled properly from real mode. + // + DEBUG_CODE ( + UINTN Vector; + UINTN Count; + + for (Vector = 0x20, Count = 0; Vector < 0x100; Vector++) { + Status = Private->Cpu->RegisterInterruptHandler (Private->Cpu, Vector, LegacyBiosNullInterruptHandler); + if (Status == EFI_ALREADY_STARTED) { + Count++; + } + if (Status == EFI_SUCCESS) { + Private->Cpu->RegisterInterruptHandler (Private->Cpu, Vector, NULL); + } + } + if (Count >= 2) { + DEBUG ((EFI_D_ERROR, "ERROR: More than one HW interrupt active with CSM enabled\n")); + } + ASSERT (Count < 2); + ); + + // + // If the Timer AP has enabled the 8254 timer IRQ and the current 8254 timer + // period is less than the CSM required rate of 54.9254, then force the 8254 + // PIT counter to 0, which is the CSM required rate of 54.9254 ms + // + if (Private->TimerUses8254 && TimerPeriod < 549254) { + SetPitCount (0); + } + + if (Stack != NULL && StackSize != 0) { + // + // Copy Stack to low memory stack + // + Stack16 -= StackSize / sizeof (UINT16); + CopyMem (Stack16, Stack, StackSize); + } + + ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12); + ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16; + ThunkRegSet.E.CS = Segment; + ThunkRegSet.E.Eip = Offset; + + mThunkContext.RealModeState = &ThunkRegSet; + + // + // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. + // + Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + AsmThunk16 (&mThunkContext); + + // + // OPROM may allocate EBDA range by itself and change EBDA base and EBDA size. + // Get the current EBDA base address, and compared with pre-allocate minimum + // EBDA base address, if the current EBDA base address is smaller, it indicates + // PcdEbdaReservedMemorySize should be adjusted to larger for more OPROMs. + // + DEBUG_CODE ( + { + UINTN EbdaBaseAddress; + UINTN ReservedEbdaBaseAddress; + + EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4; + ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize); + ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress); + } + ); + + if (Stack != NULL && StackSize != 0) { + // + // Copy low memory stack to Stack + // + CopyMem (Stack, Stack16, StackSize); + } + + // + // Restore protected mode interrupt state + // + Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + mThunkContext.RealModeState = NULL; + + // + // Enable and restore rate of DXE Timer + // + Private->Timer->SetTimerPeriod (Private->Timer, TimerPeriod); + + // + // End critical section + // + gBS->RestoreTPL (OriginalTpl); + + // + // Restore interrupt of debug timer + // + SaveAndSetDebugTimerInterrupt (InterruptState); + + Regs->E.EDI = ThunkRegSet.E.EDI; + Regs->E.ESI = ThunkRegSet.E.ESI; + Regs->E.EBP = ThunkRegSet.E.EBP; + Regs->E.EBX = ThunkRegSet.E.EBX; + Regs->E.EDX = ThunkRegSet.E.EDX; + Regs->E.ECX = ThunkRegSet.E.ECX; + Regs->E.EAX = ThunkRegSet.E.EAX; + Regs->X.SS = ThunkRegSet.E.SS; + Regs->X.CS = ThunkRegSet.E.CS; + Regs->X.DS = ThunkRegSet.E.DS; + Regs->X.ES = ThunkRegSet.E.ES; + + CopyMem (&(Regs->X.Flags), &(ThunkRegSet.E.EFLAGS.UintN), sizeof (Regs->X.Flags)); + + return (BOOLEAN) (Regs->X.Flags.CF == 1); +} + +/** + Allocate memory < 1 MB and copy the thunker code into low memory. Se up + all the descriptors. + + @param Private Private context for Legacy BIOS + + @retval EFI_SUCCESS Should only pass. + +**/ +EFI_STATUS +LegacyBiosInitializeThunk ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemoryAddress; + UINT8 TimerVector; + + MemoryAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->IntThunk; + + mThunkContext.RealModeBuffer = (VOID *) (UINTN) (MemoryAddress + ((sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE); + mThunkContext.RealModeBufferSize = EFI_PAGE_SIZE; + mThunkContext.ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE | THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15; + + AsmPrepareThunk16 (&mThunkContext); + + // + // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver + // + TimerVector = 0; + Status = Private->Legacy8259->GetVector (Private->Legacy8259, Efi8259Irq0, &TimerVector); + ASSERT_EFI_ERROR (Status); + + // + // Check to see if the Timer AP has hooked the IRQ0 from the 8254 PIT + // + Status = Private->Cpu->RegisterInterruptHandler ( + Private->Cpu, + TimerVector, + LegacyBiosNullInterruptHandler + ); + if (Status == EFI_SUCCESS) { + // + // If the Timer AP has not enabled the 8254 timer IRQ, then force the 8254 PIT + // counter to 0, which is the CSM required rate of 54.9254 ms + // + Private->Cpu->RegisterInterruptHandler ( + Private->Cpu, + TimerVector, + NULL + ); + SetPitCount (0); + + // + // Save status that the Timer AP is not using the 8254 PIT + // + Private->TimerUses8254 = FALSE; + } else if (Status == EFI_ALREADY_STARTED) { + // + // Save status that the Timer AP is using the 8254 PIT + // + Private->TimerUses8254 = TRUE; + } else { + // + // Unexpected status from CPU AP RegisterInterruptHandler() + // + ASSERT (FALSE); + } + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.S b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.S new file mode 100644 index 0000000000..0c9ce01d5b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.S @@ -0,0 +1,72 @@ +## @file +# Interrupt Redirection Template +# +# Copyright (c) 2006, Intel 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. +# +## + +#text SEGMENT + + +#---------------------------------------------------------------------------- +# Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F +# +# Input: None +# +# Output: None +# +# Prototype: VOID +# InterruptRedirectionTemplate ( +# VOID +# ); +# +# Saves: None +# +# Modified: None +# +# Description: Contains the code that is copied into low memory (below 640K). +# This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. +# This template must be copied into low memory, and the IDT entries +# 0x68-0x6F must be point to the low memory copy of this code. Each +# entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily +# computed. +# +#---------------------------------------------------------------------------- + +ASM_GLOBAL ASM_PFX(InterruptRedirectionTemplate) +ASM_PFX(InterruptRedirectionTemplate): + int $0x08 + .byte 0x0cf # IRET + nop + int $0x09 + .byte 0x0cf # IRET + nop + int $0x0a + .byte 0x0cf # IRET + nop + int $0x0b + .byte 0x0cf # IRET + nop + int $0x0c + .byte 0x0cf # IRET + nop + int $0x0d + .byte 0x0cf # IRET + nop + int $0x0e + .byte 0x0cf # IRET + nop + int $0x0f + .byte 0x0cf # IRET + nop + +#END diff --git a/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.asm b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.asm new file mode 100644 index 0000000000..750423e5b7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.asm @@ -0,0 +1,71 @@ +;; @file +; Interrupt Redirection Template +; +; Copyright (c) 2006, Intel 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. +; +;; + +text SEGMENT + +;---------------------------------------------------------------------------- +; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F +; +; Input: None +; +; Output: None +; +; Prototype: VOID +; InterruptRedirectionTemplate ( +; VOID +; ); +; +; Saves: None +; +; Modified: None +; +; Description: Contains the code that is copied into low memory (below 640K). +; This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. +; This template must be copied into low memory, and the IDT entries +; 0x68-0x6F must be point to the low memory copy of this code. Each +; entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily +; computed. +; +;---------------------------------------------------------------------------- + +InterruptRedirectionTemplate PROC + int 08h + DB 0cfh ; IRET + nop + int 09h + DB 0cfh ; IRET + nop + int 0ah + DB 0cfh ; IRET + nop + int 0bh + DB 0cfh ; IRET + nop + int 0ch + DB 0cfh ; IRET + nop + int 0dh + DB 0cfh ; IRET + nop + int 0eh + DB 0cfh ; IRET + nop + int 0fh + DB 0cfh ; IRET + nop +InterruptRedirectionTemplate ENDP + +END \ No newline at end of file diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/AcpiVariableCompatibility.h b/Core/IntelFrameworkModulePkg/Include/Guid/AcpiVariableCompatibility.h new file mode 100644 index 0000000000..6c9f851543 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/AcpiVariableCompatibility.h @@ -0,0 +1,69 @@ +/** @file + Definitions for data structures used in S3 resume. + +Copyright (c) 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 _ACPI_VARIABLE_COMPATIBILITY_H_ +#define _ACPI_VARIABLE_COMPATIBILITY_H_ + +#define EFI_ACPI_VARIABLE_COMPATIBILITY_GUID \ + { \ + 0xc020489e, 0x6db2, 0x4ef2, {0x9a, 0xa5, 0xca, 0x6, 0xfc, 0x11, 0xd3, 0x6a } \ + } + +#define ACPI_GLOBAL_VARIABLE L"AcpiGlobalVariable" + +extern EFI_GUID gEfiAcpiVariableCompatiblityGuid; + +typedef struct { + BOOLEAN APState; + BOOLEAN S3BootPath; + EFI_PHYSICAL_ADDRESS WakeUpBuffer; + EFI_PHYSICAL_ADDRESS GdtrProfile; + EFI_PHYSICAL_ADDRESS IdtrProfile; + EFI_PHYSICAL_ADDRESS CpuPrivateData; + EFI_PHYSICAL_ADDRESS StackAddress; + EFI_PHYSICAL_ADDRESS MicrocodePointerBuffer; + EFI_PHYSICAL_ADDRESS SmramBase; + EFI_PHYSICAL_ADDRESS SmmStartImageBase; + UINT32 SmmStartImageSize; + UINT32 NumberOfCpus; +} ACPI_CPU_DATA_COMPATIBILITY; + +typedef struct { + // + // Acpi Related variables + // + EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase; + UINT32 AcpiReservedMemorySize; + EFI_PHYSICAL_ADDRESS S3ReservedLowMemoryBase; + EFI_PHYSICAL_ADDRESS AcpiBootScriptTable; + EFI_PHYSICAL_ADDRESS RuntimeScriptTableBase; + EFI_PHYSICAL_ADDRESS AcpiFacsTable; + UINT64 SystemMemoryLength; + ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData; + // + // VGA OPROM to support Video Re-POST for Linux S3 + // + EFI_PHYSICAL_ADDRESS VideoOpromAddress; + UINT32 VideoOpromSize; + + // + // S3 Debug extension + // + EFI_PHYSICAL_ADDRESS S3DebugBufferAddress; + EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint; +} ACPI_VARIABLE_SET_COMPATIBILITY; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/BdsHii.h b/Core/IntelFrameworkModulePkg/Include/Guid/BdsHii.h new file mode 100644 index 0000000000..e22babc5b6 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/BdsHii.h @@ -0,0 +1,55 @@ +/** @file + GUIDs used as HII FormSet and HII Package list GUID in BdsDxe driver. + +Copyright (c) 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __BDS_HII_GUIDS_H__ +#define __BDS_HII_GUIDS_H__ + +#define FRONT_PAGE_FORMSET_GUID \ + { \ + 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe} \ + } + +#define BOOT_MANAGER_FORMSET_GUID \ + { \ + 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \ + } + +#define DEVICE_MANAGER_FORMSET_GUID \ + { \ + 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \ + } + +#define DRIVER_HEALTH_FORMSET_GUID \ + { \ + 0xf76e0a70, 0xb5ed, 0x4c38, {0xac, 0x9a, 0xe5, 0xf5, 0x4b, 0xf1, 0x6e, 0x34} \ + } + +#define BOOT_MAINT_FORMSET_GUID \ + { \ + 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \ + } + +#define FILE_EXPLORE_FORMSET_GUID \ + { \ + 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \ + } + +extern EFI_GUID gFrontPageFormSetGuid; +extern EFI_GUID gBootMaintFormSetGuid; +extern EFI_GUID gFileExploreFormSetGuid; +extern EFI_GUID gBootManagerFormSetGuid; +extern EFI_GUID gDeviceManagerFormSetGuid; +extern EFI_GUID gDriverHealthFormSetGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h b/Core/IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h new file mode 100644 index 0000000000..1a2bb024c4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h @@ -0,0 +1,25 @@ +/** @file + GUID used as HII Package list GUID in GenericBdsLib module. + +Copyright (c) 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __BDS_LIB_HII_GUID_H__ +#define __BDS_LIB_HII_GUID_H__ + +#define BDS_LIB_STRING_PACKAGE_GUID \ + { \ + 0x3b4d9b23, 0x95ac, 0x44f6, { 0x9f, 0xcd, 0xe, 0x95, 0x94, 0x58, 0x6c, 0x72 } \ + } + +extern EFI_GUID gBdsLibStringPackageGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/BlockIoVendor.h b/Core/IntelFrameworkModulePkg/Include/Guid/BlockIoVendor.h new file mode 100644 index 0000000000..71aa05a595 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/BlockIoVendor.h @@ -0,0 +1,31 @@ +/** @file + Guid for unrecognized EDD 3.0 device. + +Copyright (c) 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __BLOCKIO_VENDOR_H__ +#define __BLOCKIO_VENDOR_H__ + +// +// Guid is to specifiy the unrecognized EDD 3.0 device. +// +#define BLOCKIO_VENDOR_GUID \ + { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} } + +typedef struct { + VENDOR_DEVICE_PATH DevicePath; + UINT8 LegacyDriveLetter; +} BLOCKIO_VENDOR_DEVICE_PATH; + +extern GUID gBlockIoVendorGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/CapsuleDataFile.h b/Core/IntelFrameworkModulePkg/Include/Guid/CapsuleDataFile.h new file mode 100644 index 0000000000..7e97d17f23 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/CapsuleDataFile.h @@ -0,0 +1,23 @@ +/** @file + GUID to specify which FFS file to store the updated capsule data. + +Copyright (c) 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __UPDATE_DATA_FILE_GUID_H__ +#define __UPDATE_DATA_FILE_GUID_H__ + +#define EFI_UPDATE_DATA_FILE_GUID \ + { 0x283fa2ee, 0x532c, 0x484d, { 0x93, 0x83, 0x9f, 0x93, 0xb3, 0x6f, 0xb, 0x7e } } + +extern GUID gEfiUpdateDataFileGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h b/Core/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h new file mode 100644 index 0000000000..a03a09712c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h @@ -0,0 +1,61 @@ +/** @file + GUID used to identify Data Hub records logged by Status Code Protocol. + +Copyright (c) 2006 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __DATA_HUB_STATUS_CODE_RECORD_H__ +#define __DATA_HUB_STATUS_CODE_RECORD_H__ + +/// +/// The Global ID used to identify a structure of type DATA_HUB_STATUS_CODE_DATA_RECORD. +/// +#define EFI_DATA_HUB_STATUS_CODE_RECORD_GUID \ + { \ + 0xd083e94c, 0x6560, 0x42e4, {0xb6, 0xd4, 0x2d, 0xf7, 0x5a, 0xdf, 0x6a, 0x2a } \ + } + +/// +/// The Data Hub data record that is used to store all the parameters passed into +/// the ReportStatusCode() service of the EFI_STATUS_CODE_PROTOCOL. +/// +typedef struct { + /// + /// Status Code type to be reported. + /// + EFI_STATUS_CODE_TYPE CodeType; + + /// + /// An operation, plus value information about the class and subclass, used to + /// classify the hardware and software entity. + /// + EFI_STATUS_CODE_VALUE Value; + + /// + /// The enumeration of a hardware or software entity within + /// the system. Valid instance numbers start with 1. + /// + UINT32 Instance; + + /// + /// Identify the caller. + /// + EFI_GUID CallerId; + + /// + /// Additional status code data. + /// + EFI_STATUS_CODE_DATA Data; +} DATA_HUB_STATUS_CODE_DATA_RECORD; + +extern EFI_GUID gEfiDataHubStatusCodeRecordGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/HdBootVariable.h b/Core/IntelFrameworkModulePkg/Include/Guid/HdBootVariable.h new file mode 100644 index 0000000000..fae0839791 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/HdBootVariable.h @@ -0,0 +1,31 @@ +/** @file + GUID used as EFI Variable for the device path of Boot file on HardDevice. + +Copyright (c) 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __HD_DEVICE_PATH_VARIABLE_GUID_H__ +#define __HD_DEVICE_PATH_VARIABLE_GUID_H__ + +/// +/// This GUID is used for an EFI Variable that stores the front device pathes +/// for a partial device path that starts with the HD node. +/// +#define HD_BOOT_DEVICE_PATH_VARIABLE_GUID \ + { \ + 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } \ + } + +#define HD_BOOT_DEVICE_PATH_VARIABLE_NAME L"HDDP" + +extern EFI_GUID gHdBootDevicePathVariablGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/IntelFrameworkModulePkgTokenSpace.h b/Core/IntelFrameworkModulePkg/Include/Guid/IntelFrameworkModulePkgTokenSpace.h new file mode 100644 index 0000000000..a80c2315ba --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/IntelFrameworkModulePkgTokenSpace.h @@ -0,0 +1,27 @@ +/** @file + GUID for IntelFrameworkModulePkg PCD Token Space + +Copyright (c) 2009 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 _INTEL_FRAMEWOKR_MODULEPKG_TOKEN_SPACE_GUID_H_ +#define _INTEL_FRAMEWOKR_MODULEPKG_TOKEN_SPACE_GUID_H_ + +/// +/// The Global ID for the IntelFrameworkModulePkg PCD Token Space . +/// +#define INTEL_FRAMEWORK_MODULEPKG_TOKEN_SPACE_GUID \ + { \ + 0xD3705011, 0xBC19, 0x4af7, { 0xBE, 0x16, 0xF6, 0x80, 0x30, 0x37, 0x8C, 0x15 } \ + } + +extern EFI_GUID gEfiIntelFrameworkModulePkgTokenSpaceGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/LastEnumLang.h b/Core/IntelFrameworkModulePkg/Include/Guid/LastEnumLang.h new file mode 100644 index 0000000000..8d9e37fab2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/LastEnumLang.h @@ -0,0 +1,31 @@ +/** @file + GUID used as EFI variable to store platform language at last time enumeration. + +Copyright (c) 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __LAST_ENUM_LANGUAGE_GUID_H__ +#define __LAST_ENUM_LANGUAGE_GUID_H__ + +/// +/// This GUID is used for Set/Get platform language into/from variable at last time enumeration +/// to ensure the enumeration will only execute once. +/// +#define LAST_ENUM_LANGUAGE_GUID \ + { \ + 0xe8c545b, 0xa2ee, 0x470d, { 0x8e, 0x26, 0xbd, 0xa1, 0xa1, 0x3c, 0xa, 0xa3 } \ + } + +#define LAST_ENUM_LANGUAGE_VARIABLE_NAME L"LastEnumLang" + +extern EFI_GUID gLastEnumLangGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/LegacyBios.h b/Core/IntelFrameworkModulePkg/Include/Guid/LegacyBios.h new file mode 100644 index 0000000000..1fcea9ccfb --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/LegacyBios.h @@ -0,0 +1,36 @@ +/** @file + Defines a Tag GUID used to mark a UEFI legacy BIOS thunk driver based + on legacy BIOS services and legacy option ROM. This Tag GUID must be installed on + the ImageHandle of any module that follows the EFI Driver Model and uses + the Int86() or FarCall() services of the Legacy Bios Protocol to produce + a standard UEFI I/O Protocol. + +Copyright (c) 2006 - 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 _LEGACY_BIOS_H_ +#define _LEGACY_BIOS_H_ + +/// +/// The Global ID for the Legacy BIOS GUID that must be installed onto the ImageHandle +/// of any module follows the EFI Driver Model and uses the Int86() or FarCall() +/// services of the Legacy BIOS Protocol to produce a standard UEFI I/O Protocol. +/// +#define EFI_LEGACY_BIOS_GUID \ + { \ + 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 } \ + } + +extern EFI_GUID gEfiLegacyBiosGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/LegacyDevOrder.h b/Core/IntelFrameworkModulePkg/Include/Guid/LegacyDevOrder.h new file mode 100644 index 0000000000..684f098d58 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/LegacyDevOrder.h @@ -0,0 +1,45 @@ +/** @file + Guid of a NV Variable which store the information about the + FD/HD/CD/NET/BEV order. + +Copyright (c) 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __LEGACY_DEV_ORDER_VARIABLE_GUID_H__ +#define __LEGACY_DEV_ORDER_VARIABLE_GUID_H__ + +/// +/// Name and Guid of a NV Variable which stores the information about the +/// FD/HD/CD/NET/BEV order +/// +#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \ + { \ + 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52} \ + } + +typedef UINT8 BBS_TYPE; + +#pragma pack(1) +typedef struct { + BBS_TYPE BbsType; + /// + /// Length = sizeof (UINT16) + sizeof (Data) + /// + UINT16 Length; + UINT16 Data[1]; +} LEGACY_DEV_ORDER_ENTRY; +#pragma pack() + +#define VAR_LEGACY_DEV_ORDER L"LegacyDevOrder" + +extern EFI_GUID gEfiLegacyDevOrderVariableGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Guid/TianoDecompress.h b/Core/IntelFrameworkModulePkg/Include/Guid/TianoDecompress.h new file mode 100644 index 0000000000..7c2a6a6b93 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Guid/TianoDecompress.h @@ -0,0 +1,28 @@ +/** @file + Tiano Custom decompress Guid definition. + +Copyright (c) 2006 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __TIANO_CUSTOM_DECOMPRESS_GUID_H__ +#define __TIANO_CUSTOM_DECOMPRESS_GUID_H__ + +/// +/// The Global ID used to identify a section of an FFS file of type +/// EFI_SECTION_GUID_DEFINED, whose contents have been compressed using +/// Tiano Custom compression. +/// +#define TIANO_CUSTOM_DECOMPRESS_GUID \ + { 0xA31280AD, 0x481E, 0x41B6, { 0x95, 0xE8, 0x12, 0x7F, 0x4C, 0x98, 0x47, 0x79 } } + +extern GUID gTianoCustomDecompressGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Library/GenericBdsLib.h b/Core/IntelFrameworkModulePkg/Include/Library/GenericBdsLib.h new file mode 100644 index 0000000000..ecd68a003b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Library/GenericBdsLib.h @@ -0,0 +1,1114 @@ +/** @file + Generic BDS library defines general interfaces for a BDS driver, including: + 1) BDS boot policy interface. + 2) BDS boot device connect interface. + 3) BDS Misc interfaces for mainting boot variable, ouput string. + +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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 _GENERIC_BDS_LIB_H_ +#define _GENERIC_BDS_LIB_H_ + +#include + +/// +/// Constants which are variable names used to access variables. +/// +#define VAR_LEGACY_DEV_ORDER L"LegacyDevOrder" + +/// +/// Data structures and defines. +/// +#define FRONT_PAGE_QUESTION_ID 0x0000 +#define FRONT_PAGE_DATA_WIDTH 0x01 + +/// +/// ConnectType +/// +#define CONSOLE_OUT 0x00000001 +#define STD_ERROR 0x00000002 +#define CONSOLE_IN 0x00000004 +#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR) + +/// +/// Load Option Attributes +/// +#define LOAD_OPTION_ACTIVE 0x00000001 +#define LOAD_OPTION_FORCE_RECONNECT 0x00000002 + +#define LOAD_OPTION_HIDDEN 0x00000008 +#define LOAD_OPTION_CATEGORY 0x00001F00 + +#define LOAD_OPTION_CATEGORY_BOOT 0x00000000 +#define LOAD_OPTION_CATEGORY_APP 0x00000100 + +#define EFI_BOOT_OPTION_SUPPORT_KEY 0x00000001 +#define EFI_BOOT_OPTION_SUPPORT_APP 0x00000002 + +#define IS_LOAD_OPTION_TYPE(_c, _Mask) (BOOLEAN) (((_c) & (_Mask)) != 0) + +/// +/// Define the maximum characters that will be accepted. +/// +#define MAX_CHAR 480 +#define MAX_CHAR_SIZE (MAX_CHAR * 2) + +/// +/// Define maximum characters for boot option variable "BootXXXX". +/// +#define BOOT_OPTION_MAX_CHAR 10 + +// +// This data structure is the part of BDS_CONNECT_ENTRY +// +#define BDS_LOAD_OPTION_SIGNATURE SIGNATURE_32 ('B', 'd', 'C', 'O') + +typedef struct { + + UINTN Signature; + LIST_ENTRY Link; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + CHAR16 *OptionName; + UINTN OptionNumber; + UINT16 BootCurrent; + UINT32 Attribute; + CHAR16 *Description; + VOID *LoadOptions; + UINT32 LoadOptionsSize; + CHAR16 *StatusString; + +} BDS_COMMON_OPTION; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN ConnectType; +} BDS_CONSOLE_CONNECT_ENTRY; + +// +// Bds boot related lib functions +// +/** + Boot from the UEFI spec defined "BootNext" variable. + +**/ +VOID +EFIAPI +BdsLibBootNext ( + VOID + ); + +/** + Process the boot option according to the UEFI specification. The legacy boot option device path includes BBS_DEVICE_PATH. + + @param Option The boot option to be processed. + @param DevicePath The device path describing where to load the + boot image or the legcy 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 succeeded. + @retval EFI_NOT_FOUND 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 + ); + + +/** + This function will enumerate all possible boot devices in the system, and + automatically create boot options for Network, Shell, Removable BlockIo, + and Non-BlockIo Simplefile devices. + + BDS separates EFI boot options into six types: + 1. Network - The boot option points to the SimpleNetworkProtocol device. + Bds will try to automatically create this type of boot option during enumeration. + 2. Shell - The boot option points to internal flash shell. + Bds will try to automatically create this type of boot option during enumeration. + 3. Removable BlockIo - The boot option points to a removable media + device, such as a USB flash drive or DVD drive. + These devices 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 points to a Fixed blockIo device, + such as a hard disk. + These devices 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 options, + whose description rules 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 the user, either manually or with an OS loader. BDS will not delete or modify + these boot options. + + This function will enumerate all possible boot devices in the system, and + automatically create boot options for Network, Shell, Removable BlockIo, + and Non-BlockIo Simplefile devices. + It will excute once every boot. + + @param BdsBootOptionList The header of the linked list that indexed all + current boot options. + + @retval EFI_SUCCESS Finished all the boot device enumerations and + created the boot option based on the 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 + ); + +/** + Build the boot option with the handle parsed in. + + @param Handle The handle representing the device path for which + to create a boot option. + @param BdsBootOptionList The header of the link list that 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 + ); + + +/** + Build the on flash shell boot option with the handle parsed in. + + @param Handle The handle which present the device path to create + the on flash shell boot option. + @param BdsBootOptionList The header of the link list that indexed all + current boot options. + +**/ +VOID +EFIAPI +BdsLibBuildOptionFromShell ( + IN EFI_HANDLE Handle, + IN OUT LIST_ENTRY *BdsBootOptionList + ); + +// +// Bds misc lib functions +// +/** + Get boot mode by looking up the configuration table and parsing the HOB list. + + @param BootMode The boot mode from PEI handoff HOB. + + @retval EFI_SUCCESS Successfully got boot mode. + +**/ +EFI_STATUS +EFIAPI +BdsLibGetBootMode ( + OUT EFI_BOOT_MODE *BootMode + ); + + +/** + The function will go through the driver option link list, and then load and start + every driver to which the driver option device path points. + + @param BdsDriverLists The header of the current driver option link list. + +**/ +VOID +EFIAPI +BdsLibLoadDrivers ( + IN LIST_ENTRY *BdsDriverLists + ); + + +/** + This function processes BootOrder or DriverOrder variables, by calling + + BdsLibVariableToOption () for each UINT16 in the variables. + + @param BdsCommonOptionList The header of the option list base on the variable + VariableName. + @param VariableName An EFI Variable name indicate the BootOrder or + DriverOrder. + + @retval EFI_SUCCESS Successfully created the boot option or driver option + list. + @retval EFI_OUT_OF_RESOURCES Failed to get the boot option or the driver option list. +**/ +EFI_STATUS +EFIAPI +BdsLibBuildOptionFromVar ( + IN LIST_ENTRY *BdsCommonOptionList, + IN CHAR16 *VariableName + ); + +/** + This function reads the EFI variable (VendorGuid/Name) and returns a dynamically allocated + buffer and the size of the buffer. If it fails, return NULL. + + @param Name The string part of the EFI variable name. + @param VendorGuid The GUID part of the EFI variable name. + @param VariableSize Returns the size of the EFI variable that was read. + + @return Dynamically allocated memory that contains a copy + of the EFI variable. The caller is responsible for + freeing the buffer. + @retval NULL The variable was not read. + +**/ +VOID * +EFIAPI +BdsLibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ); + + +/** + This function prints a series of strings. + + @param ConOut A pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. + @param ... A variable argument list containing a series of + strings, the last string must be NULL. + + @retval EFI_SUCCESS Successfully printed 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, + ... + ); + +/** + 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, indicates if it is boot#### or + driver####. + + @retval BDS_COMMON_OPTION The option that was created. + @retval NULL Failed to get the new option. + +**/ +BDS_COMMON_OPTION * +EFIAPI +BdsLibVariableToOption ( + IN OUT LIST_ENTRY *BdsCommonOptionList, + IN CHAR16 *VariableName + ); + +/** + This function registers the new boot#### or driver#### option based 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 that 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 successfully + 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 + ); + +// +// Bds connect and disconnect driver lib funcions +// +/** + This function connects all system drivers with the corresponding controllers. + +**/ +VOID +EFIAPI +BdsLibConnectAllDriversToAllControllers ( + VOID + ); + +/** + This function connects all system drivers to controllers. + +**/ +VOID +EFIAPI +BdsLibConnectAll ( + VOID + ); + +/** + This function will create all handles associate with every device + path node. If the handle associate with one device path node can not + be created successfully, then still give chance to do the dispatch, + which load the missing drivers if possible. + + @param DevicePathToConnect The device path to be connected. Can be + a multi-instance device path. + + @retval EFI_SUCCESS All handles associates with every device path node + were created. + @retval EFI_OUT_OF_RESOURCES Not enough resources to create new handles. + @retval EFI_NOT_FOUND At least one handle could not be created. + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ); + +/** + 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 child handles have been + connected. + @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllEfi ( + VOID + ); + +/** + 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 + ); + +// +// Bds console related lib functions +// +/** + This function will search every simpletxt device in the current system, + and make every simpletxt device a potential console device. + +**/ +VOID +EFIAPI +BdsLibConnectAllConsoles ( + VOID + ); + + +/** + This function will connect console device based on the console + device variable ConIn, ConOut and ErrOut. + + @retval EFI_SUCCESS At least one of the ConIn and ConOut devices have + been connected. + @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable (). + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllDefaultConsoles ( + VOID + ); + + +/** + 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 + ); + + +/** + This function updates the console variable based on ConVarName. It can + add or remove one specific console device path from the variable + + @param ConVarName The console-related variable name: ConIn, ConOut, + ErrOut. + @param CustomizedConDevicePath The console device path to be added to + the console variable ConVarName. Cannot be multi-instance. + @param ExclusiveDevicePath The console device path to be removed + from the console variable ConVarName. Cannot be multi-instance. + + @retval EFI_UNSUPPORTED The added device path is the same as a removed one. + @retval EFI_SUCCESS Successfully added or removed the device path from the + console variable. + +**/ +EFI_STATUS +EFIAPI +BdsLibUpdateConsoleVariable ( + IN CHAR16 *ConVarName, + IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath + ); + +/** + Connect the console device base on the variable ConVarName, if + device path of the ConVarName is multi-instance device path 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 + ); + +// +// Bds device path related lib functions +// +/** + Delete the instance in Multi that overlaps with Single. + + @param Multi A pointer to a multi-instance device path data + structure. + @param Single A pointer to a single-instance device path data + structure. + + @return This function removes the device path instances in Multi that overlap + Single, and returns the resulting device path. If there is no + remaining device path as a result, this function will return NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +BdsLibDelPartMatchInstance ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ); + +/** + This function compares a device path data structure to that of all the nodes of a + second device path instance. + + @param Multi A pointer to a multi-instance device path data + structure. + @param Single A pointer to a single-instance device path data + structure. + + @retval TRUE If the Single device path is contained within a + Multi device path. + @retval FALSE The Single device path is not contained within a + Multi device path. + +**/ +BOOLEAN +EFIAPI +BdsLibMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ); + +/** + This function converts an input device structure to a Unicode string. + + @param DevPath A pointer to the device path structure. + + @return A newly allocated Unicode string that represents the device path. + +**/ +CHAR16 * +EFIAPI +DevicePathToStr ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +// +// Internal definitions +// +typedef struct { + CHAR16 *Str; + UINTN Len; + UINTN Maxlen; +} POOL_PRINT; + +typedef +VOID +(*DEV_PATH_FUNCTION) ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ); + +typedef struct { + UINT8 Type; + UINT8 SubType; + DEV_PATH_FUNCTION Function; +} DEVICE_PATH_STRING_TABLE; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEVICE_PATH_WITH_DATA; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT64 Lun; + UINT16 TargetPortalGroupTag; + CHAR16 TargetName[1]; +} ISCSI_DEVICE_PATH_WITH_NAME; + +// +// BBS support macros and functions +// + +#if defined(MDE_CPU_IA32) || defined(MDE_CPU_X64) +#define REFRESH_LEGACY_BOOT_OPTIONS \ + BdsDeleteAllInvalidLegacyBootOptions ();\ + BdsAddNonExistingLegacyBootOptions (); \ + BdsUpdateLegacyDevOrder () +#else +#define REFRESH_LEGACY_BOOT_OPTIONS +#endif + +/** + Delete all the invalid legacy boot options. + + @retval EFI_SUCCESS All invalid legacy boot options are deleted. + @retval EFI_OUT_OF_RESOURCES Failed to allocate necessary memory. + @retval EFI_NOT_FOUND Failed to retrieve variable of boot order. + +**/ +EFI_STATUS +EFIAPI +BdsDeleteAllInvalidLegacyBootOptions ( + VOID + ); + +/** + Add the legacy boot options from BBS table if they do not exist. + + @retval EFI_SUCCESS The boot options were 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 + ); + +/** + Add the legacy boot devices from BBS table into + the legacy device boot order. + + @retval EFI_SUCCESS The boot devices were added successfully. + @retval EFI_NOT_FOUND The legacy boot devices are not found. + @retval EFI_OUT_OF_RESOURCES Memory or storage is not enough. + @retval EFI_DEVICE_ERROR Failed to add the legacy device boot order into EFI variable + because of a hardware error. +**/ +EFI_STATUS +EFIAPI +BdsUpdateLegacyDevOrder ( + VOID + ); + +/** + Refresh the boot priority for BBS entries based on boot option entry and boot order. + + @param Entry The boot option is to be checked for a refreshed BBS table. + + @retval EFI_SUCCESS The boot priority for BBS entries 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 + ); + +/** + Delete the Boot Option from EFI Variable. The Boot Order Arrray + is also updated. + + @param OptionNumber The number of Boot options wanting 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 + ); + +// +//The interface functions related to the Setup Browser Reset Reminder feature +// +/** + Enable the setup browser reset reminder feature. + This routine is used in a platform tip. If the platform policy needs the feature, use the routine to enable it. + +**/ +VOID +EFIAPI +EnableResetReminderFeature ( + VOID + ); + +/** + Disable the setup browser reset reminder feature. + This routine is used in a platform tip. If the platform policy does not want the feature, use the routine to disable it. + +**/ +VOID +EFIAPI +DisableResetReminderFeature ( + VOID + ); + +/** + 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 + ); + + +/** + 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 + ); + +/** + Check whether platform policy enables the reset reminder feature. The default is enabled. + +**/ +BOOLEAN +EFIAPI +IsResetReminderFeatureEnable ( + VOID + ); + +/** + Check if the user changed any option setting that needs a system reset to be effective. + +**/ +BOOLEAN +EFIAPI +IsResetRequired ( + VOID + ); + +/** + Check whether a reset is needed, and finish the reset reminder feature. + If a reset is needed, pop up a menu to notice user, and finish the feature + according to the user selection. + +**/ +VOID +EFIAPI +SetupResetReminder ( + VOID + ); + + +/// +/// Define the boot type with which to classify the boot option type. +/// Different boot option types could have different boot behaviors. +/// Use their device path node (Type + SubType) as the type value. +/// The boot type here can be added according to requirements. +/// + +/// +/// ACPI boot type. For ACPI devices, using sub-types to distinguish devices is not allowed, so hardcode their values. +/// +#define BDS_EFI_ACPI_FLOPPY_BOOT 0x0201 +/// +/// Message boot type +/// If a device path of boot option only points to a message node, the boot option is a message boot type. +/// +#define BDS_EFI_MESSAGE_ATAPI_BOOT 0x0301 // Type 03; Sub-Type 01 +#define BDS_EFI_MESSAGE_SCSI_BOOT 0x0302 // Type 03; Sub-Type 02 +#define BDS_EFI_MESSAGE_USB_DEVICE_BOOT 0x0305 // Type 03; Sub-Type 05 +#define BDS_EFI_MESSAGE_SATA_BOOT 0x0312 // Type 03; Sub-Type 18 +#define BDS_EFI_MESSAGE_MAC_BOOT 0x030b // Type 03; Sub-Type 11 +#define BDS_EFI_MESSAGE_MISC_BOOT 0x03FF + +/// +/// Media boot type +/// If a device path of boot option contains a media node, the boot option is media boot type. +/// +#define BDS_EFI_MEDIA_HD_BOOT 0x0401 // Type 04; Sub-Type 01 +#define BDS_EFI_MEDIA_CDROM_BOOT 0x0402 // Type 04; Sub-Type 02 +/// +/// BBS boot type +/// If a device path of boot option contains a BBS node, the boot option is BBS boot type. +/// +#define BDS_LEGACY_BBS_BOOT 0x0501 // Type 05; Sub-Type 01 + +#define BDS_EFI_UNSUPPORT 0xFFFF + +/** + Check whether an instance in BlockIoDevicePath has the same partition node as the HardDriveDevicePath device path. + + @param BlockIoDevicePath Multi device path instances to check. + @param HardDriveDevicePath A device path starting 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 + ); + + +/** + 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. This function enables the device to boot. + To avoid requiring a connect on every boot, the front match is saved in a variable (the part point + to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ). + All successful history device paths + that point to the front part of the partition node 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 + ); + +/** + Return the bootable media handle. + First, check whether the device is connected. + Second, check whether the device path points to a device that supports SimpleFileSystemProtocol. + Third, detect the the default boot file in the Media, and return the removable Media handle. + + @param DevicePath The 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 + ); + + +/** + Checks whether the Device path in a boot option points to a valid bootable device, and if the device + is ready to boot now. + + @param DevPath The Device path in a boot option. + @param CheckMedia If true, check whether 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 + ); + +/** + Checks whether the Device path in a boot option points to a valid bootable device, and if the device + is ready to boot now. + If Description is not NULL and the device path points to a fixed BlockIo + device, this function checks whether the description conflicts with other auto-created + boot options. + + @param DevPath The Device path in a boot option. + @param CheckMedia If true, checks if the device is ready to boot now. + @param Description The description of 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 + ); + +/** + For a bootable Device path, return its boot type. + + @param DevicePath The bootable device Path to check. + + @retval BDS_EFI_MEDIA_HD_BOOT The given device path contains MEDIA_DEVICE_PATH type device path node, + whose subtype is MEDIA_HARDDRIVE_DP. + @retval BDS_EFI_MEDIA_CDROM_BOOT If given device path contains MEDIA_DEVICE_PATH type device path node, + whose subtype is MEDIA_CDROM_DP. + @retval BDS_EFI_ACPI_FLOPPY_BOOT A given device path contains ACPI_DEVICE_PATH type device path node, + whose HID is floppy device. + @retval BDS_EFI_MESSAGE_ATAPI_BOOT A 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 A 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 A 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 The device path does not contain any media device path node, and + its last device path node points to a message device path node. + @retval BDS_LEGACY_BBS_BOOT A given device path contains BBS_DEVICE_PATH type device path node. + @retval BDS_EFI_UNSUPPORT An EFI Removable BlockIO device path does not point to a media and message device. + + **/ +UINT32 +EFIAPI +BdsGetBootTypeFromDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + + +/** + This routine registers a function to adjust the different types of memory page numbers + just before booting, and saves the updated info into the variable for the next boot to use. + +**/ +VOID +EFIAPI +BdsLibSaveMemoryTypeInformation ( + VOID + ); + +/** + Identify a user and, if authenticated, returns the current user profile handle. + + @param[out] User Points to the user profile handle. + + @retval EFI_SUCCESS The user is successfully identified, or user identification + is not supported. + @retval EFI_ACCESS_DENIED The user was not successfully identified. + +**/ +EFI_STATUS +EFIAPI +BdsLibUserIdentify ( + OUT EFI_USER_PROFILE_HANDLE *User + ); + +/** + This function checks if a Fv file device path is valid, according to a file GUID. If it is invalid, + it tries to return the valid device path. + FV address maybe changes for memory layout adjust from time to time, use this funciton + could promise the Fv file device path is right. + + @param DevicePath On input, the Fv file device path to check. On + output, the updated valid Fv file device path + @param FileGuid the Fv file GUID. + + @retval EFI_INVALID_PARAMETER The input DevicePath or FileGuid is invalid. + @retval EFI_UNSUPPORTED The input DevicePath does not contain an Fv file + GUID at all. + @retval EFI_ALREADY_STARTED The input DevicePath has pointed to the Fv file and is + valid. + @retval EFI_SUCCESS Successfully updated the invalid DevicePath + and returned the updated device path in DevicePath. + +**/ +EFI_STATUS +EFIAPI +BdsLibUpdateFvFileDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath, + IN EFI_GUID *FileGuid + ); + + +/** + Connect the specific USB device that matches the RemainingDevicePath, + 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. + + @retval EFI_SUCCESS The specific Usb device is connected successfully. + @retval EFI_INVALID_PARAMETER Invalid HostControllerPi (not 0x00, 0x20 or 0xFF) + or RemainingDevicePath is not the USB class device path. + @retval EFI_NOT_FOUND The device specified by device path is not found. + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectUsbDevByShortFormDP( + IN UINT8 HostControllerPI, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + + +// +// The implementation of this function is provided by Platform code. +// +/** + Convert Vendor device path to a device name. + + @param Str The buffer storing device name. + @param DevPath The pointer to vendor device path. + +**/ +VOID +DevPathVendor ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ); + +/** + Concatenates a formatted unicode string to an allocated pool. + The caller must free the resulting buffer. + + @param Str Tracks the allocated pool, size in use, and amount of pool allocated. + @param Fmt The format string. + @param ... The data will be printed. + + @return Allocated buffer with the formatted string printed in it. + The caller must free the allocated buffer. + The buffer allocation is not packed. + +**/ +CHAR16 * +EFIAPI +CatPrint ( + IN OUT POOL_PRINT *Str, + IN CHAR16 *Fmt, + ... + ); + +/** + Use SystemTable ConOut to stop video based Simple Text Out consoles from going + to the video device. Put up LogoFile on every video device that is a console. + + @param[in] LogoFile The file name of logo to display on the center of the screen. + + @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed. + @retval EFI_UNSUPPORTED Logo not found. + +**/ +EFI_STATUS +EFIAPI +EnableQuietBoot ( + IN EFI_GUID *LogoFile + ); + + +/** + Use SystemTable ConOut to turn on video based Simple Text Out consoles. The + Simple Text Out screens will now be synced up with all non-video output devices. + + @retval EFI_SUCCESS UGA devices are back in text mode and synced up. + +**/ +EFI_STATUS +EFIAPI +DisableQuietBoot ( + VOID + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Include/Library/PlatformBdsLib.h b/Core/IntelFrameworkModulePkg/Include/Library/PlatformBdsLib.h new file mode 100644 index 0000000000..af237a6030 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Library/PlatformBdsLib.h @@ -0,0 +1,156 @@ +/** @file + Platform BDS library definition. A platform can implement + instances to support platform-specific behavior. + +Copyright (c) 2008 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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_BDS_LIB_H_ +#define __PLATFORM_BDS_LIB_H_ + +#include +#include + +/** + Perform the memory test base on the memory test intensive level, + and update the memory resource. + + @param Level The memory test intensive level. + + @retval EFI_STATUS Successfully test all the system memory, and update + the memory resource + +**/ +typedef +EFI_STATUS +(EFIAPI *BASEM_MEMORY_TEST)( + IN EXTENDMEM_COVERAGE_LEVEL Level + ); + +/** + This routine is called to see if there are any capsules we need to process. + If the boot mode is not UPDATE, then we do nothing. Otherwise, find the + capsule HOBS and produce firmware volumes for them via the DXE service. + Then call the dispatcher to dispatch drivers from them. Finally, check + the status of the updates. + + This function should be called by BDS in case we need to do some + sort of processing even if there is no capsule to process. We + need to do this if an earlier update went away and we need to + clear the capsule variable so on the next reset PEI does not see it and + think there is a capsule available. + + @param BootMode The current boot mode + + @retval EFI_INVALID_PARAMETER The boot mode is not correct for an update. + @retval EFI_SUCCESS There is no error when processing a capsule. + +**/ +typedef +EFI_STATUS +(EFIAPI *PROCESS_CAPSULES)( + IN EFI_BOOT_MODE BootMode + ); + +/** + Platform Bds initialization. Includes the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformBdsInit ( + VOID + ); + +/** + 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() + +**/ +VOID +EFIAPI +PlatformBdsPolicyBehavior ( + IN LIST_ENTRY *DriverOptionList, + IN LIST_ENTRY *BootOptionList, + IN PROCESS_CAPSULES ProcessCapsules, + IN BASEM_MEMORY_TEST BaseMemoryTest + ); + +/** + Hook point for a user-provided function, for after a boot attempt fails. + + @param Option A pointer to Boot Option that failed to boot. + @param Status The status returned from failed boot. + @param ExitData The exit data returned from failed boot. + @param ExitDataSize The exit data size returned from failed boot. + +**/ +VOID +EFIAPI +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ); + +/** + 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 also a platform implementation, and can be customized by an IBV/OEM. + + @param Option A pointer to the Boot Option that successfully booted. + +**/ +VOID +EFIAPI +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ); + + +/** + This function locks platform flash that is not allowed to be updated during normal boot path. + The flash layout is platform specific. + + **/ +VOID +EFIAPI +PlatformBdsLockNonUpdatableFlash ( + VOID + ); + +/** + 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 The 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 + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Protocol/ExitPmAuth.h b/Core/IntelFrameworkModulePkg/Include/Protocol/ExitPmAuth.h new file mode 100644 index 0000000000..748ab96620 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Protocol/ExitPmAuth.h @@ -0,0 +1,25 @@ +/** @file + Defines the ExitPmAuth protocol. + +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 _EXIT_PM_AUTH_PROTOCOL_H_ +#define _EXIT_PM_AUTH_PROTOCOL_H_ + +#define EXIT_PM_AUTH_PROTOCOL_GUID \ + { 0xd088a413, 0xa70, 0x4217, { 0xba, 0x55, 0x9a, 0x3c, 0xb6, 0x5c, 0x41, 0xb3 }} + +extern EFI_GUID gExitPmAuthProtocolGuid; + +#endif // #ifndef _EXIT_PM_AUTH_PROTOCOL_H_ diff --git a/Core/IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h b/Core/IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h new file mode 100644 index 0000000000..7de3504417 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h @@ -0,0 +1,304 @@ +/** @file + EFI ISA ACPI Protocol is used to enumerate and manage all the ISA controllers on + the platform's ISA Bus. + +Copyright (c) 2006 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __ISA_ACPI_H_ +#define __ISA_ACPI_H_ + +/// +/// Global ID for the EFI ISA ACPI Protocol. +/// +#define EFI_ISA_ACPI_PROTOCOL_GUID \ + { \ + 0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55 } \ + } + +/// +/// Forward declaration fo the EFI ISA ACPI Protocol +/// +typedef struct _EFI_ISA_ACPI_PROTOCOL EFI_ISA_ACPI_PROTOCOL; + +/// +/// ISA ACPI Protocol interrupt resource attributes. +/// +#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE 0x01 ///< Edge triggered interrupt on a rising edge. +#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE 0x02 ///< Edge triggered interrupt on a falling edge. +#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE 0x04 ///< Level sensitive interrupt active high. +#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE 0x08 ///< Level sensitive interrupt active low. + +/// +/// ISA ACPI Protocol DMA resource attributes. +/// +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_MASK 0x03 ///< Bit mask of supported DMA speed attributes. +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_COMPATIBILITY 0x00 ///< ISA controller supports compatibility mode DMA transfers. +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_A 0x01 ///< ISA controller supports type A DMA transfers. +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_B 0x02 ///< ISA controller supports type B DMA transfers. +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_F 0x03 ///< ISA controller supports type F DMA transfers. +#define EFI_ISA_ACPI_DMA_COUNT_BY_BYTE 0x04 ///< ISA controller increments DMA address by bytes (8-bit). +#define EFI_ISA_ACPI_DMA_COUNT_BY_WORD 0x08 ///< ISA controller increments DMA address by words (16-bit). +#define EFI_ISA_ACPI_DMA_BUS_MASTER 0x10 ///< ISA controller is a DMA bus master. +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT 0x20 ///< ISA controller only supports 8-bit DMA transfers. +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT 0x40 ///< ISA controller both 8-bit and 16-bit DMA transfers. +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x80 ///< ISA controller only supports 16-bit DMA transfers. + +/// +/// ISA ACPI Protocol MMIO resource attributes +/// +#define EFI_ISA_ACPI_MEMORY_WIDTH_MASK 0x03 ///< Bit mask of supported ISA memory width attributes. +#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT 0x00 ///< ISA MMIO region only supports 8-bit access. +#define EFI_ISA_ACPI_MEMORY_WIDTH_16_BIT 0x01 ///< ISA MMIO region only supports 16-bit access. +#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT_AND_16_BIT 0x02 ///< ISA MMIO region supports both 8-bit and 16-bit access. +#define EFI_ISA_ACPI_MEMORY_WRITEABLE 0x04 ///< ISA MMIO region supports write transactions. +#define EFI_ISA_ACPI_MEMORY_CACHEABLE 0x08 ///< ISA MMIO region supports being cached. +#define EFI_ISA_ACPI_MEMORY_SHADOWABLE 0x10 ///< ISA MMIO region may be shadowed. +#define EFI_ISA_ACPI_MEMORY_EXPANSION_ROM 0x20 ///< ISA MMIO region is an expansion ROM. + +/// +/// ISA ACPI Protocol I/O resource attributes +/// +#define EFI_ISA_ACPI_IO_DECODE_10_BITS 0x01 ///< ISA controllers uses a 10-bit address decoder for I/O cycles. +#define EFI_ISA_ACPI_IO_DECODE_16_BITS 0x02 ///< ISA controllers uses a 16-bit address decoder for I/O cycles. + +/// +/// EFI ISA ACPI resource type +/// +typedef enum { + EfiIsaAcpiResourceEndOfList, ///< Marks the end if a resource list. + EfiIsaAcpiResourceIo, ///< ISA I/O port resource range. + EfiIsaAcpiResourceMemory, ///< ISA MMIO resource range. + EfiIsaAcpiResourceDma, ///< ISA DMA resource. + EfiIsaAcpiResourceInterrupt ///< ISA interrupt resource. +} EFI_ISA_ACPI_RESOURCE_TYPE; + +/// +/// EFI ISA ACPI generic resource structure +/// +typedef struct { + EFI_ISA_ACPI_RESOURCE_TYPE Type; ///< The type of resource (I/O, MMIO, DMA, Interrupt). + UINT32 Attribute; ///< Bit mask of attributes associated with this resource. See EFI_ISA_ACPI_xxx macros for valid combinations. + UINT32 StartRange; ///< The start of the resource range. + UINT32 EndRange; ///< The end of the resource range. +} EFI_ISA_ACPI_RESOURCE; + +/// +/// EFI ISA ACPI resource device identifier +/// +typedef struct { + UINT32 HID; ///< The ACPI Hardware Identifier value associated with an ISA controller. Matchs ACPI DSDT contents. + UINT32 UID; ///< The ACPI Unique Identifier value associated with an ISA controller. Matches ACPI DSDT contents. +} EFI_ISA_ACPI_DEVICE_ID; + +/// +/// EFI ISA ACPI resource list +/// +typedef struct { + EFI_ISA_ACPI_DEVICE_ID Device; ///< The ACPI HID/UID associated with an ISA controller. + EFI_ISA_ACPI_RESOURCE *ResourceItem; ///< A pointer to the list of resources associated with an ISA controller. +} EFI_ISA_ACPI_RESOURCE_LIST; + +/** + Enumerates the ISA controllers on an ISA bus. + + This service allows all the ISA controllers on an ISA bus to be enumerated. If + Device is a pointer to a NULL value, then the first ISA controller on the ISA + bus is returned in Device and EFI_SUCCESS is returned. If Device is a pointer + to a value that was returned on a prior call to DeviceEnumerate(), then the next + ISA controller on the ISA bus is returned in Device and EFI_SUCCESS is returned. + If Device is a pointer to the last ISA controller on the ISA bus, then + EFI_NOT_FOUND is returned. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[out] Device The pointer to an ISA controller named by ACPI HID/UID. + + @retval EFI_SUCCESS The next ISA controller on the ISA bus was returned. + @retval EFI_NOT_FOUND No device found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_DEVICE_ENUMERATE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + OUT EFI_ISA_ACPI_DEVICE_ID **Device + ); + +/** + Sets the power state of an ISA controller. + + This services sets the power state of the ISA controller specified by Device to + the power state specified by OnOff. TRUE denotes on, FALSE denotes off. + If the power state is sucessfully set on the ISA Controller, then + EFI_SUCCESS is returned. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. + @param[in] OnOff TRUE denotes on, FALSE denotes off. + + @retval EFI_SUCCESS Successfully set the power state of the ISA controller. + @retval Other The ISA controller could not be placed in the requested power state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_SET_DEVICE_POWER)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN OnOff + ); + +/** + Retrieves the current set of resources associated with an ISA controller. + + Retrieves the set of I/O, MMIO, DMA, and interrupt resources currently + assigned to the ISA controller specified by Device. These resources + are returned in ResourceList. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. + @param[out] ResourceList The pointer to the current resource list for Device. + + @retval EFI_SUCCESS Successfully retrieved the current resource list. + @retval EFI_NOT_FOUND The resource list could not be retrieved. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_GET_CUR_RESOURCE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ); + +/** + Retrieves the set of possible resources that may be assigned to an ISA controller + with SetResource(). + + Retrieves the possible sets of I/O, MMIO, DMA, and interrupt resources for the + ISA controller specified by Device. The sets are returned in ResourceList. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. + @param[out] ResourceList The pointer to the returned list of resource lists. + + @retval EFI_UNSUPPORTED This service is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_GET_POS_RESOURCE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ); + +/** + Assigns resources to an ISA controller. + + Assigns the I/O, MMIO, DMA, and interrupt resources specified by ResourceList + to the ISA controller specified by Device. ResourceList must match a resource list returned by GetPosResource() for the same ISA controller. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. + @param[in] ResourceList The pointer to a resources list that must be one of the + resource lists returned by GetPosResource() for the + ISA controller specified by Device. + + @retval EFI_SUCCESS Successfully set resources on the ISA controller. + @retval Other The resources could not be set for the ISA controller. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_SET_RESOURCE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList + ); + +/** + Enables or disables an ISA controller. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to the ISA controller to enable/disable. + @param[in] Enable TRUE to enable the ISA controller. FALSE to disable the + ISA controller. + + @retval EFI_SUCCESS Successfully enabled/disabled the ISA controller. + @retval Other The ISA controller could not be placed in the requested state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_ENABLE_DEVICE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN Enable + ); + +/** + Initializes an ISA controller, so that it can be used. This service must be called + before SetResource(), EnableDevice(), or SetPower() will behave as expected. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. + + @retval EFI_SUCCESS Successfully initialized an ISA controller. + @retval Other The ISA controller could not be initialized. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_INIT_DEVICE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device + ); + +/** + Initializes all the HW states required for the ISA controllers on the ISA bus + to be enumerated and managed by the rest of the services in this prorotol. + This service must be called before any of the other services in this + protocol will function as expected. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + + @retval EFI_SUCCESS Successfully initialized all required hardware states. + @retval Other The ISA interface could not be initialized. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_INTERFACE_INIT)( + IN EFI_ISA_ACPI_PROTOCOL *This + ); + +/// +/// The EFI_ISA_ACPI_PROTOCOL provides the services to enumerate and manage +/// ISA controllers on an ISA bus. These services include the ability to initialize, +/// enable, disable, and manage the power state of ISA controllers. It also +/// includes services to query current resources, query possible resources, +/// and assign resources to an ISA controller. +/// +struct _EFI_ISA_ACPI_PROTOCOL { + EFI_ISA_ACPI_DEVICE_ENUMERATE DeviceEnumerate; + EFI_ISA_ACPI_SET_DEVICE_POWER SetPower; + EFI_ISA_ACPI_GET_CUR_RESOURCE GetCurResource; + EFI_ISA_ACPI_GET_POS_RESOURCE GetPosResource; + EFI_ISA_ACPI_SET_RESOURCE SetResource; + EFI_ISA_ACPI_ENABLE_DEVICE EnableDevice; + EFI_ISA_ACPI_INIT_DEVICE InitDevice; + EFI_ISA_ACPI_INTERFACE_INIT InterfaceInit; +}; + +extern EFI_GUID gEfiIsaAcpiProtocolGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Protocol/IsaIo.h b/Core/IntelFrameworkModulePkg/Include/Protocol/IsaIo.h new file mode 100644 index 0000000000..cf6632e737 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Protocol/IsaIo.h @@ -0,0 +1,362 @@ +/** @file + ISA I/O Protocol is used by ISA device drivers to perform I/O, MMIO and DMA + operations on the ISA controllers they manage. + +Copyright (c) 2006 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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_ISA_IO_H_ +#define _EFI_ISA_IO_H_ + +#include + +/// +/// Global ID for the EFI_ISA_IO_PROTOCOL +/// +#define EFI_ISA_IO_PROTOCOL_GUID \ + { \ + 0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +/// +/// Forward declaration for the EFI_ISA_IO_PROTOCOL. +/// +typedef struct _EFI_ISA_IO_PROTOCOL EFI_ISA_IO_PROTOCOL; + +/// +/// Width of EFI_ISA_IO_PROTOCOL I/O Port and MMIO operations. +/// +typedef enum { + EfiIsaIoWidthUint8 = 0, ///< 8-bit operation. + EfiIsaIoWidthUint16, ///< 16-bit operation. + EfiIsaIoWidthUint32, ///< 32-bit operation + EfiIsaIoWidthReserved, + EfiIsaIoWidthFifoUint8, ///< 8-bit FIFO operation. + EfiIsaIoWidthFifoUint16, ///< 16-bit FIFO operation. + EfiIsaIoWidthFifoUint32, ///< 32-bit FIFO operation. + EfiIsaIoWidthFifoReserved, + EfiIsaIoWidthFillUint8, ///< 8-bit Fill operation. + EfiIsaIoWidthFillUint16, ///< 16-bit Fill operation. + EfiIsaIoWidthFillUint32, ///< 32-bit Fill operation. + EfiIsaIoWidthFillReserved, + EfiIsaIoWidthMaximum +} EFI_ISA_IO_PROTOCOL_WIDTH; + +/// +/// Attributes for the EFI_ISA_IO_PROTOCOL common DMA buffer allocations. +/// +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x080 ///< Map a memory range so write are combined. +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED 0x800 ///< Map a memory range so all read and write accesses are cached. +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 ///< Disable a memory range. + +/// +/// Channel attribute for EFI_ISA_IO_PROTOCOL slave DMA requests +/// +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE 0x001 ///< Set the speed of the DMA transfer in compatible mode. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A 0x002 ///< Not supported. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B 0x004 ///< Not supported. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C 0x008 ///< Not supported. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8 0x010 ///< Request 8-bit DMA transfers. Only available on channels 0..3. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16 0x020 ///< Request 16-bit DMA transfers. Only available on channels 4..7. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE 0x040 ///< Request a single DMA transfer. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE 0x080 ///< Request multiple DMA transfers until TC (Terminal Count) or EOP (End of Process). +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE 0x100 ///< Automatically reload base and count at the end of the DMA transfer. + +/// +/// The DMA opreration type for EFI_ISA_IO_PROTOCOL DMA requests. +/// +typedef enum { + /// + /// A read operation from system memory by a bus master. + /// + EfiIsaIoOperationBusMasterRead, + /// + /// A write operation to system memory by a bus master. + /// + EfiIsaIoOperationBusMasterWrite, + /// + /// Provides both read and write access to system memory by both the processor + /// and a bus master. The buffer is coherent from both the processor's and the + /// bus master's point of view. + /// + EfiIsaIoOperationBusMasterCommonBuffer, + /// + /// A read operation from system memory by a slave device. + /// + EfiIsaIoOperationSlaveRead, + /// + /// A write operation to system memory by a slave master. + /// + EfiIsaIoOperationSlaveWrite, + EfiIsaIoOperationMaximum +} EFI_ISA_IO_PROTOCOL_OPERATION; + +/** + Performs ISA I/O and MMIO Read/Write Cycles + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O or MMIO operation. + @param[in] Offset The offset into the ISA I/O or MMIO space to start the + operation. + @param[in] Count The number of I/O or MMIO operations to perform. + @param[in, out] Buffer For read operations, the destination buffer to store + the results. For write operations, the source buffer to + write data from. + + @retval EFI_SUCCESS The data was successfully read from or written to the device. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_IO_MEM)( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/// +/// Structure of functions for accessing ISA I/O and MMIO space. +/// +typedef struct { + /// + /// Read from ISA I/O or MMIO space. + /// + EFI_ISA_IO_PROTOCOL_IO_MEM Read; + /// + /// Write to ISA I/O or MMIO space. + /// + EFI_ISA_IO_PROTOCOL_IO_MEM Write; +} EFI_ISA_IO_PROTOCOL_ACCESS; + +/** + Copies data from one region of ISA MMIO space to another region of ISA + MMIO space. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the MMIO copy operation. + @param[in] DestOffset The offset of the destination in ISA MMIO space. + @param[in] SrcOffset The offset of the source in ISA MMIO space. + @param[in] Count The number tranfers to perform for this copy operation. + + @retval EFI_SUCCESS The data was copied sucessfully. + @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_COPY_MEM)( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ); + +/** + Maps a memory region for DMA. + + This function returns the device-specific addresses required to access system memory. + This function is used to map system memory for ISA DMA operations. All ISA DMA + operations must be performed through their mapped addresses, and such mappings must + be freed with EFI_ISA_IO_PROTOCOL.Unmap() after the DMA operation is completed. + + If the DMA operation is a single read or write data transfer through an ISA bus + master, then EfiIsaIoOperationBusMasterRead or EfiIsaIoOperationBusMasterWrite + is used and the range is unmapped to complete the operation. If the DMA operation + is a single read or write data transfer through an ISA slave controller, then + EfiIsaIoOperationSlaveRead or EfiIsaIoOperationSlaveWrite is used and the range + is unmapped to complete the operation. + + If performing a DMA read operation, all the data must be present in system memory before the Map() is performed. Similarly, + if performing a DMA write operation, the data must not be accessed in system + memory until EFI_ISA_IO_PROTOCOL.Unmap() is performed. Bus master operations that + require both read and write access or require multiple host device interactions + within the same mapped region must use EfiIsaIoOperationBusMasterCommonBuffer. + However, only memory allocated via the EFI_ISA_IO_PROTOCOL.AllocateBuffer() interface + is guaranteed to be able to be mapped for this operation type. In all mapping + requests the NumberOfBytes returned may be less than originally requested. It is + the caller's responsibility to make additional requests to complete the entire + transfer. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Operation Indicates the type of DMA (slave or bus master), + and if the DMA operation is going to read or + write to system memory. + @param[in] ChannelNumber The slave channel number to use for this DMA + operation. If Operation and ChannelAttributes + shows that this device performs bus mastering + DMA, then this field is ignored. The legal + range for this field is 0..7. + @param[in] ChannelAttributes A bitmask of the attributes used to configure + the slave DMA channel for this DMA operation. + See EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_* for the + legal bit combinations. + @param[in] HostAddress The system memory address to map to the device. + @param[in, out] NumberOfBytes On input the number of bytes to map. On + output the number of bytes that were mapped. + @param[out] DeviceAddress The resulting map address for the bus master + device to use to access the hosts HostAddress. + @param[out] Mapping A returned value that must be passed to into + EFI_ISA_IO_PROTOCOL.Unmap() to free all the the + resources associated with this map request. + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation is undefined. + @retval EFI_INVALID_PARAMETER The HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_MAP)( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Unmaps a memory region that was previously mapped with EFI_ISA_IO_PROTOCOL.Map(). + + The EFI_ISA_IO_PROTOCOL.Map() operation is completed and any corresponding + resources are released. If the operation was EfiIsaIoOperationSlaveWrite + or EfiIsaIoOperationBusMasterWrite, the data is committed to system memory. + Any resources used for the mapping are freed. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Mapping The mapping value returned from EFI_ISA_IO_PROTOCOL.Map(). + + @retval EFI_SUCCESS The memory region was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_UNMAP)( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer + mapping. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Type The type allocation to perform. + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base address of the allocated range. + @param[in] Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER Type is invalid. + @retval EFI_INVALID_PARAMETER MemoryType is invalid. + @retval EFI_INVALID_PARAMETER HostAddress is NULL. + @retval EFI_UNSUPPORTED Attributes is unsupported. + @retval EFI_UNSUPPORTED The memory range specified by HostAddress, Pages, + and Type is not available for common buffer use. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER)( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees a common buffer that was allocated with EFI_ISA_IO_PROTOCOL.AllocateBuffer(). + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Pages The number of pages to free from the previously allocated common buffer. + @param[in] HostAddress The base address of the previously allocated common buffer. + + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_FREE_BUFFER)( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +/** + Flushes a DMA buffer, which forces all DMA posted write transactions to complete. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The DMA buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_FLUSH)( + IN EFI_ISA_IO_PROTOCOL *This + ); + +/// +/// The EFI_ISA_IO_PROTOCOL provides the basic Memory, I/O, and DMA interfaces +/// used to abstract accesses to ISA controllers. There is one EFI_ISA_IO_PROTOCOL +/// instance for each ISA controller on a ISA bus. A device driver that wishes +/// to manage an ISA controller in a system will have to retrieve the +/// ISA_PCI_IO_PROTOCOL instance associated with the ISA controller. +/// +struct _EFI_ISA_IO_PROTOCOL { + EFI_ISA_IO_PROTOCOL_ACCESS Mem; + EFI_ISA_IO_PROTOCOL_ACCESS Io; + EFI_ISA_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_ISA_IO_PROTOCOL_MAP Map; + EFI_ISA_IO_PROTOCOL_UNMAP Unmap; + EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_ISA_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_ISA_IO_PROTOCOL_FLUSH Flush; + /// + /// The list of I/O , MMIO, DMA, and Interrupt resources associated with the + /// ISA controller abstracted by this instance of the EFI_ISA_IO_PROTOCOL. + /// + EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; + /// + /// The size, in bytes, of the ROM image. + /// + UINT32 RomSize; + /// + /// A pointer to the in memory copy of the ROM image. The ISA Bus Driver is responsible + /// for allocating memory for the ROM image, and copying the contents of the ROM to memory + /// during ISA Bus initialization. + /// + VOID *RomImage; +}; + +extern EFI_GUID gEfiIsaIoProtocolGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Protocol/OEMBadging.h b/Core/IntelFrameworkModulePkg/Include/Protocol/OEMBadging.h new file mode 100644 index 0000000000..c56b7e725b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Protocol/OEMBadging.h @@ -0,0 +1,88 @@ +/** @file + The OEM Badging Protocol defines the interface to get the OEM badging + image with the display attribute. This protocol can be produced based on OEM badging images. + +Copyright (c) 2006 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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_OEM_BADGING_H__ +#define __EFI_OEM_BADGING_H__ + +// +// GUID for EFI OEM Badging Protocol +// +#define EFI_OEM_BADGING_PROTOCOL_GUID \ + { 0x170e13c0, 0xbf1b, 0x4218, {0x87, 0x1d, 0x2a, 0xbd, 0xc6, 0xf8, 0x87, 0xbc } } + + +typedef struct _EFI_OEM_BADGING_PROTOCOL EFI_OEM_BADGING_PROTOCOL; + +typedef enum { + EfiBadgingFormatBMP, + EfiBadgingFormatJPEG, + EfiBadgingFormatTIFF, + EfiBadgingFormatGIF, + EfiBadgingFormatUnknown +} EFI_BADGING_FORMAT; + +typedef enum { + EfiBadgingDisplayAttributeLeftTop, + EfiBadgingDisplayAttributeCenterTop, + EfiBadgingDisplayAttributeRightTop, + EfiBadgingDisplayAttributeCenterRight, + EfiBadgingDisplayAttributeRightBottom, + EfiBadgingDisplayAttributeCenterBottom, + EfiBadgingDisplayAttributeLeftBottom, + EfiBadgingDisplayAttributeCenterLeft, + EfiBadgingDisplayAttributeCenter, + EfiBadgingDisplayAttributeCustomized +} EFI_BADGING_DISPLAY_ATTRIBUTE; + +/** + + Load an OEM badge image and return its data and attributes. + + @param This The pointer to this protocol instance. + @param Instance The visible image instance is found. + @param Format The format of the image. Examples: BMP, JPEG. + @param ImageData The image data for the badge file. Currently only + supports the .bmp file format. + @param ImageSize The size of the image returned. + @param Attribute The display attributes of the image returned. + @param CoordinateX The X coordinate of the image. + @param CoordinateY The Y coordinate of the image. + + @retval EFI_SUCCESS The image was fetched successfully. + @retval EFI_NOT_FOUND The specified image could not be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BADGING_GET_IMAGE)( + IN EFI_OEM_BADGING_PROTOCOL *This, + IN OUT UINT32 *Instance, + OUT EFI_BADGING_FORMAT *Format, + OUT UINT8 **ImageData, + OUT UINTN *ImageSize, + OUT EFI_BADGING_DISPLAY_ATTRIBUTE *Attribute, + OUT UINTN *CoordinateX, + OUT UINTN *CoordinateY +); + + +struct _EFI_OEM_BADGING_PROTOCOL { + EFI_BADGING_GET_IMAGE GetImage; +}; + + +extern EFI_GUID gEfiOEMBadgingProtocolGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Protocol/Ps2Policy.h b/Core/IntelFrameworkModulePkg/Include/Protocol/Ps2Policy.h new file mode 100644 index 0000000000..8e915edaf5 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Protocol/Ps2Policy.h @@ -0,0 +1,41 @@ +/** @file + PS/2 policy protocol abstracts the specific platform initialization and settings. + +Copyright (c) 2006 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 _PS2_POLICY_PROTOCOL_H_ +#define _PS2_POLICY_PROTOCOL_H_ + +#define EFI_PS2_POLICY_PROTOCOL_GUID \ + { \ + 0x4df19259, 0xdc71, 0x4d46, {0xbe, 0xf1, 0x35, 0x7b, 0xb5, 0x78, 0xc4, 0x18 } \ + } + +#define EFI_KEYBOARD_CAPSLOCK 0x0004 +#define EFI_KEYBOARD_NUMLOCK 0x0002 +#define EFI_KEYBOARD_SCROLLLOCK 0x0001 + +typedef +EFI_STATUS +(EFIAPI *EFI_PS2_INIT_HARDWARE) ( + IN EFI_HANDLE Handle + ); + +typedef struct { + UINT8 KeyboardLight; + EFI_PS2_INIT_HARDWARE Ps2InitHardware; +} EFI_PS2_POLICY_PROTOCOL; + +extern EFI_GUID gEfiPs2PolicyProtocolGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h b/Core/IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h new file mode 100644 index 0000000000..e912eed213 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h @@ -0,0 +1,94 @@ +/** @file + The VGA Mini Port Protocol used to set the text display mode of a VGA controller. + +Copyright (c) 2006 - 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 that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 __VGA_MINI_PORT_H_ +#define __VGA_MINI_PORT_H_ + +/// +/// Global ID for the EFI_VGA_MINI_PORT_PROTOCOL. +/// +#define EFI_VGA_MINI_PORT_PROTOCOL_GUID \ + { \ + 0xc7735a2f, 0x88f5, 0x4882, {0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3 } \ + } + +/// +/// Forward declaration for the EFI_VGA_MINI_PORT_PROTOCOL. +/// +typedef struct _EFI_VGA_MINI_PORT_PROTOCOL EFI_VGA_MINI_PORT_PROTOCOL; + +/** + Sets the text display mode of a VGA controller. + + Sets the text display mode of the VGA controller to the mode specified by + ModeNumber. A ModeNumber of 0 is a request for an 80x25 text mode. A + ModeNumber of 1 is a request for an 80x50 text mode. If ModeNumber is greater + than MaxModeNumber, then EFI_UNSUPPORTED is returned. If the VGA controller + is not functioning properly, then EFI_DEVICE_ERROR is returned. If the VGA + controller is sucessfully set to the mode number specified by ModeNumber, then + EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_VGA_MINI_PORT_PROTOCOL instance. + @param[in] ModeNumber The requested mode number. 0 for 80x25. 1 for 80x5. + + @retval EFI_SUCCESS The mode number was set. + @retval EFI_UNSUPPORTED The mode number specified by ModeNumber is not supported. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_VGA_MINI_PORT_SET_MODE)( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +struct _EFI_VGA_MINI_PORT_PROTOCOL { + EFI_VGA_MINI_PORT_SET_MODE SetMode; + /// + /// MMIO base address of the VGA text mode framebuffer. Typically set to 0xB8000. + /// + UINT64 VgaMemoryOffset; + /// + /// I/O Port address for the VGA CRTC address register. Typically set to 0x3D4. + /// + UINT64 CrtcAddressRegisterOffset; + /// + /// I/O Port address for the VGA CRTC data register. Typically set to 0x3D5. + /// + UINT64 CrtcDataRegisterOffset; + /// + /// PCI Controller MMIO BAR index of the VGA text mode frame buffer. Typically + /// set to EFI_PCI_IO_PASS_THROUGH_BAR + /// + UINT8 VgaMemoryBar; + /// + /// PCI Controller I/O BAR index of the VGA CRTC address register. Typically + /// set to EFI_PCI_IO_PASS_THROUGH_BAR + /// + UINT8 CrtcAddressRegisterBar; + /// + /// PCI Controller I/O BAR index of the VGA CRTC data register. Typically set + /// to EFI_PCI_IO_PASS_THROUGH_BAR + /// + UINT8 CrtcDataRegisterBar; + /// + /// The maximum number of text modes that this VGA controller supports. + /// + UINT8 MaxMode; +}; + +extern EFI_GUID gEfiVgaMiniPortProtocolGuid; + +#endif diff --git a/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec b/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec new file mode 100644 index 0000000000..8bbde8e2c9 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec @@ -0,0 +1,283 @@ +## @file +# Intel Framework Module Package. +# +# This package contains the definitions and module implementation +# which follows Intel EFI Framework Specification. +# +# Copyright (c) 2007 - 2015, Intel 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] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = IntelFrameworkModulePkg + PACKAGE_UNI_FILE = IntelFrameworkModulePkg.uni + PACKAGE_GUID = 88894582-7553-4822-B484-624E24B6DECF + PACKAGE_VERSION = 0.96 + +[Includes] + Include # Root include for the package + +[LibraryClasses] + ## @libraryclass Platform BDS library definition about platform specific behavior. + PlatformBdsLib|Include/Library/PlatformBdsLib.h + + ## @libraryclass Generic BDS library definition, include the data structure and function. + GenericBdsLib|Include/Library/GenericBdsLib.h + +[Guids] + ## IntelFrameworkModule package token space guid + # Include/Guid/IntelFrameworkModulePkgTokenSpace.h + gEfiIntelFrameworkModulePkgTokenSpaceGuid = { 0xD3705011, 0xBC19, 0x4af7, { 0xBE, 0x16, 0xF6, 0x80, 0x30, 0x37, 0x8C, 0x15 }} + + ## GUID identifies Data Hub records logged by Status Code Runtime Protocol. + # Include/Guid/DataHubStatusCodeRecord.h + gEfiDataHubStatusCodeRecordGuid = { 0xD083E94C, 0x6560, 0x42E4, { 0xB6, 0xD4, 0x2D, 0xF7, 0x5A, 0xDF, 0x6A, 0x2A }} + + ## GUID indicates the tiano custom compress/decompress algorithm. + # Include/Guid/TianoDecompress.h + gTianoCustomDecompressGuid = { 0xA31280AD, 0x481E, 0x41B6, { 0x95, 0xE8, 0x12, 0x7F, 0x4C, 0x98, 0x47, 0x79 }} + + ## Include/Guid/AcpiVariable.h + gEfiAcpiVariableCompatiblityGuid = { 0xc020489e, 0x6db2, 0x4ef2, { 0x9a, 0xa5, 0xca, 0x6, 0xfc, 0x11, 0xd3, 0x6a }} + + ## Include/Guid/LegacyBios.h + gEfiLegacyBiosGuid = { 0x2E3044AC, 0x879F, 0x490F, { 0x97, 0x60, 0xBB, 0xDF, 0xAF, 0x69, 0x5F, 0x50 }} + + ## Include/Guid/LegacyDevOrder.h + gEfiLegacyDevOrderVariableGuid = { 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52 }} + + ## Include/Guid/CapsuleDataFile.h + gEfiUpdateDataFileGuid = { 0x283fa2ee, 0x532c, 0x484d, { 0x93, 0x83, 0x9f, 0x93, 0xb3, 0x6f, 0xb, 0x7e }} + + ## Include/Guid/BlockIoVendor.h + gBlockIoVendorGuid = { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b }} + + ## Include/Guid/BdsHii.h + gFrontPageFormSetGuid = { 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }} + gBootManagerFormSetGuid = { 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }} + gDeviceManagerFormSetGuid = { 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 }} + gDriverHealthFormSetGuid = { 0xf76e0a70, 0xb5ed, 0x4c38, {0xac, 0x9a, 0xe5, 0xf5, 0x4b, 0xf1, 0x6e, 0x34 }} + gBootMaintFormSetGuid = { 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22 }} + gFileExploreFormSetGuid = { 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b }} + + ## Include/Guid/BdsLibHii.h + gBdsLibStringPackageGuid = { 0x3b4d9b23, 0x95ac, 0x44f6, {0x9f, 0xcd, 0xe, 0x95, 0x94, 0x58, 0x6c, 0x72 }} + + ## Include/Guid/LastEnumLang.h + gLastEnumLangGuid = { 0xe8c545b, 0xa2ee, 0x470d, {0x8e, 0x26, 0xbd, 0xa1, 0xa1, 0x3c, 0xa, 0xa3 }} + + ## Include/Guid/HdBootVariable.h + gHdBootDevicePathVariablGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, {0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde }} + +[Protocols] + ## Vga Mini port binding for a VGA controller + # Include/Protocol/VgaMiniPort.h + gEfiVgaMiniPortProtocolGuid = { 0xc7735a2f, 0x88f5, 0x4882, { 0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3 }} + + ## ISA I/O Protocol is used to perform ISA device Io/Mem operations. + # Include/Protocol/IsaIo.h + gEfiIsaIoProtocolGuid = { 0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }} + + ## ISA Acpi Protocol is used to operate and communicate with ISA device. + # Include/Protocol/IsaAcpi.h + gEfiIsaAcpiProtocolGuid = { 0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55 }} + + ## PS/2 policy protocol abstracts the specific platform initialization and setting. + # Include/Protocol/Ps2Policy.h + gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE, 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 }} + + ## OEM Badging Protocol defines the interface to get the OEM badging image with the dispaly attribute. + # Include/Protocol/OEMBadging.h + gEfiOEMBadgingProtocolGuid = { 0x170E13C0, 0xBF1B, 0x4218, { 0x87, 0x1D, 0x2A, 0xBD, 0xC6, 0xF8, 0x87, 0xBC }} + + ## Include/Protocol/ExitPmAuth.h + gExitPmAuthProtocolGuid = { 0xd088a413, 0xa70, 0x4217, { 0xba, 0x55, 0x9a, 0x3c, 0xb6, 0x5c, 0x41, 0xb3 }} + +# +# [Error.gEfiIntelFrameworkModulePkgTokenSpaceGuid] +# 0x80000001 | Invalid value provided. +# 0x80000002 | Reserved bits must be set to zero. +# + +[PcdsFeatureFlag] + ## Indicates if OEM device is enabled as StatusCode report device. + # It is only used in Framework StatusCode implementation.

+ # TRUE - Enable OEM device.
+ # FALSE - Disable OEM device.
+ # @Prompt Report StatusCode via OEM Device + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseOEM|FALSE|BOOLEAN|0x00010024 + + ## Indicates if StatusCode report is loged into DataHub.

+ # TRUE - Log StatusCode report into DataHub.
+ # FALSE - Does not log StatusCode report into DataHub.
+ # @Prompt Log StatusCode into DataHub + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub|FALSE|BOOLEAN|0x00010029 + + ## Indicates if Serial device uses half hand shake.

+ # TRUE - Serial device uses half hand shake.
+ # FALSE - Serial device doesn't use half hand shake.
+ # @Prompt Enable Serial device Half Hand Shake + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE|BOOLEAN|0x00010043 + + ## Indicates if Legacy support is needed for ACPI S3 Save.

+ # TRUE - Support Legacy OS with S3 boot.
+ # FALSE - Does not support Legacy OS with S3 boot.
+ # @Prompt Turn on Legacy Support in S3 Boot + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformCsmSupport|TRUE|BOOLEAN|0x00010044 + + ## Indicates if PS2 keyboard does a extended verification during start. + # Extended verification will take some performance. It can be set to FALSE for boot performance.

+ # TRUE - Turn on PS2 keyboard extended verification.
+ # FALSE - Turn off PS2 keyboard extended verification.
+ # @Prompt Turn on PS2 Keyboard Extended Verification + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|TRUE|BOOLEAN|0x00010045 + + ## Indicates if Framework Acpi Support protocol is installed.

+ # TRUE - Install Framework Acpi Support protocol.
+ # FALSE - Doesn't install Framework Acpi Support protocol.
+ # @Prompt Enable Framework Acpi Support + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdInstallAcpiSupportProtocol|TRUE|BOOLEAN|0x00010046 + + + ## Indicates if PS2 mouse does a extended verification during start. + # Extended verification will take some performance. It can be set to FALSE for boot performance.

+ # TRUE - Turn on PS2 mouse extended verification.
+ # FALSE - Turn off PS2 mouse extended verification.
+ # @Prompt Turn on PS2 Mouse Extended Verification + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification|TRUE|BOOLEAN|0x00010047 + + ## Indicates if only Boot logo is showed and all message output is disabled in BDS.

+ # TRUE - Only Boot Logo is showed in boot.
+ # FALSE - All messages and Boot Logo are showed in boot.
+ # @Prompt Enable Boot Logo only + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootlogoOnlyEnable|FALSE|BOOLEAN|0x00010048 + +[PcdsFixedAtBuild, PcdsPatchableInModule] + ## FFS filename to find the default BMP Logo file. + # @Prompt FFS Name of Boot Logo File + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile |{ 0x99, 0x8b, 0xB2, 0x7B, 0xBB, 0x61, 0xD5, 0x11, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }|VOID*|0x40000003 + + ## FFS filename to find the shell application. + # @Prompt FFS Name of Shell Application + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0xB7, 0xD6, 0x7A, 0xC5, 0x15, 0x05, 0xA8, 0x40, 0x9D, 0x21, 0x55, 0x16, 0x52, 0x85, 0x4E, 0x37 }|VOID*|0x40000004 + + ## ISA Bus features to support DMA, SlaveDMA and ISA Memory.

+ # BIT0 indicates if DMA is supported
+ # BIT1 indicates if only slave DMA is supported
+ # BIT2 indicates if ISA memory is supported
+ # Other BITs are reseved and must be zero. + # If more than one features are supported, the different BIT will be enabled at the same time. + # @Prompt ISA Bus Features + # @Expression 0x80000002 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures & 0xF8) == 0 + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures|0x05|UINT8|0x00010040 + +[PcdsDynamic, PcdsDynamicEx] + ## Indicates if the machine has completed one boot cycle before. + # After the complete boot, BootState will be set to FALSE.

+ # TRUE - The complete boot cycle has not happened before.
+ # FALSE - The complete boot cycle has happened before.
+ # @Prompt Boot State Flag + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|TRUE|BOOLEAN|0x0001002f + +[PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule] + ## I/O Base address of floppy device controller. + # @Prompt I/O Base Address of Floppy Device Controller + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFdcBaseAddress|0x3f0|UINT16|0x30000000 + + ## Indicates if BiosVideo driver will switch to 80x25 Text VGA Mode when exiting boot service.

+ # TRUE - Switch to Text VGA Mode.
+ # FALSE - Does not switch to Text VGA Mode.
+ # @Prompt Switch to Text VGA Mode on UEFI Boot + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable|FALSE|BOOLEAN|0x30000001 + + ## Indicates if BiosVideo driver will check for VESA BIOS Extension service support.

+ # TRUE - Check for VESA BIOS Extension service.
+ # FALSE - Does not check for VESA BIOS Extension service.
+ # @Prompt Enable Check for VESA BIOS Extension Service + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable|TRUE|BOOLEAN|0x30000002 + + ## Indicates if BiosVideo driver will check for VGA service support. + # NOTE: If both PcdBiosVideoCheckVbeEnable and PcdBiosVideoCheckVgaEnable are set to FALSE, + # that means Graphics Output protocol will not be installed, the VGA miniport protocol will be installed instead.

+ # TRUE - Check for VGA service.
+ # FALSE - Does not check for VGA service.
+ # @Prompt Enable Check for VGA Service + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable|TRUE|BOOLEAN|0x30000003 + + ## Indicates if memory space for legacy region will be set as cacheable.

+ # TRUE - Set cachebility for legacy region.
+ # FALSE - Does not set cachebility for legacy region.
+ # @Prompt Enable Cachebility for Legacy Region + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion|TRUE|BOOLEAN|0x00000004 + + ## Specify memory size with bytes to reserve EBDA below 640K for OPROM. + # The value should be a multiple of 4KB. + # @Prompt Reserved EBDA Memory Size + # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize < 0xA0000) AND ((gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize & 0x1000) == 0) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize|0x8000|UINT32|0x30000005 + + ## Specify memory base address for OPROM to find free memory. + # Some OPROMs do not use EBDA or PMM to allocate memory for its usage, + # instead they find the memory filled with zero from 0x20000. + # The value should be a multiple of 4KB. + # The range should be below the EBDA reserved range from + # (CONVENTIONAL_MEMORY_TOP - Reserved EBDA Memory Size) to CONVENTIONAL_MEMORY_TOP. + # @Prompt Reserved Memory Base Address for OPROM + # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase >= 0x20000) AND ((gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase & 0x1000) == 0) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase|0x60000|UINT32|0x3000000c + + ## Specify memory size with bytes for OPROM to find free memory. + # The value should be a multiple of 4KB. And the range should be below the EBDA reserved range from + # (CONVENTIONAL_MEMORY_TOP - Reserved EBDA Memory Size) to CONVENTIONAL_MEMORY_TOP. + # @Prompt Reserved Memory Size for OPROM + # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize < 0x80000) AND ((gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize & 0x1000) == 0) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize|0x28000|UINT32|0x3000000d + + ## Specify memory size with page number for a pre-allocated reserved memory to be used + # by PEI in S3 phase. The default size 32K. When changing the value make sure the memory size + # is large enough to meet PEI requirement in the S3 phase. + # @Prompt Reserved S3 Boot ACPI Memory Size + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize|0x8000|UINT32|0x30000006 + + ## Specify memory size for boot script executor stack usage in S3 phase. + # The default size 32K. When changing the value make sure the memory size is large enough + # to meet boot script executor requirement in the S3 phase. + # @Prompt Reserved S3 Boot Script Stack ACPI Memory Size + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3BootScriptStackSize|0x8000|UINT32|0x30000007 + + ## Specify the end of address below 1MB for the OPROM. + # The last shadowed OpROM should not exceed this address. + # @Prompt Top Address of Shadowed Legacy OpROM + # @Expression 0x80000001 | gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEndOpromShadowAddress < 0x100000 + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEndOpromShadowAddress|0xdffff|UINT32|0x30000008 + + ## Specify the low PMM (Post Memory Manager) size with bytes below 1MB. + # The value should be a multiple of 4KB. + # @Prompt Low PMM (Post Memory Manager) Size + # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize < 0x100000) AND ((gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize & 0x1000) == 0) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize|0x10000|UINT32|0x30000009 + + ## Specify the high PMM (Post Memory Manager) size with bytes above 1MB. + # The value should be a multiple of 4KB. + # @Prompt High PMM (Post Memory Manager) Size + # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize & 0x1000) == 0 + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize|0x400000|UINT32|0x3000000a + + ## Indicates if 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.

+ # TRUE - Use the optimized timing for best PS2 detection performance.
+ # FALSE - Use the normal timing to detect PS2.
+ # @Prompt Enable fast PS2 detection + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection|FALSE|BOOLEAN|0x3000000b + +[UserExtensions.TianoCore."ExtraFiles"] + IntelFrameworkModulePkgExtra.uni diff --git a/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc b/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc new file mode 100644 index 0000000000..b4adab11ef --- /dev/null +++ b/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc @@ -0,0 +1,198 @@ +## @file +# Intel Framework Reference Module Package for All Architectures +# +# This file is used to build all modules in IntelFrameworkModulePkg. +# +#Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
+#This program and the accompanying materials are licensed and made available under +#the terms and conditions of the BSD License that accompanies this distribution. +#The full text of the license may be found at +#http://opensource.org/licenses/bsd-license.php. +# +# 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 = IntelFrameworkModuleAll + PLATFORM_GUID = FFF87D9A-E5BB-4AFF-9ADE-8645492E8087 + PLATFORM_VERSION = 0.96 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/IntelFrameworkModuleAll + SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC|ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + +################################################################################ +# +# SKU Identification section - list of all SKU IDs supported by this +# Platform. +# +################################################################################ +[SkuIds] + 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required. + +[LibraryClasses] + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + PlatformBdsLib|IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + PalLib|MdePkg/Library/BasePalLibNull/BasePalLibNull.inf + +[LibraryClasses.common.PEIM] + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + +[LibraryClasses.EBC.PEIM] + IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf + +[LibraryClasses.common.DXE_DRIVER] + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf + +[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ +[PcdsFeatureFlag] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE + +[PcdsFixedAtBuild] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000 + +[PcdsFixedAtBuild.IPF] + gEfiMdePkgTokenSpaceGuid.PcdIoBlockBaseAddressForIpf|0x0ffffc000000 + +################################################################################################### +# +# Components Section - list of the modules and components that will be processed by compilation +# tools and the EDK II tools to generate PE32/PE32+/Coff image files. +# +# Note: The EDK II DSC file is not used to specify how compiled binary images get placed +# into firmware volume images. This section is just a list of modules to compile from +# source into UEFI-compliant binaries. +# It is the FDF file that contains information on combining binary files into firmware +# volume images, whose concept is beyond UEFI and is described in PI specification. +# Binary modules do not need to be listed in this section, as they should be +# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi), +# Logo (Logo.bmp), and etc. +# There may also be modules listed in this section that are not required in the FDF file, +# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be +# generated for it, but the binary will not be put into any firmware volume. +# +################################################################################################### + +[Components] + IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf + IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf + IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf + IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf + IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf + IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf + IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf + IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf + + IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf + IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf + IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf + + IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf + IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf + IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf + IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf + + IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf + IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf + IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf + IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf + IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf + IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf + IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf + IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf + IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf + IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf + IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf + +[Components.IA32,Components.X64] + IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf + IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf + +[Components.IA32,Components.X64,Components.IPF] + IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf + +[Components.IA32] + IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf + IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf { + + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + } + +[Components.X64] + IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf + IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf { + + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + } + +[Components.IPF] + IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf { + + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + } diff --git a/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.uni b/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.uni new file mode 100644 index 0000000000..50106e10d5 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkg.uni differ diff --git a/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkgExtra.uni b/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkgExtra.uni new file mode 100644 index 0000000000..15fdff98ad Binary files /dev/null and b/Core/IntelFrameworkModulePkg/IntelFrameworkModulePkgExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c b/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c new file mode 100644 index 0000000000..2e527234e2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c @@ -0,0 +1,1050 @@ +/** @file + UEFI and Tiano Custom Decompress Library + It will do Tiano or UEFI decompress with different verison parameter. + +Copyright (c) 2006 - 2015, Intel 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 "BaseUefiTianoCustomDecompressLibInternals.h" + +/** + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + + @param Sd The global scratch data + @param NumOfBits The number of bits to shift and read. +**/ +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +{ + // + // Left shift NumOfBits of bits in advance + // + Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); + + // + // Copy data needed in bytes into mSbuBitBuf + // + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + + } else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + // + // Calculate additional bit count read to update mBitCount + // + Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); + + // + // Copy NumOfBits of bits from mSubBitBuf into mBitBuf + // + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +/** + Get NumOfBits of bits out from mBitBuf + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + + @param Sd The global scratch data. + @param NumOfBits The number of bits to pop and read. + + @return The bits that are popped out. + +**/ +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +{ + UINT32 OutBits; + + // + // Pop NumOfBits of Bits from Left + // + OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + // + // Fill up mBitBuf from source + // + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +/** + Creates Huffman Code mapping table according to code length array. + + Creates Huffman Code mapping table for Extra Set, Char&Len Set + and Position Set according to code length array. + If TableBits > 16, then ASSERT (). + + @param Sd The global scratch data + @param NumOfChar Number of symbols in the symbol set + @param BitLen Code length array + @param TableBits The width of the mapping table + @param Table The table to be created. + + @retval 0 OK. + @retval BAD_TABLE The table is corrupted. + +**/ +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + UINT16 WordOfStart; + UINT16 WordOfCount; + + // + // The maximum mapping table width supported by this internal + // working function is 16. + // + ASSERT (TableBits <= 16); + + for (Index = 0; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + Count[BitLen[Index]]++; + } + + Start[0] = 0; + Start[1] = 0; + + for (Index = 1; Index <= 16; Index++) { + WordOfStart = Start[Index]; + WordOfCount = Count[Index]; + Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index))); + } + + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16) BAD_TABLE; + } + + JuBits = (UINT16) (16 - TableBits); + + Weight[0] = 0; + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16) (1U << (TableBits - Index)); + } + + while (Index <= 16) { + Weight[Index] = (UINT16) (1U << (16 - Index)); + Index++; + } + + Index = (UINT16) (Start[TableBits + 1] >> JuBits); + + if (Index != 0) { + Index3 = (UINT16) (1U << TableBits); + if (Index < Index3) { + SetMem16 (Table + Index, (Index3 - Index) * sizeof (*Table), 0); + } + } + + Avail = NumOfChar; + Mask = (UINT16) (1U << (15 - TableBits)); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0 || Len >= 17) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + for (Index = Start[Len]; Index < NextCode; Index++) { + Table[Index] = Char; + } + + } else { + + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16) (Len - TableBits); + + while (Index != 0) { + if (*Pointer == 0 && Avail < (2 * NC - 1)) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } + + if (*Pointer < (2 * NC - 1)) { + if ((Index3 & Mask) != 0) { + Pointer = &Sd->mRight[*Pointer]; + } else { + Pointer = &Sd->mLeft[*Pointer]; + } + } + + Index3 <<= 1; + Index--; + } + + *Pointer = Char; + + } + + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; +} + +/** + Decodes a position value. + + Get a position value according to Position Huffman Table. + + @param Sd the global scratch data + + @return The position value decoded. +**/ +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if ((Sd->mBitBuf & Mask) != 0) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); + } + + return Pos; +} + +/** + Reads code lengths for the Extra Set or the Position Set. + + Read in the Extra Set or Pointion Set Length Arrary, then + generate the Huffman code mapping for them. + + @param Sd The global scratch data. + @param nn Number of symbols. + @param nbit Number of bits needed to represent nn. + @param Special The special symbol that needs to be taken care of. + + @retval 0 OK. + @retval BAD_TABLE Table is corrupted. + +**/ +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + ASSERT (nn <= NPT); + // + // Read Extra Set Code Length Array size + // + Number = (UINT16) GetBits (Sd, nbit); + + if (Number == 0) { + // + // This represents only Huffman code used + // + CharC = (UINT16) GetBits (Sd, nbit); + + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } + + SetMem (Sd->mPTLen, nn, 0); + + return 0; + } + + Index = 0; + + while (Index < Number && Index < NPT) { + + CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); + + // + // If a code length is less than 7, then it is encoded as a 3-bit + // value. Or it is encoded as a series of "1"s followed by a + // terminating "0". The number of "1"s = Code length - 4. + // + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } + + FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); + + Sd->mPTLen[Index++] = (UINT8) CharC; + + // + // For Code&Len Set, + // After the third length of the code length concatenation, + // a 2-bit value is used to indicated the number of consecutive + // zero lengths after the third length. + // + if (Index == Special) { + CharC = (UINT16) GetBits (Sd, 2); + while ((INT16) (--CharC) >= 0 && Index < NPT) { + Sd->mPTLen[Index++] = 0; + } + } + } + + while (Index < nn && Index < NPT) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +/** + Reads code lengths for Char&Len Set. + + Read in and decode the Char&Len Set Code Length Array, then + generate the Huffman Code mapping table for the Char&Len Set. + + @param Sd the global scratch data + +**/ +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, CBIT); + + if (Number == 0) { + // + // This represents only Huffman code used + // + CharC = (UINT16) GetBits (Sd, CBIT); + + SetMem (Sd->mCLen, NC, 0); + + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } + + return ; + } + + Index = 0; + while (Index < Number && Index < NC) { + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } else { + CharC = Sd->mLeft[CharC]; + } + + Mask >>= 1; + + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[CharC]); + + if (CharC <= 2) { + + if (CharC == 0) { + CharC = 1; + } else if (CharC == 1) { + CharC = (UINT16) (GetBits (Sd, 4) + 3); + } else if (CharC == 2) { + CharC = (UINT16) (GetBits (Sd, CBIT) + 20); + } + + while ((INT16) (--CharC) >= 0 && Index < NC) { + Sd->mCLen[Index++] = 0; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + SetMem (Sd->mCLen + Index, NC - Index, 0); + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +/** + Decode a character/length value. + + Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates + Huffman code mapping table for Extra Set, Code&Len Set and + Position Set. + + @param Sd The global scratch data. + + @return The value decoded. + +**/ +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +{ + UINT16 Index2; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // Read BlockSize from block header + // + Sd->mBlockSize = (UINT16) GetBits (Sd, 16); + + // + // Read in the Extra Set Code Length Arrary, + // Generate the Huffman code mapping table for Extra Set. + // + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + // + // Read in and decode the Char&Len Set Code Length Arrary, + // Generate the Huffman code mapping table for Char&Len Set. + // + ReadCLen (Sd); + + // + // Read in the Position Set Code Length Arrary, + // Generate the Huffman code mapping table for the Position Set. + // + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + // + // Get one code according to Code&Set Huffman Table + // + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if ((Sd->mBitBuf & Mask) != 0) { + Index2 = Sd->mRight[Index2]; + } else { + Index2 = Sd->mLeft[Index2]; + } + + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mCLen[Index2]); + + return Index2; +} + +/** + Decode the source data and put the resulting data into the destination buffer. + + @param Sd The global scratch data +**/ +VOID +Decode ( + SCRATCH_DATA *Sd + ) +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; + + BytesRemain = (UINT16) (-1); + + DataIdx = 0; + + for (;;) { + // + // Get one code from mBitBuf + // + CharC = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + goto Done; + } + + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + goto Done; + } else { + // + // Write orignal character into mDstBase + // + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + } + + } else { + // + // Process a Pointer + // + CharC = (UINT16) (CharC - (BIT8 - THRESHOLD)); + + // + // Get string length + // + BytesRemain = CharC; + + // + // Locate string position + // + DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; + + // + // Write BytesRemain of bytes into mDstBase + // + BytesRemain--; + while ((INT16) (BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + goto Done ; + } + + BytesRemain--; + } + } + } + +Done: + return ; +} + +/** + Given a compressed source buffer, this function retrieves the size of + the uncompressed buffer and the size of the scratch buffer required + to decompress the compressed source buffer. + + Retrieves the size of the uncompressed buffer and the temporary scratch buffer + required to decompress the buffer specified by Source and SourceSize. + If the size of the uncompressed buffer or the size of the scratch buffer cannot + be determined from the compressed data specified by Source and SourceData, + then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed + buffer is returned in DestinationSize, the size of the scratch buffer is returned + in ScratchSize, and RETURN_SUCCESS is returned. + This function does not have scratch buffer available to perform a thorough + checking of the validity of the source data. It just retrieves the "Original Size" + field from the beginning bytes of the source data and output it as DestinationSize. + And ScratchSize is specific to the decompression implementation. + + If Source is NULL, then ASSERT(). + If DestinationSize is NULL, then ASSERT(). + If ScratchSize is NULL, then ASSERT(). + + @param Source The source buffer containing the compressed data. + @param SourceSize The size, in bytes, of the source buffer. + @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer + that will be generated when the compressed buffer specified + by Source and SourceSize is decompressed.. + @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that + is required to decompress the compressed buffer specified + by Source and SourceSize. + + @retval RETURN_SUCCESS The size of the uncompressed data was returned + in DestinationSize and the size of the scratch + buffer was returned in ScratchSize. + @retval RETURN_INVALID_PARAMETER + The size of the uncompressed data or the size of + the scratch buffer cannot be determined from + the compressed data specified by Source + and SourceSize. +**/ +RETURN_STATUS +EFIAPI +UefiDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +{ + UINT32 CompressedSize; + + ASSERT (Source != NULL); + ASSERT (DestinationSize != NULL); + ASSERT (ScratchSize != NULL); + + if (SourceSize < 8) { + return RETURN_INVALID_PARAMETER; + } + + CompressedSize = ReadUnaligned32 ((UINT32 *)Source); + if (SourceSize < (CompressedSize + 8)) { + return RETURN_INVALID_PARAMETER; + } + + *ScratchSize = sizeof (SCRATCH_DATA); + *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1); + + return RETURN_SUCCESS; +} + +/** + Decompresses a compressed source buffer by EFI or Tiano algorithm. + + Extracts decompressed data to its original form. + This function is designed so that the decompression algorithm can be implemented + without using any memory services. As a result, this function is not allowed to + call any memory allocation services in its implementation. It is the caller's + responsibility to allocate and free the Destination and Scratch buffers. + If the compressed source data specified by Source is successfully decompressed + into Destination, then RETURN_SUCCESS is returned. If the compressed source data + specified by Source is not in a valid compressed data format, + then RETURN_INVALID_PARAMETER is returned. + + If Source is NULL, then ASSERT(). + If Destination is NULL, then ASSERT(). + If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT(). + + @param Source The source buffer containing the compressed data. + @param Destination The destination buffer to store the decompressed data + @param Scratch A temporary scratch buffer that is used to perform the decompression. + This is an optional parameter that may be NULL if the + required scratch buffer size is 0. + @param Version 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm. + + @retval RETURN_SUCCESS Decompression completed successfully, and + the uncompressed buffer is returned in Destination. + @retval RETURN_INVALID_PARAMETER + The source buffer specified by Source is corrupted + (not in a valid compressed format). +**/ +RETURN_STATUS +EFIAPI +UefiTianoDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch, + IN UINT32 Version + ) +{ + UINT32 CompSize; + UINT32 OrigSize; + SCRATCH_DATA *Sd; + CONST UINT8 *Src; + UINT8 *Dst; + + ASSERT (Source != NULL); + ASSERT (Destination != NULL); + ASSERT (Scratch != NULL); + + Src = Source; + Dst = Destination; + + Sd = (SCRATCH_DATA *) Scratch; + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return RETURN_SUCCESS; + } + + Src = Src + 8; + + SetMem (Sd, sizeof (SCRATCH_DATA), 0); + + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + switch (Version) { + case 1 : + Sd->mPBit = 4; + break; + case 2 : + Sd->mPBit = 5; + break; + default: + ASSERT (FALSE); + } + Sd->mSrcBase = (UINT8 *)Src; + Sd->mDstBase = Dst; + // + // CompSize and OrigSize are calculated in bytes + // + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + + // + // Fill the first BITBUFSIZ bits + // + FillBuf (Sd, BITBUFSIZ); + + // + // Decompress it + // + Decode (Sd); + + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + return RETURN_INVALID_PARAMETER; + } + + return RETURN_SUCCESS; +} + +/** + Decompresses a UEFI compressed source buffer. + + Extracts decompressed data to its original form. + This function is designed so that the decompression algorithm can be implemented + without using any memory services. As a result, this function is not allowed to + call any memory allocation services in its implementation. It is the caller's + responsibility to allocate and free the Destination and Scratch buffers. + If the compressed source data specified by Source is successfully decompressed + into Destination, then RETURN_SUCCESS is returned. If the compressed source data + specified by Source is not in a valid compressed data format, + then RETURN_INVALID_PARAMETER is returned. + + If Source is NULL, then ASSERT(). + If Destination is NULL, then ASSERT(). + If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT(). + + @param Source The source buffer containing the compressed data. + @param Destination The destination buffer to store the decompressed data + @param Scratch A temporary scratch buffer that is used to perform the decompression. + This is an optional parameter that may be NULL if the + required scratch buffer size is 0. + + @retval RETURN_SUCCESS Decompression completed successfully, and + the uncompressed buffer is returned in Destination. + @retval RETURN_INVALID_PARAMETER + The source buffer specified by Source is corrupted + (not in a valid compressed format). +**/ +RETURN_STATUS +EFIAPI +UefiDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch OPTIONAL + ) +{ + return UefiTianoDecompress (Source, Destination, Scratch, 1); +} + +/** + Examines a GUIDed section and returns the size of the decoded buffer and the + size of an optional scratch buffer required to actually decode the data in a GUIDed section. + + Examines a GUIDed section specified by InputSection. + If GUID for InputSection does not match the GUID that this handler supports, + then RETURN_UNSUPPORTED is returned. + If the required information can not be retrieved from InputSection, + then RETURN_INVALID_PARAMETER is returned. + If the GUID of InputSection does match the GUID that this handler supports, + then the size required to hold the decoded buffer is returned in OututBufferSize, + the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field + from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute. + + If InputSection is NULL, then ASSERT(). + If OutputBufferSize is NULL, then ASSERT(). + If ScratchBufferSize is NULL, then ASSERT(). + If SectionAttribute is NULL, then ASSERT(). + + + @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. + @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required + if the buffer specified by InputSection were decoded. + @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space + if the buffer specified by InputSection were decoded. + @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes + field of EFI_GUID_DEFINED_SECTION in the PI Specification. + + @retval RETURN_SUCCESS The information about InputSection was returned. + @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. + @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection. + +**/ +RETURN_STATUS +EFIAPI +TianoDecompressGetInfo ( + IN CONST VOID *InputSection, + OUT UINT32 *OutputBufferSize, + OUT UINT32 *ScratchBufferSize, + OUT UINT16 *SectionAttribute + ) + +{ + ASSERT (SectionAttribute != NULL); + + if (InputSection == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (IS_SECTION2 (InputSection)) { + if (!CompareGuid ( + &gTianoCustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + // + // Get guid attribute of guid section. + // + *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes; + + // + // Call Tiano GetInfo to get the required size info. + // + return UefiDecompressGetInfo ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + OutputBufferSize, + ScratchBufferSize + ); + } else { + if (!CompareGuid ( + &gTianoCustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + // + // Get guid attribute of guid section. + // + *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes; + + // + // Call Tiano GetInfo to get the required size info. + // + return UefiDecompressGetInfo ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + OutputBufferSize, + ScratchBufferSize + ); + } +} + +/** + Decompress a Tiano compressed GUIDed section into a caller allocated output buffer. + + Decodes the GUIDed section specified by InputSection. + If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned. + If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned. + If the GUID of InputSection does match the GUID that this handler supports, then InputSection + is decoded into the buffer specified by OutputBuffer and the authentication status of this + decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the + data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise, + the decoded data will be placed in caller allocated buffer specified by OutputBuffer. + + If InputSection is NULL, then ASSERT(). + If OutputBuffer is NULL, then ASSERT(). + If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT(). + If AuthenticationStatus is NULL, then ASSERT(). + + + @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. + @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation. + @param[in] ScratchBuffer A caller allocated buffer that may be required by this function + as a scratch buffer to perform the decode operation. + @param[out] AuthenticationStatus + A pointer to the authentication status of the decoded output buffer. + See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI + section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must + never be set by this handler. + + @retval RETURN_SUCCESS The buffer specified by InputSection was decoded. + @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. + @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded. + +**/ +RETURN_STATUS +EFIAPI +TianoDecompress ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + IN VOID *ScratchBuffer, OPTIONAL + OUT UINT32 *AuthenticationStatus + ) +{ + ASSERT (OutputBuffer != NULL); + ASSERT (InputSection != NULL); + + if (IS_SECTION2 (InputSection)) { + if (!CompareGuid ( + &gTianoCustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + + // + // Set Authentication to Zero. + // + *AuthenticationStatus = 0; + + // + // Call Tiano Decompress to get the raw data + // + return UefiTianoDecompress ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + *OutputBuffer, + ScratchBuffer, + 2 + ); + } else { + if (!CompareGuid ( + &gTianoCustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + + // + // Set Authentication to Zero. + // + *AuthenticationStatus = 0; + + // + // Call Tiano Decompress to get the raw data + // + return UefiTianoDecompress ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + *OutputBuffer, + ScratchBuffer, + 2 + ); + } +} + +/** + Registers TianoDecompress and TianoDecompressGetInfo handlers with TianoCustomerDecompressGuid + + @retval RETURN_SUCCESS Register successfully. + @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler. +**/ +RETURN_STATUS +EFIAPI +TianoDecompressLibConstructor ( +) +{ + return ExtractGuidedSectionRegisterHandlers ( + &gTianoCustomDecompressGuid, + TianoDecompressGetInfo, + TianoDecompress + ); +} diff --git a/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf b/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf new file mode 100644 index 0000000000..18417d1956 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf @@ -0,0 +1,48 @@ +## @file +# This library instance produces UefiDecompressLib and Tiano Custom decompression algorithm. +# Tiano custom decompression algorithm shares most of code with Uefi Decompress algorithm. +# +# 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 +# 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 = BaseUefiTianoDecompressLib + MODULE_UNI_FILE = BaseUefiTianoDecompressLib.uni + FILE_GUID = d774c4d9-c121-4da3-a5e2-0f317e3c630c + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiDecompressLib + CONSTRUCTOR = TianoDecompressLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + BaseUefiTianoCustomDecompressLibInternals.h + BaseUefiTianoCustomDecompressLib.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + ExtractGuidedSectionLib + +[Guids] + gTianoCustomDecompressGuid ## PRODUCES ## UNDEFINED # specifies tiano custom decompress algorithm. + diff --git a/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLibInternals.h b/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLibInternals.h new file mode 100644 index 0000000000..6ba3f43f75 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLibInternals.h @@ -0,0 +1,220 @@ +/** @file + Internal data structure and interfaces defintions for UEFI and Tiano Decompress Libary. + + Copyright (c) 2006 - 2009, Intel 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 __BASE_UEFI_TIANO_CUSTOM_DECOMPRESS_LIB_INTERNALS_H__ +#define __BASE_UEFI_TIANO_CUSTOM_DECOMPRESS_LIB_INTERNALS_H__ + +#include + +#include +#include +#include +#include +#include +#include + +// +// Decompression algorithm begins here +// +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define BAD_TABLE - 1 + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP +#define NPT NT +#else +#define NPT MAXNP +#endif + +typedef struct { + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; + + /// + /// The length of the field 'Position Set Code Length Array Size' in Block Header. + /// For UEFI 2.0 de/compression algorithm, mPBit = 4 + /// For Tiano de/compression algorithm, mPBit = 5 + /// + UINT8 mPBit; +} SCRATCH_DATA; + +/** + Read NumOfBit of bits from source into mBitBuf. + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + + @param Sd The global scratch data + @param NumOfBits The number of bits to shift and read. + +**/ +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ); + +/** + Get NumOfBits of bits out from mBitBuf. + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + + @param Sd The global scratch data. + @param NumOfBits The number of bits to pop and read. + + @return The bits that are popped out. + +**/ +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ); + +/** + Creates Huffman Code mapping table according to code length array. + + Creates Huffman Code mapping table for Extra Set, Char&Len Set + and Position Set according to code length array. + + @param Sd The global scratch data + @param NumOfChar Number of symbols in the symbol set + @param BitLen Code length array + @param TableBits The width of the mapping table + @param Table The table to be created. + + @retval 0 OK. + @retval BAD_TABLE The table is corrupted. + +**/ +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ); + +/** + Decodes a position value. + + Get a position value according to Position Huffman Table. + + @param Sd the global scratch data + + @return The position value decoded. + +**/ +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ); + +/** + Reads code lengths for the Extra Set or the Position Set. + + Read in the Extra Set or Pointion Set Length Arrary, then + generate the Huffman code mapping for them. + + @param Sd The global scratch data. + @param nn Number of symbols. + @param nbit Number of bits needed to represent nn. + @param Special The special symbol that needs to be taken care of. + + @retval 0 OK. + @retval BAD_TABLE Table is corrupted. + +**/ +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ); + +/** + Reads code lengths for Char&Len Set. + + Read in and decode the Char&Len Set Code Length Array, then + generate the Huffman Code mapping table for the Char&Len Set. + + @param Sd the global scratch data + +**/ +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ); + +/** + Decode a character/length value. + + Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates + Huffman code mapping table for Extra Set, Code&Len Set and + Position Set. + + @param Sd The global scratch data. + + @return The value decoded. + +**/ +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ); + +/** + Decode the source data and put the resulting data into the destination buffer. + + @param Sd The global scratch data + +**/ +VOID +Decode ( + SCRATCH_DATA *Sd + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoDecompressLib.uni b/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoDecompressLib.uni new file mode 100644 index 0000000000..f18b1ff6b1 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoDecompressLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c b/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c new file mode 100644 index 0000000000..fc9b533f2c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c @@ -0,0 +1,518 @@ +/** @file + Capsule Library instance to process capsule images. + + 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. + +**/ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/** + Function indicate the current completion progress of the firmware + update. Platform may override with own specific progress function. + + @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update + + @retval EFI_SUCESS Input capsule is a correct FMP capsule. +**/ +EFI_STATUS +EFIAPI +Update_Image_Progress ( + IN UINTN Completion +) +{ + return EFI_SUCCESS; +} + + +/** + Validate Fmp capsules layout. + + @param CapsuleHeader Points to a capsule header. + + @retval EFI_SUCESS Input capsule is a correct FMP capsule. + @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule. +**/ +EFI_STATUS +ValidateFmpCapsule ( + IN EFI_CAPSULE_HEADER *CapsuleHeader + ) +{ + EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader; + UINT8 *EndOfCapsule; + EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader; + UINT8 *EndOfPayload; + UINT64 *ItemOffsetList; + UINT32 ItemNum; + UINTN Index; + + FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); + EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize; + + if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) { + return EFI_INVALID_PARAMETER; + } + ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1); + + ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; + + if (ItemNum == FmpCapsuleHeader->EmbeddedDriverCount) { + // + // No payload element + // + if (((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]) < EndOfCapsule) { + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } + } + + if (FmpCapsuleHeader->PayloadItemCount != 0) { + // + // Check if the last payload is within capsule image range + // + ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]); + EndOfPayload = (UINT8 *)(ImageHeader + 1) + ImageHeader->UpdateImageSize + ImageHeader->UpdateVendorCodeSize; + } else { + // + // No driver & payload element in FMP + // + EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1); + } + + if (EndOfPayload != EndOfCapsule) { + return EFI_INVALID_PARAMETER; + } + + // + // All the address in ItemOffsetList must be stored in ascending order + // + if (ItemNum >= 2) { + for (Index = 0; Index < ItemNum - 1; Index++) { + if (ItemOffsetList[Index] >= ItemOffsetList[Index + 1]) { + return EFI_INVALID_PARAMETER; + } + } + } + + return EFI_SUCCESS; +} + +/** + Process Firmware management protocol data capsule. + + @param CapsuleHeader Points to a capsule header. + + @retval EFI_SUCESS Process Capsule Image successfully. + @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. + @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. + @retval EFI_OUT_OF_RESOURCES Not enough memory. +**/ +EFI_STATUS +ProcessFmpCapsuleImage ( + IN EFI_CAPSULE_HEADER *CapsuleHeader + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader; + EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader; + EFI_HANDLE ImageHandle; + UINT64 *ItemOffsetList; + UINT32 ItemNum; + UINTN Index; + UINTN ExitDataSize; + EFI_HANDLE *HandleBuffer; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; + UINTN NumberOfHandles; + UINTN DescriptorSize; + UINT8 FmpImageInfoCount; + UINT32 FmpImageInfoDescriptorVer; + UINTN ImageInfoSize; + UINT32 PackageVersion; + CHAR16 *PackageVersionName; + CHAR16 *AbortReason; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo; + UINTN DriverLen; + UINTN Index1; + UINTN Index2; + MEMMAP_DEVICE_PATH MemMapNode; + EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath; + + Status = EFI_SUCCESS; + HandleBuffer = NULL; + ExitDataSize = 0; + DriverDevicePath = NULL; + + FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); + + if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) { + return EFI_INVALID_PARAMETER; + } + ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1); + + ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; + + // + // capsule in which driver count and payload count are both zero is not processed. + // + if (ItemNum == 0) { + return EFI_SUCCESS; + } + + // + // 1. ConnectAll to ensure + // All the communication protocol required by driver in capsule installed + // All FMP protocols are installed + // + BdsLibConnectAll(); + + + // + // 2. Try to load & start all the drivers within capsule + // + SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode)); + MemMapNode.Header.Type = HARDWARE_DEVICE_PATH; + MemMapNode.Header.SubType = HW_MEMMAP_DP; + MemMapNode.MemoryType = EfiBootServicesCode; + MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader; + MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1); + + DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header); + if (DriverDevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) { + if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) { + // + // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER + // + DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index]; + } else { + DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index]; + } + + Status = gBS->LoadImage( + FALSE, + gImageHandle, + DriverDevicePath, + (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index], + DriverLen, + &ImageHandle + ); + if (EFI_ERROR(Status)) { + goto EXIT; + } + + Status = gBS->StartImage( + ImageHandle, + &ExitDataSize, + NULL + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status)); + goto EXIT; + } + } + + // + // Connnect all again to connect drivers within capsule + // + if (FmpCapsuleHeader->EmbeddedDriverCount > 0) { + BdsLibConnectAll(); + } + + // + // 3. Route payload to right FMP instance + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareManagementProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + + if (!EFI_ERROR(Status)) { + for(Index1 = 0; Index1 < NumberOfHandles; Index1++) { + Status = gBS->HandleProtocol( + HandleBuffer[Index1], + &gEfiFirmwareManagementProtocolGuid, + (VOID **)&Fmp + ); + if (EFI_ERROR(Status)) { + continue; + } + + ImageInfoSize = 0; + Status = Fmp->GetImageInfo ( + Fmp, + &ImageInfoSize, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + ); + if (Status != EFI_BUFFER_TOO_SMALL) { + continue; + } + + FmpImageInfoBuf = NULL; + FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize); + if (FmpImageInfoBuf == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + PackageVersionName = NULL; + Status = Fmp->GetImageInfo ( + Fmp, + &ImageInfoSize, // ImageInfoSize + FmpImageInfoBuf, // ImageInfo + &FmpImageInfoDescriptorVer, // DescriptorVersion + &FmpImageInfoCount, // DescriptorCount + &DescriptorSize, // DescriptorSize + &PackageVersion, // PackageVersion + &PackageVersionName // PackageVersionName + ); + + // + // If FMP GetInformation interface failed, skip this resource + // + if (EFI_ERROR(Status)) { + FreePool(FmpImageInfoBuf); + continue; + } + + if (PackageVersionName != NULL) { + FreePool(PackageVersionName); + } + + TempFmpImageInfo = FmpImageInfoBuf; + for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) { + // + // Check all the payload entry in capsule payload list + // + for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) { + ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]); + if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) && + ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) { + AbortReason = NULL; + if (ImageHeader->UpdateVendorCodeSize == 0) { + Status = Fmp->SetImage( + Fmp, + TempFmpImageInfo->ImageIndex, // ImageIndex + (UINT8 *)(ImageHeader + 1), // Image + ImageHeader->UpdateImageSize, // ImageSize + NULL, // VendorCode + Update_Image_Progress, // Progress + &AbortReason // AbortReason + ); + } else { + Status = Fmp->SetImage( + Fmp, + TempFmpImageInfo->ImageIndex, // ImageIndex + (UINT8 *)(ImageHeader + 1), // Image + ImageHeader->UpdateImageSize, // ImageSize + (UINT8 *)((UINT8 *) (ImageHeader + 1) + ImageHeader->UpdateImageSize), // VendorCode + Update_Image_Progress, // Progress + &AbortReason // AbortReason + ); + } + if (AbortReason != NULL) { + DEBUG ((EFI_D_ERROR, "%s\n", AbortReason)); + FreePool(AbortReason); + } + } + } + // + // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version + // + TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize); + } + FreePool(FmpImageInfoBuf); + } + } + +EXIT: + + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + + if (DriverDevicePath != NULL) { + FreePool(DriverDevicePath); + } + + return Status; +} + +/** + Those capsules supported by the firmwares. + + @param CapsuleHeader Points to a capsule header. + + @retval EFI_SUCESS Input capsule is supported by firmware. + @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware. + @retval EFI_INVALID_PARAMETER Input capsule layout is not correct +**/ +EFI_STATUS +EFIAPI +SupportCapsuleImage ( + IN EFI_CAPSULE_HEADER *CapsuleHeader + ) +{ + if (CompareGuid (&gEfiCapsuleGuid, &CapsuleHeader->CapsuleGuid)) { + return EFI_SUCCESS; + } + + if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)) { + // + // Check layout of FMP capsule + // + return ValidateFmpCapsule(CapsuleHeader); + } + + return EFI_UNSUPPORTED; +} + +/** + The firmware implements to process the capsule image. + + @param CapsuleHeader Points to a capsule header. + + @retval EFI_SUCESS Process Capsule Image successfully. + @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. + @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. + @retval EFI_OUT_OF_RESOURCES Not enough memory. +**/ +EFI_STATUS +EFIAPI +ProcessCapsuleImage ( + IN EFI_CAPSULE_HEADER *CapsuleHeader + ) +{ + UINT32 Length; + EFI_FIRMWARE_VOLUME_HEADER *FvImage; + EFI_FIRMWARE_VOLUME_HEADER *ProcessedFvImage; + EFI_STATUS Status; + EFI_HANDLE FvProtocolHandle; + UINT32 FvAlignment; + + FvImage = NULL; + ProcessedFvImage = NULL; + Status = EFI_SUCCESS; + + if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) { + return EFI_UNSUPPORTED; + } + + // + // Check FMP capsule layout + // + if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)){ + Status = ValidateFmpCapsule(CapsuleHeader); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Press EFI FMP Capsule + // + return ProcessFmpCapsuleImage(CapsuleHeader); + } + + // + // Skip the capsule header, move to the Firware Volume + // + FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); + Length = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize; + + while (Length != 0) { + // + // Point to the next firmware volume header, and then + // call the DXE service to process it. + // + if (FvImage->FvLength > (UINTN) Length) { + // + // Notes: need to stuff this status somewhere so that the + // error can be detected at OS runtime + // + Status = EFI_VOLUME_CORRUPTED; + break; + } + + FvAlignment = 1 << ((FvImage->Attributes & EFI_FVB2_ALIGNMENT) >> 16); + // + // FvAlignment must be more than 8 bytes required by FvHeader structure. + // + if (FvAlignment < 8) { + FvAlignment = 8; + } + // + // Check FvImage Align is required. + // + if (((UINTN) FvImage % FvAlignment) == 0) { + ProcessedFvImage = FvImage; + } else { + // + // Allocate new aligned buffer to store FvImage. + // + ProcessedFvImage = (EFI_FIRMWARE_VOLUME_HEADER *) AllocateAlignedPages ((UINTN) EFI_SIZE_TO_PAGES ((UINTN) FvImage->FvLength), (UINTN) FvAlignment); + if (ProcessedFvImage == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + CopyMem (ProcessedFvImage, FvImage, (UINTN) FvImage->FvLength); + } + + Status = gDS->ProcessFirmwareVolume ( + (VOID *) ProcessedFvImage, + (UINTN) ProcessedFvImage->FvLength, + &FvProtocolHandle + ); + if (EFI_ERROR (Status)) { + break; + } + // + // Call the dispatcher to dispatch any drivers from the produced firmware volume + // + gDS->Dispatch (); + // + // On to the next FV in the capsule + // + Length -= (UINT32) FvImage->FvLength; + FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) FvImage + FvImage->FvLength); + } + + return Status; +} + + diff --git a/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf b/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf new file mode 100644 index 0000000000..28b4693c1f --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf @@ -0,0 +1,55 @@ +## @file +# Capsule library instance for DXE_DRIVER, DXE_RUNTIME_DRIVER. +# +# Copyright (c) 2007 - 2015, Intel 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 = DxeCapsuleLib + MODULE_UNI_FILE = DxeCapsuleLib.uni + FILE_GUID = 654950df-1ede-4b04-b144-6b77845736ad + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = CapsuleLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DxeCapsuleLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + DxeServicesTableLib + GenericBdsLib + UefiBootServicesTableLib + DevicePathLib + +[Protocols] + gEfiFirmwareManagementProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + gEfiCapsuleGuid ## SOMETIMES_CONSUMES ## GUID # Capsule Image Header Guid + gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID diff --git a/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.uni b/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.uni new file mode 100644 index 0000000000..8191bfa72d Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf b/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf new file mode 100644 index 0000000000..a97d4e8aac --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf @@ -0,0 +1,58 @@ +## @file +# Framework DXE report status code library to support EFI1.1 and UEFI2.0 system. +# +# 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 +# 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 = DxeReportStatusCodeLib + MODULE_UNI_FILE = DxeReportStatusCodeLib.uni + FILE_GUID = 3ddc3b12-99ea-4364-b315-6310a2050be5 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ReportStatusCodeLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + ReportStatusCodeLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + PcdLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + DebugLib + UefiRuntimeServicesTableLib + DevicePathLib + +[Guids] + gEfiStatusCodeSpecificDataGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## UNDEFINED + +[Protocols] + gEfiStatusCodeRuntimeProtocolGuid ## SOMETIMES_CONSUMES # Used if revision of the EFI Specification is not less than 0x20000 + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask ## CONSUMES + diff --git a/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.uni b/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.uni new file mode 100644 index 0000000000..befd970aa5 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/ReportStatusCodeLib.c b/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/ReportStatusCodeLib.c new file mode 100644 index 0000000000..a3603f862f --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/ReportStatusCodeLib.c @@ -0,0 +1,634 @@ +/** @file + Report Status Code Library for DXE Phase. + + Copyright (c) 2006 - 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// +// Define the maximum extended data size that is supported when a status code is +// reported at TPL_HIGH_LEVEL. +// +#define MAX_EXTENDED_DATA_SIZE 0x200 + +EFI_REPORT_STATUS_CODE mReportStatusCode = NULL; + +/** + Locate the report status code service. + + @return Function pointer to the report status code service. + NULL is returned if no status code service is available. + +**/ +EFI_REPORT_STATUS_CODE +InternalGetReportStatusCode ( + VOID + ) +{ + EFI_STATUS_CODE_PROTOCOL *StatusCodeProtocol; + EFI_STATUS Status; + + if (gRT != NULL && gRT->Hdr.Revision < 0x20000) { + return ((FRAMEWORK_EFI_RUNTIME_SERVICES*)gRT)->ReportStatusCode; + } else if (gBS != NULL && gBS->LocateProtocol != NULL) { + Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol); + if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) { + return StatusCodeProtocol->ReportStatusCode; + } + } + + return NULL; +} + +/** + Internal worker function that reports a status code through the status code service. + + If status code service is not cached, then this function checks if status code service is + available in system. If status code service is not available, then EFI_UNSUPPORTED is + returned. If status code service is present, then it is cached in mReportStatusCode. + Finally this function reports status code through the status code service. + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. This is an optional parameter that may be + NULL. + @param Data Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_UNSUPPORTED Status code service is not available. + @retval EFI_UNSUPPORTED Status code type is not supported. + +**/ +EFI_STATUS +InternalReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + if ((ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) || + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)) { + // + // If mReportStatusCode is NULL, then check if status code service is available in system. + // + if (mReportStatusCode == NULL) { + mReportStatusCode = InternalGetReportStatusCode (); + if (mReportStatusCode == NULL) { + return EFI_UNSUPPORTED; + } + } + + // + // A status code service is present in system, so pass in all the parameters to the service. + // + return (*mReportStatusCode) (Type, Value, Instance, (EFI_GUID *)CallerId, Data); + } + + return EFI_UNSUPPORTED; +} + + +/** + Converts a status code to an 8-bit POST code value. + + Converts the status code specified by CodeType and Value to an 8-bit POST code + and returns the 8-bit POST code in PostCode. If CodeType is an + EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode + are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits + 24..26 of Value., and TRUE is returned. Otherwise, FALSE is returned. + + If PostCode is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param PostCode A pointer to the 8-bit POST code value to return. + + @retval TRUE The status code specified by CodeType and Value was converted + to an 8-bit POST code and returned in PostCode. + @retval FALSE The status code specified by CodeType and Value could not be + converted to an 8-bit POST code value. + +**/ +BOOLEAN +EFIAPI +CodeTypeToPostCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + OUT UINT8 *PostCode + ) +{ + // + // If PostCode is NULL, then ASSERT() + // + ASSERT (PostCode != NULL); + + // + // Convert Value to an 8 bit post code + // + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || + ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ) { + *PostCode = (UINT8) ((((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5) | + (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f)); + return TRUE; + } + return FALSE; +} + + +/** + Extracts ASSERT() information from a status code structure. + + Converts the status code specified by CodeType, Value, and Data to the ASSERT() + arguments specified by Filename, Description, and LineNumber. If CodeType is + an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and + Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract + Filename, Description, and LineNumber from the optional data area of the + status code buffer specified by Data. The optional data area of Data contains + a Null-terminated ASCII string for the FileName, followed by a Null-terminated + ASCII string for the Description, followed by a 32-bit LineNumber. If the + ASSERT() information could be extracted from Data, then return TRUE. + Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If Filename is NULL, then ASSERT(). + If Description is NULL, then ASSERT(). + If LineNumber is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param Data Pointer to status code data buffer. + @param Filename Pointer to the source file name that generated the ASSERT(). + @param Description Pointer to the description of the ASSERT(). + @param LineNumber Pointer to source line number that generated the ASSERT(). + + @retval TRUE The status code specified by CodeType, Value, and Data was + converted ASSERT() arguments specified by Filename, Description, + and LineNumber. + @retval FALSE The status code specified by CodeType, Value, and Data could + not be converted to ASSERT() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractAssertInfo ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST EFI_STATUS_CODE_DATA *Data, + OUT CHAR8 **Filename, + OUT CHAR8 **Description, + OUT UINT32 *LineNumber + ) +{ + EFI_DEBUG_ASSERT_DATA *AssertData; + + ASSERT (Data != NULL); + ASSERT (Filename != NULL); + ASSERT (Description != NULL); + ASSERT (LineNumber != NULL); + + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && + ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) && + ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) { + AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1); + *Filename = (CHAR8 *)(AssertData + 1); + *Description = *Filename + AsciiStrLen (*Filename) + 1; + *LineNumber = AssertData->LineNumber; + return TRUE; + } + return FALSE; +} + + +/** + Extracts DEBUG() information from a status code structure. + + Converts the status code specified by Data to the DEBUG() arguments specified + by ErrorLevel, Marker, and Format. If type GUID in Data is + EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and + Format from the optional data area of the status code buffer specified by Data. + The optional data area of Data contains a 32-bit ErrorLevel followed by Marker + which is 12 UINTN parameters, followed by a Null-terminated ASCII string for + the Format. If the DEBUG() information could be extracted from Data, then + return TRUE. Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If ErrorLevel is NULL, then ASSERT(). + If Marker is NULL, then ASSERT(). + If Format is NULL, then ASSERT(). + + @param Data Pointer to status code data buffer. + @param ErrorLevel Pointer to error level mask for a debug message. + @param Marker Pointer to the variable argument list associated with Format. + @param Format Pointer to a Null-terminated ASCII format string of a + debug message. + + @retval TRUE The status code specified by Data was converted DEBUG() arguments + specified by ErrorLevel, Marker, and Format. + @retval FALSE The status code specified by Data could not be converted to + DEBUG() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractDebugInfo ( + IN CONST EFI_STATUS_CODE_DATA *Data, + OUT UINT32 *ErrorLevel, + OUT BASE_LIST *Marker, + OUT CHAR8 **Format + ) +{ + EFI_DEBUG_INFO *DebugInfo; + + ASSERT (Data != NULL); + ASSERT (ErrorLevel != NULL); + ASSERT (Marker != NULL); + ASSERT (Format != NULL); + + // + // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE + // + if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) { + return FALSE; + } + + // + // Retrieve the debug information from the status code record + // + DebugInfo = (EFI_DEBUG_INFO *)(Data + 1); + + *ErrorLevel = DebugInfo->ErrorLevel; + + // + // The first 12 * sizeof (UINT64) bytes following EFI_DEBUG_INFO are for variable arguments + // of format in DEBUG string. Its address is returned in Marker and has to be 64-bit aligned. + // It must be noticed that EFI_DEBUG_INFO follows EFI_STATUS_CODE_DATA, whose size is + // 20 bytes. The size of EFI_DEBUG_INFO is 4 bytes, so we can ensure that Marker + // returned is 64-bit aligned. + // 64-bit aligned is a must, otherwise retrieving 64-bit parameter from BASE_LIST will + // cause unalignment exception. + // + *Marker = (BASE_LIST) (DebugInfo + 1); + *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12); + + return TRUE; +} + + +/** + Reports a status code. + + Reports the status code specified by the parameters Type and Value. Status + code also require an instance, caller ID, and extended data. This function + passed in a zero instance, NULL extended data, and a caller ID of + gEfiCallerIdGuid, which is the GUID for the module. + + ReportStatusCode()must actively prevent recusrsion. If ReportStatusCode() + is called while processing another any other Report Status Code Library function, + then ReportStatusCode() must return immediately. + + @param Type Status code type. + @param Value Status code value. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_DEVICE_ERROR There status code could not be reported due to a + device error. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value + ) +{ + return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL); +} + + +/** + Reports a status code with a Device Path Protocol as the extended data. + + Allocates and fills in the extended data section of a status code with the + Device Path Protocol specified by DevicePath. This function is responsible + for allocating a buffer large enough for the standard header and the device + path. The standard header is filled in with a GUID of + gEfiStatusCodeSpecificDataGuid. The status code is reported with a zero + instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithDevicePath()must actively prevent recursion. If + ReportStatusCodeWithDevicePath() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithDevicePath() + must return EFI_DEVICE_ERROR immediately. + + If DevicePath is NULL, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param DevicePath Pointer to the Device Path Protocol to be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by DevicePath. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithDevicePath ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ASSERT (DevicePath != NULL); + return ReportStatusCodeWithExtendedData ( + Type, + Value, + (VOID *)DevicePath, + GetDevicePathSize (DevicePath) + ); +} + + +/** + Reports a status code with an extended data buffer. + + Allocates and fills in the extended data section of a status code with the + extended data specified by ExtendedData and ExtendedDataSize. ExtendedData + is assumed to be one of the data structures specified in Related Definitions. + These data structure do not have the standard header, so this function is + responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled + in with a GUID of gEfiStatusCodeSpecificDataGuid. The status code is reported + with a zero instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithExtendedData()must actively prevent recursion. If + ReportStatusCodeWithExtendedData() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithExtendedData() + must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL, then ASSERT(). + If ExtendedDataSize is 0, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param ExtendedData Pointer to the extended data buffer to be reported. + @param ExtendedDataSize The size, in bytes, of the extended data buffer to + be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by ExtendedData and ExtendedDataSize. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithExtendedData ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST VOID *ExtendedData, + IN UINTN ExtendedDataSize + ) +{ + ASSERT (ExtendedData != NULL); + ASSERT (ExtendedDataSize != 0); + return ReportStatusCodeEx ( + Type, + Value, + 0, + NULL, + NULL, + ExtendedData, + ExtendedDataSize + ); +} + + +/** + Reports a status code with full parameters. + + The function reports a status code. If ExtendedData is NULL and ExtendedDataSize + is 0, then an extended data buffer is not reported. If ExtendedData is not + NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. + ExtendedData is assumed not have the standard status code header, so this function + is responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled in + with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a + GUID of gEfiStatusCodeSpecificDataGuid is used. The status code is reported with + an instance specified by Instance and a caller ID specified by CallerId. If + CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. + + ReportStatusCodeEx()must actively prevent recursion. If + ReportStatusCodeEx() is called while processing another any + other Report Status Code Library function, then + ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). + If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. If this parameter is NULL, then a caller + ID of gEfiCallerIdGuid is used. + @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. + If this parameter is NULL, then a the status code + standard header is filled in with + gEfiStatusCodeSpecificDataGuid. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate + the extended data section if it was specified. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeEx ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId OPTIONAL, + IN CONST EFI_GUID *ExtendedDataGuid OPTIONAL, + IN CONST VOID *ExtendedData OPTIONAL, + IN UINTN ExtendedDataSize + ) +{ + EFI_STATUS Status; + EFI_STATUS_CODE_DATA *StatusCodeData; + EFI_TPL Tpl; + UINT64 Buffer[(MAX_EXTENDED_DATA_SIZE / sizeof (UINT64)) + 1]; + + ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); + ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); + + if (gBS == NULL || gBS->AllocatePool == NULL || gBS->FreePool == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Retrieve the current TPL + // + Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + gBS->RestoreTPL (Tpl); + + StatusCodeData = NULL; + if (Tpl <= TPL_NOTIFY) { + // + // Allocate space for the Status Code Header and its buffer + // + gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData); + } + + if (StatusCodeData == NULL) { + // + // If a buffer could not be allocated, then see if the local variable Buffer can be used + // + if (ExtendedDataSize > (MAX_EXTENDED_DATA_SIZE - sizeof (EFI_STATUS_CODE_DATA))) { + // + // The local variable Buffer not large enough to hold the extended data associated + // with the status code being reported. + // + DEBUG ((EFI_D_ERROR, "Status code extended data is too large to be reported!\n")); + return EFI_OUT_OF_RESOURCES; + } + StatusCodeData = (EFI_STATUS_CODE_DATA *)Buffer; + } + + // + // Fill in the extended data header + // + StatusCodeData->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA); + StatusCodeData->Size = (UINT16)ExtendedDataSize; + if (ExtendedDataGuid == NULL) { + ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid; + } + CopyGuid (&StatusCodeData->Type, ExtendedDataGuid); + + // + // Fill in the extended data buffer + // + if (ExtendedData != NULL) { + CopyMem (StatusCodeData + 1, ExtendedData, ExtendedDataSize); + } + + // + // Report the status code + // + if (CallerId == NULL) { + CallerId = &gEfiCallerIdGuid; + } + Status = InternalReportStatusCode (Type, Value, Instance, CallerId, StatusCodeData); + + // + // Free the allocated buffer + // + if (StatusCodeData != (EFI_STATUS_CODE_DATA *)Buffer) { + gBS->FreePool (StatusCodeData); + } + + return Status; +} + + +/** + Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportProgressCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_ERROR_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportErrorCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportDebugCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} diff --git a/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c new file mode 100644 index 0000000000..bba62a801a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c @@ -0,0 +1,4356 @@ +/** @file + BDS Lib functions which relate with create or process the boot option. + +Copyright (c) 2004 - 2016, Intel 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 + ); + // + // Deleting variable with existing variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + // + // 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 + // + UnicodeStrToAsciiStrS (BootDesc, HelpString, sizeof (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; + } + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (BootOrder == NULL) { + return EFI_NOT_FOUND; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + 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 + ); + // + // Shrinking variable with existing variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + 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)) { + ASSERT (BootOrder != NULL); + 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_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_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 *) ((UINTN) 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; + } + } + + FreePool (DeviceType); + + 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; + LIST_ENTRY TempBootLists; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + + Status = EFI_SUCCESS; + *ExitDataSize = 0; + *ExitData = 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. + // + SetVariableAndReportStatusCodeOnError ( + L"BootCurrent", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT16), + &Option->BootCurrent + ); + } + + // + // Signal the EVT_SIGNAL_READY_TO_BOOT event + // + EfiSignalEventReadyToBoot(); + + // + // Report Status Code to indicate ReadyToBoot event was signalled + // + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT)); + + // + // 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 + // Deleting variable with current implementation shouldn't fail. + // + gRT->SetVariable ( + L"BootCurrent", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 0, + NULL + ); + + 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 + // + GetVariable2 ( + HD_BOOT_DEVICE_PATH_VARIABLE_NAME, + &gHdBootDevicePathVariablGuid, + (VOID **) &CachedDevicePath, + &CachedDevicePathSize + ); + + // + // Delete the invalid HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable. + // + if ((CachedDevicePath != NULL) && !IsDevicePathValid (CachedDevicePath, CachedDevicePathSize)) { + FreePool (CachedDevicePath); + CachedDevicePath = NULL; + Status = gRT->SetVariable ( + HD_BOOT_DEVICE_PATH_VARIABLE_NAME, + &gHdBootDevicePathVariablGuid, + 0, + 0, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + + 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 + // Failure to set the variable only impacts the performance when next time expanding the short-form device path. + // + Status = gRT->SetVariable ( + HD_BOOT_DEVICE_PATH_VARIABLE_NAME, + &gHdBootDevicePathVariablGuid, + EFI_VARIABLE_BOOTSERVICE_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 + // Failure to set the variable only impacts the performance when next time expanding the short-form device path. + // + Status = gRT->SetVariable ( + HD_BOOT_DEVICE_PATH_VARIABLE_NAME, + &gHdBootDevicePathVariablGuid, + EFI_VARIABLE_BOOTSERVICE_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 + ); + // + // Shrinking variable with existing variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + 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 + ); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + // + // 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 + ); + // + // Shrinking variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + 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 + ); + // + // Failure to set the variable only impacts the performance next time enumerating the boot options. + // + + 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 logical partition + // + if (EFI_ERROR (Status) || BlkIo->Media->LogicalPartition) { + continue; + } + + // + // firstly fixed block io then the removable block io + // + if (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: + default: + 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; + } + } + } + + 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)), Index); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK))); + } + 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 + ) +{ + EFI_STATUS Status; + 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) { + Status = gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + // + // 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); + FreePool(BootOption); + FreePool(BootNext); + } + +} + +/** + 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); + ASSERT (NewDevicePath != NULL); + *DevicePath = NewDevicePath; + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} diff --git a/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c new file mode 100644 index 0000000000..f487aa611a --- /dev/null +++ b/Core/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/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c new file mode 100644 index 0000000000..eefec0642a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c @@ -0,0 +1,1301 @@ +/** @file + BDS Lib functions which contain all the code to connect console device + +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 +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 handle 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 handle 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 = SetVariableAndReportStatusCodeOnError ( + ConVarName, + &gEfiGlobalVariableGuid, + Attributes, + DevicePathSize, + NewDevicePath + ); + if ((DevicePathSize == 0) && (Status == EFI_NOT_FOUND)) { + Status = EFI_SUCCESS; + } + + 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/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c new file mode 100644 index 0000000000..24c1998a14 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c @@ -0,0 +1,1589 @@ +/** @file + Misc BDS library function + +Copyright (c) 2004 - 2015, Intel 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; + } + FreePool(OptionBuffer); + 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; + + if (DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + 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)) { + FreePool(OptionPtr); + 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)) { + FreePool (Variable); + 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) { + FreePool (Variable); + 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); + StrCpyS ( + StringBuffer1, + MAX_STRING_LEN, + L"Configuration changed. Reset to apply it Now." + ); + StrCpyS ( + StringBuffer2, + MAX_STRING_LEN, + 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 = SetVariableAndReportStatusCodeOnError ( + EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, + &gEfiMemoryTypeInformationGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + VariableSize, + PreviousMemoryTypeInformation + ); + + if (!EFI_ERROR (Status)) { + // + // 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); + } + } else { + DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n")); + } + } +} + +/** + 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); +} + +/** + Set the variable and report the error through status code upon failure. + + @param VariableName A Null-terminated string that is the name of the vendor's variable. + Each VariableName is unique for each VendorGuid. VariableName must + contain 1 or more characters. If VariableName is an empty string, + then EFI_INVALID_PARAMETER is returned. + @param VendorGuid A unique identifier for the vendor. + @param Attributes Attributes bitmask to set for the variable. + @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero + causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is + set, then a SetVariable() call with a DataSize of zero will not cause any change to + the variable value (the timestamp associated with the variable may be updated however + even if no new data value is provided,see the description of the + EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not + be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). + @param Data The contents for the variable. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as + defined by the Attributes. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the + DataSize exceeds the maximum allowed. + @retval EFI_INVALID_PARAMETER VariableName is an empty string. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + @retval EFI_WRITE_PROTECTED The variable in question is read-only. + @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. + @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS + or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo + does NOT pass the validation check carried out by the firmware. + + @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. +**/ +EFI_STATUS +SetVariableAndReportStatusCodeOnError ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + EFI_STATUS Status; + EDKII_SET_VARIABLE_STATUS *SetVariableStatus; + UINTN NameSize; + + Status = gRT->SetVariable ( + VariableName, + VendorGuid, + Attributes, + DataSize, + Data + ); + if (EFI_ERROR (Status)) { + NameSize = StrSize (VariableName); + SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize); + if (SetVariableStatus != NULL) { + CopyGuid (&SetVariableStatus->Guid, VendorGuid); + SetVariableStatus->NameSize = NameSize; + SetVariableStatus->DataSize = DataSize; + SetVariableStatus->SetStatus = Status; + SetVariableStatus->Attributes = Attributes; + CopyMem (SetVariableStatus + 1, VariableName, NameSize); + if ((Data != NULL) && (DataSize != 0)) { + CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data, DataSize); + } + + REPORT_STATUS_CODE_EX ( + EFI_ERROR_CODE, + PcdGet32 (PcdErrorCodeSetVariable), + 0, + NULL, + &gEdkiiStatusCodeDataTypeVariableGuid, + SetVariableStatus, + sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize + ); + + FreePool (SetVariableStatus); + } + } + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c new file mode 100644 index 0000000000..2f22e7df7f --- /dev/null +++ b/Core/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/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf new file mode 100644 index 0000000000..5a138a9169 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf @@ -0,0 +1,145 @@ +## @file +# General BDS library. +# +# 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 - 2014, Intel 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 + MODULE_UNI_FILE = GenericBdsLib.uni + 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] + ## SOMETIMES_CONSUMES ## HOB # The hob holding memory type information + ## SOMETIMES_CONSUMES ## SystemTable # The identifier of memory type information type in system table + ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation" + ## SOMETIMES_PRODUCES ## Variable:L"MemoryTypeInformation" + gEfiMemoryTypeInformationGuid + ## SOMETIMES_CONSUMES ## Variable:L"BootXXXX" # Boot option variable + ## SOMETIMES_PRODUCES ## Variable:L"BootXXXX" # Boot option variable + ## SOMETIMES_CONSUMES ## Variable:L"DriverXXXX" # Driver load option. + ## SOMETIMES_PRODUCES ## Variable:L"DriverXXXX" # Driver load option. + ## SOMETIMES_CONSUMES ## Variable:L"BootNext" # Next Boot Option + ## SOMETIMES_PRODUCES ## Variable:L"BootNext" # Next Boot Option + ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" # The boot option array + ## SOMETIMES_PRODUCES ## Variable:L"BootOrder" # The boot option array + ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" # The driver order list + ## SOMETIMES_CONSUMES ## Variable:L"ConIn" # The device path of console in device + ## SOMETIMES_PRODUCES ## Variable:L"ConIn" # The device path of console in device + ## SOMETIMES_CONSUMES ## Variable:L"ConOut" # The device path of console out device + ## SOMETIMES_PRODUCES ## Variable:L"ConOut" # The device path of console out device + ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" # The device path of error out device + ## SOMETIMES_PRODUCES ## Variable:L"ErrOut" # The device path of error out device + ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" # The boot option of current boot + ## SOMETIMES_PRODUCES ## Variable:L"BootNext" # The number of next boot option + gEfiGlobalVariableGuid + gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID + gPerformanceProtocolGuid ## SOMETIMES_PRODUCES ## Variable:L"PerfDataMemAddr" # The ACPI address of performance data + 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 ## CONSUMES ## HII # HII String PackageList Guid + ## SOMETIMES_PRODUCES ## Variable:L"LegacyDevOrder" + ## SOMETIMES_CONSUMES ## Variable:L"LegacyDevOrder" + gEfiLegacyDevOrderVariableGuid + gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID + +[Protocols] + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadFileProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimpleTextOutProtocolGuid ## CONSUMES + gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimpleNetworkProtocolGuid ## SOMETIMES_CONSUMES + gEfiDebugPortProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimpleTextInProtocolGuid ## CONSUMES + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES + gEfiCpuArchProtocolGuid ## CONSUMES + gEfiDevicePathProtocolGuid ## CONSUMES + gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES + gEfiUgaDrawProtocolGuid |gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## SOMETIMES_CONSUMES + gEfiOEMBadgingProtocolGuid ## SOMETIMES_CONSUMES + gEfiHiiFontProtocolGuid ## CONSUMES + gEfiUserManagerProtocolGuid ## SOMETIMES_CONSUMES + gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootlogoOnlyEnable ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile ## CONSUMES + +# +# [BootMode] +# RECOVERY_FULL ## SOMETIMES_CONSUMES # Memory Type Information variable +# + diff --git a/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.uni b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.uni new file mode 100644 index 0000000000..5611f6f6bf Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni new file mode 100644 index 0000000000..7c3b4f9690 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h new file mode 100644 index 0000000000..7201d8a335 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h @@ -0,0 +1,194 @@ +/** @file + BDS library definition, include the file and data structure + +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 +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 + ); + +/** + Set the variable and report the error through status code upon failure. + + @param VariableName A Null-terminated string that is the name of the vendor's variable. + Each VariableName is unique for each VendorGuid. VariableName must + contain 1 or more characters. If VariableName is an empty string, + then EFI_INVALID_PARAMETER is returned. + @param VendorGuid A unique identifier for the vendor. + @param Attributes Attributes bitmask to set for the variable. + @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero + causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is + set, then a SetVariable() call with a DataSize of zero will not cause any change to + the variable value (the timestamp associated with the variable may be updated however + even if no new data value is provided,see the description of the + EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not + be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). + @param Data The contents for the variable. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as + defined by the Attributes. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the + DataSize exceeds the maximum allowed. + @retval EFI_INVALID_PARAMETER VariableName is an empty string. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + @retval EFI_WRITE_PROTECTED The variable in question is read-only. + @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. + @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS + or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo + does NOT pass the validation check carried out by the firmware. + + @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. +**/ +EFI_STATUS +SetVariableAndReportStatusCodeOnError ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + +#endif // _BDS_LIB_H_ diff --git a/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c new file mode 100644 index 0000000000..e50345a597 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c @@ -0,0 +1,313 @@ +/** @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 - 2015, Intel 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) { + AsciiStrCpyS (GaugeString, PERF_TOKEN_SIZE, " "); + } 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) { + 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; + + AsciiStrCpyS (GaugeString, PERF_TOKEN_SIZE, " "); + + // + // 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_SIZE]; + 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 VarSize; + BOOLEAN Found; + + // + // 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; + } + + // + // Reset the entry count + // + mPerfHeader.Count = 0; + + 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); + + // + // Get performance data + // + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Handle, + &Token, + &Module, + &StartTicker, + &EndTicker)) != 0) { + if (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) { + continue; + } + + ZeroMem (&mPerfData, sizeof (PERF_DATA)); + + mPerfData.Duration = Duration; + + // + // See if the Handle is in the handle buffer + // + Found = FALSE; + for (Index = 0; Index < NoHandles; Index++) { + if (Handle == Handles[Index]) { + GetNameFromHandle (Handles[Index], GaugeString); + AsciiStrCpyS (mPerfData.Token, PERF_TOKEN_SIZE, GaugeString); + Found = TRUE; + break; + } + } + + if (!Found) { + AsciiStrnCpyS (mPerfData.Token, PERF_TOKEN_SIZE, Token, PERF_TOKEN_LENGTH); + } + + CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA)); + Ptr += sizeof (PERF_DATA); + + mPerfHeader.Count++; + if (mPerfHeader.Count == LimitCount) { + goto Done; + } + } + } + +Done: + + FreePool (Handles); + + mPerfHeader.Signiture = PERFORMANCE_SIGNATURE; + + // + // Put performance data to Reserved memory + // + CopyMem ( + (UINTN *) (UINTN) mAcpiLowMemoryBase, + &mPerfHeader, + sizeof (PERF_HEADER) + ); + + return ; +} diff --git a/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c new file mode 100644 index 0000000000..762871605d --- /dev/null +++ b/Core/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/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h b/Core/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h new file mode 100644 index 0000000000..13b745de87 --- /dev/null +++ b/Core/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/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c new file mode 100644 index 0000000000..bb320f37b2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c @@ -0,0 +1,1456 @@ +/** @file + Legacy Boot Maintainence UI implementation. + +Copyright (c) 2004 - 2015, Intel 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 "LegacyBootMaintUi.h" + +LEGACY_BOOT_OPTION_CALLBACK_DATA *mLegacyBootOptionPrivate; +EFI_GUID mLegacyBootOptionGuid = LEGACY_BOOT_OPTION_FORMSET_GUID; +CHAR16 mLegacyBootStorageName[] = L"LegacyBootData"; +BBS_TYPE mBbsType[] = {BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM, BBS_EMBED_NETWORK, BBS_BEV_DEVICE, BBS_UNKNOWN}; + + +/// +/// Legacy FD Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyFDMenu = { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy HD Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyHDMenu = { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy CD Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyCDMenu = { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy NET Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyNETMenu = { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy NET Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyBEVMenu = { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + + +VOID *mLegacyStartOpCodeHandle = NULL; +VOID *mLegacyEndOpCodeHandle = NULL; +EFI_IFR_GUID_LABEL *mLegacyStartLabel = NULL; +EFI_IFR_GUID_LABEL *mLegacyEndLabel = NULL; + + +HII_VENDOR_DEVICE_PATH mLegacyBootOptionHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + { 0x6bc75598, 0x89b4, 0x483d, { 0x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x35, 0x31 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +/** + Re-order the Boot Option according to the DevOrder. + + The routine re-orders the Boot Option in BootOption array according to + the order specified by DevOrder. + + @param DevOrder Pointer to buffer containing the BBS Index, + high 8-bit value 0xFF indicating a disabled boot option + @param DevOrderCount Count of the BBS Index + @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers + @param EnBootOptionCount Count of the enabled Boot Option Numbers + @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers + @param DisBootOptionCount Count of the disabled Boot Option Numbers +**/ +VOID +OrderLegacyBootOption4SameType ( + UINT16 *DevOrder, + UINTN DevOrderCount, + UINT16 **EnBootOption, + UINTN *EnBootOptionCount, + UINT16 **DisBootOption, + UINTN *DisBootOptionCount + ) +{ + EFI_STATUS Status; + UINT16 *NewBootOption; + UINT16 *BootOrder; + UINTN BootOrderSize; + UINTN Index; + UINTN StartPosition; + + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + + CHAR16 OptionName[sizeof ("Boot####")]; + UINT16 *BbsIndexArray; + UINT16 *DeviceTypeArray; + + GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize); + ASSERT (BootOrder != NULL); + + BbsIndexArray = AllocatePool (BootOrderSize); + DeviceTypeArray = AllocatePool (BootOrderSize); + *EnBootOption = AllocatePool (BootOrderSize); + *DisBootOption = AllocatePool (BootOrderSize); + *DisBootOptionCount = 0; + *EnBootOptionCount = 0; + Index = 0; + + ASSERT (BbsIndexArray != NULL); + ASSERT (DeviceTypeArray != NULL); + ASSERT (*EnBootOption != NULL); + ASSERT (*DisBootOption != NULL); + + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); + Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption); + ASSERT_EFI_ERROR (Status); + + if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) { + // + // Legacy Boot Option + // + ASSERT (BootOption.OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); + + DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType; + BbsIndexArray [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption.OptionalData)->BbsIndex; + } else { + DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN; + BbsIndexArray [Index] = 0xFFFF; + } + EfiBootManagerFreeLoadOption (&BootOption); + } + + // + // Record the corresponding Boot Option Numbers according to the DevOrder + // Record the EnBootOption and DisBootOption according to the DevOrder + // + StartPosition = BootOrderSize / sizeof (UINT16); + NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16)); + ASSERT (NewBootOption != NULL); + while (DevOrderCount-- != 0) { + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) { + StartPosition = MIN (StartPosition, Index); + NewBootOption[DevOrderCount] = BootOrder[Index]; + + if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) { + (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index]; + (*DisBootOptionCount)++; + } else { + (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index]; + (*EnBootOptionCount)++; + } + break; + } + } + } + + // + // Overwrite the old BootOption + // + CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16)); + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderSize, + BootOrder + ); + ASSERT_EFI_ERROR (Status); + + FreePool (NewBootOption); + FreePool (DeviceTypeArray); + FreePool (BbsIndexArray); +} + +/** + Update the legacy BBS boot option. L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable + is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid + is also updated. + + @param NVMapData The data for egacy BBS boot. + + @return EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND If L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable can be found. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource +**/ +EFI_STATUS +UpdateBBSOption ( + IN LEGACY_BOOT_NV_DATA *NVMapData + ) +{ + UINTN Index; + UINTN Index2; + UINTN CurrentType; + VOID *BootOptionVar; + CHAR16 VarName[100]; + UINTN OptionSize; + EFI_STATUS Status; + UINT32 *Attribute; + LEGACY_MENU_OPTION *OptionMenu; + UINT16 *LegacyDev; + UINT16 *InitialLegacyDev; + UINT8 *VarData; + UINTN VarSize; + LEGACY_DEV_ORDER_ENTRY *DevOrder; + UINT8 *OriginalPtr; + UINT8 *DisMap; + UINTN Pos; + UINTN Bit; + UINT16 *NewOrder; + UINT16 Tmp; + UINT16 *EnBootOption; + UINTN EnBootOptionCount; + UINT16 *DisBootOption; + UINTN DisBootOptionCount; + UINTN BufferSize; + + + DisMap = NULL; + NewOrder = NULL; + CurrentType = 0; + + + DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap; + Status = EFI_SUCCESS; + + // + // Update the Variable "LegacyDevOrder" + // + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize); + if (VarData == NULL) { + return EFI_NOT_FOUND; + } + OriginalPtr = VarData; + + while (mBbsType[CurrentType] != BBS_UNKNOWN) { + switch (mBbsType[CurrentType]) { + case BBS_FLOPPY: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu; + LegacyDev = NVMapData->LegacyFD; + InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD; + BufferSize = sizeof (NVMapData->LegacyFD); + break; + + case BBS_HARDDISK: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu; + LegacyDev = NVMapData->LegacyHD; + InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD; + + BufferSize = sizeof (NVMapData->LegacyHD); + break; + + case BBS_CDROM: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu; + LegacyDev = NVMapData->LegacyCD; + InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD; + BufferSize = sizeof (NVMapData->LegacyCD); + break; + + case BBS_EMBED_NETWORK: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu; + LegacyDev = NVMapData->LegacyNET; + InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET; + BufferSize = sizeof (NVMapData->LegacyNET); + break; + + default: + ASSERT (mBbsType[CurrentType] == BBS_BEV_DEVICE); + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu; + LegacyDev = NVMapData->LegacyBEV; + InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV; + BufferSize = sizeof (NVMapData->LegacyBEV); + break; + } + + // + // Check whether has value changed. + // + if (CompareMem (LegacyDev, InitialLegacyDev, BufferSize) == 0) { + CurrentType++; + continue; + } + + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) OriginalPtr; + while (VarData < OriginalPtr + VarSize) { + if (DevOrder->BbsType == mBbsType[CurrentType]) { + break; + } + + VarData += sizeof (BBS_TYPE) + DevOrder->Length; + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; + } + + if (VarData >= OriginalPtr + VarSize) { + FreePool (OriginalPtr); + return EFI_NOT_FOUND; + } + + NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length)); + if (NewOrder == NULL) { + FreePool (OriginalPtr); + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + if (0xFF == LegacyDev[Index]) { + break; + } + + NewOrder[Index] = LegacyDev[Index]; + } + + // + // Only the enable/disable state of each boot device with same device type can be changed, + // so we can count on the index information in DevOrder. + // DisMap bit array is the only reliable source to check a device's en/dis state, + // so we use DisMap to set en/dis state of each item in NewOrder array + // + for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) { + Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF); + Pos = Tmp / 8; + Bit = 7 - (Tmp % 8); + if ((DisMap[Pos] & (1 << Bit)) != 0) { + NewOrder[Index] = (UINT16) (0xFF00 | Tmp); + Index++; + } + } + + CopyMem ( + DevOrder->Data, + NewOrder, + DevOrder->Length - sizeof (DevOrder->Length) + ); + FreePool (NewOrder); + + // + // Update BootOrder and Boot####.Attribute + // + // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order + // + ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1); + + OrderLegacyBootOption4SameType ( + DevOrder->Data, + DevOrder->Length / sizeof (UINT16) - 1, + &EnBootOption, + &EnBootOptionCount, + &DisBootOption, + &DisBootOptionCount + ); + + // + // 2. Deactivate the DisBootOption and activate the EnBootOption + // + for (Index = 0; Index < DisBootOptionCount; Index++) { + UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]); + GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize); + if (BootOptionVar != NULL) { + Attribute = (UINT32 *) BootOptionVar; + *Attribute &= ~LOAD_OPTION_ACTIVE; + + Status = gRT->SetVariable ( + VarName, + &gEfiGlobalVariableGuid, + VAR_FLAG, + OptionSize, + BootOptionVar + ); + + FreePool (BootOptionVar); + } + } + + for (Index = 0; Index < EnBootOptionCount; Index++) { + UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]); + GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize); + if (BootOptionVar != NULL) { + Attribute = (UINT32 *) BootOptionVar; + *Attribute |= LOAD_OPTION_ACTIVE; + + Status = gRT->SetVariable ( + VarName, + &gEfiGlobalVariableGuid, + VAR_FLAG, + OptionSize, + BootOptionVar + ); + + FreePool (BootOptionVar); + } + } + + + FreePool (EnBootOption); + FreePool (DisBootOption); + + CurrentType++; + } + + Status = gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + VarSize, + OriginalPtr + ); + + FreePool (OriginalPtr); + return Status; +} + +/** + 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 illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + +/** + 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 +LegacyBootOptionRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_STATUS Status; + EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; + LEGACY_BOOT_NV_DATA *CurrentNVMapData; + UINTN BufferSize; + + + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check routing data in . + // Note: there is no name for Name/Value storage, only GUID will be checked + // + if (!HiiIsConfigHdrMatch (Configuration, &mLegacyBootOptionGuid, mLegacyBootStorageName)) { + return EFI_NOT_FOUND; + } + + Status = gBS->LocateProtocol ( + &gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID **) &ConfigRouting + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Convert to buffer data by helper function ConfigToBlock() + // + CurrentNVMapData = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData; + Status = ConfigRouting->ConfigToBlock ( + ConfigRouting, + Configuration, + (UINT8 *) CurrentNVMapData, + &BufferSize, + Progress + ); + ASSERT_EFI_ERROR (Status); + + Status = UpdateBBSOption (CurrentNVMapData); + + return Status; +} + +/** + Refresh the global UpdateData structure. + +**/ +VOID +RefreshLegacyUpdateData ( + VOID + ) +{ + // + // Free current updated date + // + if (mLegacyStartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mLegacyStartOpCodeHandle); + } + if (mLegacyEndOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mLegacyEndOpCodeHandle); + } + + // + // Create new OpCode Handle + // + mLegacyStartOpCodeHandle = HiiAllocateOpCodeHandle (); + mLegacyEndOpCodeHandle = HiiAllocateOpCodeHandle (); + + // + // Create Hii Extend Label OpCode as the start opcode + // + mLegacyStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + mLegacyStartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + mLegacyStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + + mLegacyStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID; + + // + // Create Hii Extend Label OpCode as the start opcode + // + mLegacyEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + mLegacyEndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + mLegacyEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + + mLegacyEndLabel->Number = FORM_BOOT_LEGACY_LABEL_END; + +} + +/** + Get the Menu Entry from the list in Menu Entry List. + + If MenuNumber is great or equal to the number of Menu + Entry in the list, then ASSERT. + + @param MenuOption The Menu Entry List to read the menu entry. + @param MenuNumber The index of Menu Entry. + + @return The Menu Entry. + +**/ +LEGACY_MENU_ENTRY * +GetMenuEntry ( + LEGACY_MENU_OPTION *MenuOption, + UINTN MenuNumber + ) +{ + LEGACY_MENU_ENTRY *NewMenuEntry; + UINTN Index; + LIST_ENTRY *List; + + ASSERT (MenuNumber < MenuOption->MenuNumber); + + List = MenuOption->Head.ForwardLink; + for (Index = 0; Index < MenuNumber; Index++) { + List = List->ForwardLink; + } + + NewMenuEntry = CR (List, LEGACY_MENU_ENTRY, Link, LEGACY_MENU_ENTRY_SIGNATURE); + + return NewMenuEntry; +} + +/** + Create string tokens for a menu from its help strings and display strings + + @param HiiHandle Hii Handle of the package to be updated. + @param MenuOption The Menu whose string tokens need to be created + +**/ +VOID +CreateLegacyMenuStringToken ( + IN EFI_HII_HANDLE HiiHandle, + IN LEGACY_MENU_OPTION *MenuOption + ) +{ + LEGACY_MENU_ENTRY *NewMenuEntry; + UINTN Index; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = GetMenuEntry (MenuOption, Index); + + NewMenuEntry->DisplayStringToken = HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->DisplayString, + NULL + ); + + if (NULL == NewMenuEntry->HelpString) { + NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; + } else { + NewMenuEntry->HelpStringToken = HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->HelpString, + NULL + ); + } + } +} + +/** + Create a dynamic page so that Legacy Device boot order + can be set for specified device type. + + @param UpdatePageId The form ID. It also spefies the legacy device type. + + +**/ +VOID +UpdateLegacyDeviceOrderPage ( + IN UINT16 UpdatePageId + ) +{ + LEGACY_MENU_OPTION *OptionMenu; + LEGACY_MENU_ENTRY *NewMenuEntry; + EFI_STRING_ID StrRef; + EFI_STRING_ID StrRefHelp; + UINT16 *Default; + UINT16 Index; + UINT16 Key; + CHAR16 String[100]; + CHAR16 *TypeStr; + CHAR16 *TypeStrHelp; + CHAR16 *FormTitle; + VOID *OptionsOpCodeHandle; + VOID *DefaultOpCodeHandle; + + Key = 0; + StrRef = 0; + StrRefHelp = 0; + OptionMenu = NULL; + TypeStr = NULL; + TypeStrHelp = NULL; + Default = NULL; + + RefreshLegacyUpdateData(); + + // + // Create oneof option list + // + switch (UpdatePageId) { + case FORM_FLOPPY_BOOT_ID: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu; + Key = (UINT16) LEGACY_FD_QUESTION_ID; + TypeStr = STR_FLOPPY; + TypeStrHelp = STR_FLOPPY_HELP; + FormTitle = STR_FLOPPY_TITLE; + Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyFD; + break; + + case FORM_HARDDISK_BOOT_ID: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu; + Key = (UINT16) LEGACY_HD_QUESTION_ID; + TypeStr = STR_HARDDISK; + TypeStrHelp = STR_HARDDISK_HELP; + FormTitle = STR_HARDDISK_TITLE; + Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyHD; + break; + + case FORM_CDROM_BOOT_ID: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu; + Key = (UINT16) LEGACY_CD_QUESTION_ID; + TypeStr = STR_CDROM; + TypeStrHelp = STR_CDROM_HELP; + FormTitle = STR_CDROM_TITLE; + Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyCD; + break; + + case FORM_NET_BOOT_ID: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu; + Key = (UINT16) LEGACY_NET_QUESTION_ID; + TypeStr = STR_NET; + TypeStrHelp = STR_NET_HELP; + FormTitle = STR_NET_TITLE; + Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyNET; + break; + + case FORM_BEV_BOOT_ID: + OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu; + Key = (UINT16) LEGACY_BEV_QUESTION_ID; + TypeStr = STR_BEV; + TypeStrHelp = STR_BEV_HELP; + FormTitle = STR_BEV_TITLE; + Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyBEV; + break; + + default: + DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n")); + return; + } + + HiiSetString (mLegacyBootOptionPrivate->HiiHandle, STRING_TOKEN(STR_ORDER_CHANGE_PROMPT), FormTitle, NULL); + + CreateLegacyMenuStringToken (mLegacyBootOptionPrivate->HiiHandle, OptionMenu); + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = GetMenuEntry (OptionMenu, Index); + // + // Create OneOf for each legacy device + // + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + ((LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex + ); + } + + // + // Create OneOf for item "Disabled" + // + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE), + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + 0xFF + ); + + // + // Create oneof tag here for FD/HD/CD #1 #2 + // + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + + HiiCreateDefaultOpCode ( + DefaultOpCodeHandle, + EFI_HII_DEFAULT_CLASS_STANDARD, + EFI_IFR_TYPE_NUM_SIZE_16, + *Default++ + ); + + // + // Create the string for oneof tag + // + UnicodeSPrint (String, sizeof (String), TypeStr, Index); + StrRef = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL); + + UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index); + StrRefHelp = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL); + + HiiCreateOneOfOpCode ( + mLegacyStartOpCodeHandle, + (EFI_QUESTION_ID) (Key + Index), + VARSTORE_ID_LEGACY_BOOT, + (UINT16) (Key + Index * 2 - CONFIG_OPTION_OFFSET), + StrRef, + StrRefHelp, + EFI_IFR_FLAG_CALLBACK, + EFI_IFR_NUMERIC_SIZE_2, + OptionsOpCodeHandle, + DefaultOpCodeHandle //NULL // + ); + + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + } + + HiiUpdateForm ( + mLegacyBootOptionPrivate->HiiHandle, + &mLegacyBootOptionGuid, + LEGACY_ORDER_CHANGE_FORM_ID, + mLegacyStartOpCodeHandle, + mLegacyEndOpCodeHandle + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); +} + + +/** + Adjust question value when one question value has been changed. + + @param QuestionId The question id for the value changed question. + @param Value The value for the changed question. + +**/ +VOID +AdjustOptionValue ( + IN UINT16 QuestionId, + IN EFI_IFR_TYPE_VALUE *Value + ) +{ + UINTN Number; + UINT16 *Default; + LEGACY_BOOT_NV_DATA *CurrentNVMap; + UINT16 *CurrentVal; + UINTN Index; + UINTN Index2; + UINTN Index3; + UINTN NewValuePos; + UINTN OldValue; + UINTN NewValue; + UINT8 *DisMap; + UINTN Pos; + UINTN Bit; + + Number = 0; + CurrentVal = 0; + Default = NULL; + NewValue = 0; + NewValuePos = 0; + OldValue = 0; + + // + // Update Select FD/HD/CD/NET/BEV Order Form + // + ASSERT ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)); + + CurrentNVMap = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData; + HiiGetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap); + DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap; + + if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyFDMenu.MenuNumber; + CurrentVal = CurrentNVMap->LegacyFD; + Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyFD; + } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyHDMenu.MenuNumber; + CurrentVal = CurrentNVMap->LegacyHD; + Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyHD; + } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyCDMenu.MenuNumber; + CurrentVal = CurrentNVMap->LegacyCD; + Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyCD; + } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyNETMenu.MenuNumber; + CurrentVal = CurrentNVMap->LegacyNET; + Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyNET; + } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyBEVMenu.MenuNumber; + CurrentVal = CurrentNVMap->LegacyBEV; + Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyBEV; + } + + // + // First, find the different position + // if there is change, it should be only one + // + for (Index = 0; Index < Number; Index++) { + if (CurrentVal[Index] != Default[Index]) { + OldValue = Default[Index]; + NewValue = CurrentVal[Index]; + break; + } + } + + if (Index != Number) { + // + // there is change, now process + // + if (0xFF == NewValue) { + // + // This item will be disable + // Just move the items behind this forward to overlap it + // + Pos = OldValue / 8; + Bit = 7 - (OldValue % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + for (Index2 = Index; Index2 < Number - 1; Index2++) { + CurrentVal[Index2] = CurrentVal[Index2 + 1]; + } + + CurrentVal[Index2] = 0xFF; + } else { + for (Index2 = 0; Index2 < Number; Index2++) { + if (Index2 == Index) { + continue; + } + + if (Default[Index2] == NewValue) { + // + // If NewValue is in OldLegacyDev array + // remember its old position + // + NewValuePos = Index2; + break; + } + } + + if (Index2 != Number) { + // + // We will change current item to an existing item + // (It's hard to describe here, please read code, it's like a cycle-moving) + // + for (Index2 = NewValuePos; Index2 != Index;) { + if (NewValuePos < Index) { + CurrentVal[Index2] = Default[Index2 + 1]; + Index2++; + } else { + CurrentVal[Index2] = Default[Index2 - 1]; + Index2--; + } + } + } else { + // + // If NewValue is not in OldlegacyDev array, we are changing to a disabled item + // so we should modify DisMap to reflect the change + // + Pos = NewValue / 8; + Bit = 7 - (NewValue % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); + if (0xFF != OldValue) { + // + // Because NewValue is a item that was disabled before + // so after changing the OldValue should be disabled + // actually we are doing a swap of enable-disable states of two items + // + Pos = OldValue / 8; + Bit = 7 - (OldValue % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + } + } + } + // + // To prevent DISABLE appears in the middle of the list + // we should perform a re-ordering + // + Index3 = Index; + Index = 0; + while (Index < Number) { + if (0xFF != CurrentVal[Index]) { + Index++; + continue; + } + + Index2 = Index; + Index2++; + while (Index2 < Number) { + if (0xFF != CurrentVal[Index2]) { + break; + } + + Index2++; + } + + if (Index2 < Number) { + CurrentVal[Index] = CurrentVal[Index2]; + CurrentVal[Index2] = 0xFF; + } + + Index++; + } + + // + // Return correct question value. + // + Value->u16 = CurrentVal[Index3]; + CopyMem (Default, CurrentVal, sizeof (UINT16) * Number); + } + + // + // Pass changed uncommitted data back to Form Browser + // + HiiSetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap, NULL); +} + +/** + This call back function is registered with Boot Manager formset. + When user selects a boot option, this call back function will + be triggered. The boot option is saved for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + if (Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_CHANGING) { + // + // Do nothing for other UEFI Action. Only do call back when data is changed. + // + return EFI_UNSUPPORTED; + } + + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (Action == EFI_BROWSER_ACTION_CHANGING) { + switch (QuestionId) { + case FORM_FLOPPY_BOOT_ID: + case FORM_HARDDISK_BOOT_ID: + case FORM_CDROM_BOOT_ID: + case FORM_NET_BOOT_ID: + case FORM_BEV_BOOT_ID: + UpdateLegacyDeviceOrderPage (QuestionId); + break; + + default: + break; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) { + AdjustOptionValue(QuestionId, Value); + } + } + return EFI_SUCCESS; +} + + +/** + Create a menu entry by given menu type. + + @param MenuType The Menu type to be created. + + @retval NULL If failed to create the menu. + @return the new menu entry. + +**/ +LEGACY_MENU_ENTRY * +CreateMenuEntry ( + VOID + ) +{ + LEGACY_MENU_ENTRY *MenuEntry; + + // + // Create new menu entry + // + MenuEntry = AllocateZeroPool (sizeof (LEGACY_MENU_ENTRY)); + if (MenuEntry == NULL) { + return NULL; + } + + MenuEntry->VariableContext = AllocateZeroPool (sizeof (LEGACY_DEVICE_CONTEXT)); + if (MenuEntry->VariableContext == NULL) { + FreePool (MenuEntry); + return NULL; + } + + MenuEntry->Signature = LEGACY_MENU_ENTRY_SIGNATURE; + return MenuEntry; +} + +/** + + Base on the L"LegacyDevOrder" variable to build the current order data. + +**/ +VOID +GetLegacyOptionsOrder ( + VOID + ) +{ + UINTN VarSize; + UINT8 *VarData; + UINT8 *VarTmp; + LEGACY_DEV_ORDER_ENTRY *DevOrder; + UINT16 *LegacyDev; + UINTN Index; + LEGACY_MENU_OPTION *OptionMenu; + UINT16 VarDevOrder; + UINTN Pos; + UINTN Bit; + UINT8 *DisMap; + UINTN TotalLength; + + LegacyDev = NULL; + OptionMenu = NULL; + + DisMap = ZeroMem (mLegacyBootOptionPrivate->MaintainMapData->DisableMap, sizeof (mLegacyBootOptionPrivate->MaintainMapData->DisableMap)); + + // + // Get Device Order from variable + // + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize); + VarTmp = VarData; + if (NULL != VarData) { + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; + while (VarData < VarTmp + VarSize) { + switch (DevOrder->BbsType) { + case BBS_FLOPPY: + LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD; + OptionMenu = &LegacyFDMenu; + break; + + case BBS_HARDDISK: + LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD; + OptionMenu = &LegacyHDMenu; + break; + + case BBS_CDROM: + LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD; + OptionMenu = &LegacyCDMenu; + break; + + case BBS_EMBED_NETWORK: + LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET; + OptionMenu = &LegacyNETMenu; + break; + + case BBS_BEV_DEVICE: + LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV; + OptionMenu = &LegacyBEVMenu; + break; + + case BBS_UNKNOWN: + default: + ASSERT (FALSE); + DEBUG ((DEBUG_ERROR, "Unsupported device type found!\n")); + break; + } + + // + // Create oneof tag here for FD/HD/CD #1 #2 + // + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + TotalLength = sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16); + VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + TotalLength); + + if (0xFF00 == (VarDevOrder & 0xFF00)) { + LegacyDev[Index] = 0xFF; + Pos = (VarDevOrder & 0xFF) / 8; + Bit = 7 - ((VarDevOrder & 0xFF) % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + } else { + LegacyDev[Index] = VarDevOrder & 0xFF; + } + } + + VarData ++; + VarData += *(UINT16 *) VarData; + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; + } + } + + CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA)); + CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA)); +} + +/** + + Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). + +**/ +VOID +GetLegacyOptions ( + VOID + ) +{ + LEGACY_MENU_ENTRY *NewMenuEntry; + LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + UINT16 Index; + UINTN FDNum; + UINTN HDNum; + UINTN CDNum; + UINTN NETNum; + UINTN BEVNum; + + // + // Initialize Bbs Table Context from BBS info data + // + InitializeListHead (&LegacyFDMenu.Head); + InitializeListHead (&LegacyHDMenu.Head); + InitializeListHead (&LegacyCDMenu.Head); + InitializeListHead (&LegacyNETMenu.Head); + InitializeListHead (&LegacyBEVMenu.Head); + + FDNum = 0; + HDNum = 0; + CDNum = 0; + NETNum = 0; + BEVNum = 0; + + EfiBootManagerConnectAll (); + + // + // for better user experience + // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option + // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option + // + EfiBootManagerRefreshAllBootOption (); + + BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + for (Index = 0; Index < BootOptionCount; Index++) { + if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) || + (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP) + ) { + continue; + } + ASSERT (BootOption[Index].OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); + NewMenuEntry = CreateMenuEntry (); + ASSERT (NewMenuEntry != NULL); + + NewLegacyDevContext = (LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; + NewLegacyDevContext->BbsIndex = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex; + NewLegacyDevContext->Description = AllocateCopyPool (StrSize (BootOption[Index].Description), BootOption[Index].Description); + ASSERT (NewLegacyDevContext->Description != NULL); + + NewMenuEntry->DisplayString = NewLegacyDevContext->Description; + NewMenuEntry->HelpString = NULL; + + switch (((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) { + case BBS_TYPE_FLOPPY: + InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); + FDNum++; + break; + + case BBS_TYPE_HARDDRIVE: + InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); + HDNum++; + break; + + case BBS_TYPE_CDROM: + InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); + CDNum++; + break; + + case BBS_TYPE_EMBEDDED_NETWORK: + InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); + NETNum++; + break; + + case BBS_TYPE_BEV: + InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); + BEVNum++; + break; + } + } + + EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); + + LegacyFDMenu.MenuNumber = FDNum; + LegacyHDMenu.MenuNumber = HDNum; + LegacyCDMenu.MenuNumber = CDNum; + LegacyNETMenu.MenuNumber = NETNum; + LegacyBEVMenu.MenuNumber = BEVNum; +} + + +/** + + Install Boot Manager Menu driver. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCEESS Install Boot manager menu success. + @retval Other Return error status. + +**/ +EFI_STATUS +EFIAPI +LegacyBootMaintUiLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + LEGACY_BOOT_OPTION_CALLBACK_DATA *LegacyBootOptionData; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (!EFI_ERROR (Status)) { + // + // Create LegacyBootOptionData structures for Driver Callback + // + LegacyBootOptionData = AllocateZeroPool (sizeof (LEGACY_BOOT_OPTION_CALLBACK_DATA)); + ASSERT (LegacyBootOptionData != NULL); + + LegacyBootOptionData->MaintainMapData = AllocateZeroPool (sizeof (LEGACY_BOOT_MAINTAIN_DATA)); + ASSERT (LegacyBootOptionData->MaintainMapData != NULL); + + LegacyBootOptionData->ConfigAccess.ExtractConfig = LegacyBootOptionExtractConfig; + LegacyBootOptionData->ConfigAccess.RouteConfig = LegacyBootOptionRouteConfig; + LegacyBootOptionData->ConfigAccess.Callback = LegacyBootOptionCallback; + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &LegacyBootOptionData->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mLegacyBootOptionHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &LegacyBootOptionData->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data + // + LegacyBootOptionData->HiiHandle = HiiAddPackages ( + &mLegacyBootOptionGuid, + LegacyBootOptionData->DriverHandle, + LegacyBootMaintUiVfrBin, + LegacyBootMaintUiLibStrings, + NULL + ); + ASSERT (LegacyBootOptionData->HiiHandle != NULL); + + mLegacyBootOptionPrivate = LegacyBootOptionData; + + GetLegacyOptions (); + + GetLegacyOptionsOrder(); + } + + return EFI_SUCCESS; +} + +/** + Destructor of Customized Display Library Instance. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor completed successfully. + @retval Other value The destructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +LegacyBootMaintUiLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (mLegacyBootOptionPrivate->DriverHandle != NULL) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + mLegacyBootOptionPrivate->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mLegacyBootOptionHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mLegacyBootOptionPrivate->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + HiiRemovePackages (mLegacyBootOptionPrivate->HiiHandle); + + FreePool (mLegacyBootOptionPrivate->MaintainMapData); + FreePool (mLegacyBootOptionPrivate); + } + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.h b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.h new file mode 100644 index 0000000000..86ea8eba7a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.h @@ -0,0 +1,255 @@ +/** @file + Legacy boot maintainence Ui definition. + +Copyright (c) 2004 - 2015, Intel 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 _EFI_LEGACY_BOOT_OPTION_H_ +#define _EFI_LEGACY_BOOT_OPTION_H_ + +#include + + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LegacyBootMaintUiVfr.h" + +#define CONFIG_OPTION_OFFSET 0x1200 + +// +// VarOffset that will be used to create question +// all these values are computed from the structure +// defined below +// +#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((LEGACY_BOOT_NV_DATA *) 0)->Field))) + +// +// Question Id of Zero is invalid, so add an offset to it +// +#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET) + + +#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD) +#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD) +#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD) +#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET) +#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV) + + +// +// String Contant +// +#define STR_FLOPPY L"Floppy Drive #%02x" +#define STR_HARDDISK L"HardDisk Drive #%02x" +#define STR_CDROM L"ATAPI CDROM Drive #%02x" +#define STR_NET L"NET Drive #%02x" +#define STR_BEV L"BEV Drive #%02x" + +#define STR_FLOPPY_HELP L"Select Floppy Drive #%02x" +#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x" +#define STR_CDROM_HELP L"Select ATAPI CDROM Drive #%02x" +#define STR_NET_HELP L"NET Drive #%02x" +#define STR_BEV_HELP L"BEV Drive #%02x" + +#define STR_FLOPPY_TITLE L"Set Legacy Floppy Drive Order" +#define STR_HARDDISK_TITLE L"Set Legacy HardDisk Drive Order" +#define STR_CDROM_TITLE L"Set Legacy CDROM Drive Order" +#define STR_NET_TITLE L"Set Legacy NET Drive Order" +#define STR_BEV_TITLE L"Set Legacy BEV Drive Order" + +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 LegacyBootMaintUiVfrBin[]; + +#pragma pack(1) + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + + + +// +// Variable created with this flag will be "Efi:...." +// +#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE + + +#define LEGACY_BOOT_OPTION_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('L', 'G', 'C', 'B') + +typedef struct { + UINTN Signature; + + // + // HII relative handles + // + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + // + // Produced protocols + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + + // + // Maintain the data. + // + LEGACY_BOOT_MAINTAIN_DATA *MaintainMapData; +} LEGACY_BOOT_OPTION_CALLBACK_DATA; + +// +// All of the signatures that will be used in list structure +// +#define LEGACY_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u') +#define LEGACY_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r') + +#define LEGACY_LEGACY_DEV_CONTEXT_SELECT 0x9 + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} LEGACY_MENU_OPTION; + +typedef struct { + UINT16 BbsIndex; + CHAR16 *Description; +} LEGACY_DEVICE_CONTEXT; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINTN OptionNumber; + UINT16 *DisplayString; + UINT16 *HelpString; + EFI_STRING_ID DisplayStringToken; + EFI_STRING_ID HelpStringToken; + VOID *VariableContext; +} LEGACY_MENU_ENTRY; + +typedef struct { + UINT16 BbsIndex; +} LEGACY_BOOT_OPTION_BBS_DATA; + +#pragma pack() + +/** + This call back function is registered with Boot Manager formset. + When user selects a boot option, this call back function will + be triggered. The boot option is saved for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ); + +/** + 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 +LegacyBootOptionRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf new file mode 100644 index 0000000000..17c9cac811 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf @@ -0,0 +1,69 @@ +## @file +# Legacy Boot Maintainence UI module is library for BDS phase. +# +# Copyright (c) 2015, Intel 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 = LegacyBootMaintUiLib + MODULE_UNI_FILE = LegacyBootMaintUiLib.uni + FILE_GUID = e6f7f038-3ed9-401a-af1f-5ea7bf644d34 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION + CONSTRUCTOR = LegacyBootMaintUiLibConstructor + DESTRUCTOR = LegacyBootMaintUiLibDestructor +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + LegacyBootMaintUiVfr.h + LegacyBootMaintUi.h + LegacyBootMaintUiVfr.Vfr + LegacyBootMaintUiStrings.uni + LegacyBootMaintUi.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + DevicePathLib + BaseLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + DebugLib + HiiLib + MemoryAllocationLib + UefiBootManagerLib + UefiLib + PrintLib + BaseMemoryLib + +[Guids] + gEfiIfrTianoGuid ## SOMETIMES_PRODUCES ## UNDEFINED # Extended IFR Guid Opcode + gEfiIfrBootMaintenanceGuid ## CONSUMES ## HII # BootMaint HII Package + gEfiLegacyDevOrderVariableGuid ## PRODUCES ## Variable:L"LegacyDevOrder" + +[Protocols] + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + gEfiLegacyBiosProtocolGuid ## CONSUMES + gEfiHiiConfigRoutingProtocolGuid ## CONSUMES + +[Depex] + gEfiHiiDatabaseProtocolGuid + diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni new file mode 100644 index 0000000000..892d6e218e Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni new file mode 100644 index 0000000000..dbec69bfd6 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr new file mode 100644 index 0000000000..882da99f9e --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr @@ -0,0 +1,73 @@ +///** @file +// +// Browser formset. +// +// Copyright (c) 2015, Intel 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 "LegacyBootMaintUiVfr.h" + + +formset + guid = LEGACY_BOOT_OPTION_FORMSET_GUID, + title = STRING_TOKEN(STR_LEGACY_BOOT_PROMPT), + help = STRING_TOKEN(STR_LEGACY_BOOT_HELP), + classguid = EFI_IFR_BOOT_MAINTENANCE_GUID, + + varstore LEGACY_BOOT_NV_DATA, + varid = VARSTORE_ID_LEGACY_BOOT, + name = LegacyBootData, + guid = LEGACY_BOOT_OPTION_FORMSET_GUID; + + form formid = LEGACY_BOOT_FORM_ID, + title = STRING_TOKEN(STR_LEGACY_BOOT_PROMPT); + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt = STRING_TOKEN(STR_FORM_FLOPPY_BOOT_TITLE), + help = STRING_TOKEN(STR_FORM_FLOPPY_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_FLOPPY_BOOT_ID; + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt = STRING_TOKEN(STR_FORM_HARDDISK_BOOT_TITLE), + help = STRING_TOKEN(STR_FORM_HARDDISK_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_HARDDISK_BOOT_ID; + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt = STRING_TOKEN(STR_FORM_CDROM_BOOT_TITLE), + help = STRING_TOKEN(STR_FORM_CDROM_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_CDROM_BOOT_ID; + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt = STRING_TOKEN(STR_FORM_NET_BOOT_TITLE), + help = STRING_TOKEN(STR_FORM_NET_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_NET_BOOT_ID; + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt = STRING_TOKEN(STR_FORM_BEV_BOOT_TITLE), + help = STRING_TOKEN(STR_FORM_BEV_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_BEV_BOOT_ID; + + endform; + + form formid = LEGACY_ORDER_CHANGE_FORM_ID, + title = STRING_TOKEN(STR_ORDER_CHANGE_PROMPT); + + label FORM_BOOT_LEGACY_DEVICE_ID; + label FORM_BOOT_LEGACY_LABEL_END; + + endform; + +endformset; diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h new file mode 100644 index 0000000000..713ea4c640 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h @@ -0,0 +1,85 @@ +/** @file + Legacy Boot Maintainence UI definition. + +Copyright (c) 2004 - 2015, Intel 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 _EFI_LEGACY_BOOT_OPTION_VFR_H_ +#define _EFI_LEGACY_BOOT_OPTION_VFR_H_ + +#include + +#define MAX_MENU_NUMBER 100 + +#define LEGACY_BOOT_OPTION_FORMSET_GUID { 0x6bc75598, 0x89b4, 0x483d, { 0x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x35, 0x31 } } + +#define VARSTORE_ID_LEGACY_BOOT 0x0001 + + +#define LEGACY_BOOT_FORM_ID 0x1000 +#define LEGACY_ORDER_CHANGE_FORM_ID 0x1001 + + +#define FORM_FLOPPY_BOOT_ID 0x2000 +#define FORM_HARDDISK_BOOT_ID 0x2001 +#define FORM_CDROM_BOOT_ID 0x2002 +#define FORM_NET_BOOT_ID 0x2003 +#define FORM_BEV_BOOT_ID 0x2004 + + + +#define FORM_BOOT_LEGACY_DEVICE_ID 0x9000 +#define FORM_BOOT_LEGACY_LABEL_END 0x9001 + + +#pragma pack(1) + +/// +/// This is the structure that will be used to store the +/// question's current value. Use it at initialize time to +/// set default value for each question. When using at run +/// time, this map is returned by the callback function, +/// so dynamically changing the question's value will be +/// possible through this mechanism +/// +typedef struct { + // + // Legacy Device Order Selection Storage + // + UINT16 LegacyFD[MAX_MENU_NUMBER]; + UINT16 LegacyHD[MAX_MENU_NUMBER]; + UINT16 LegacyCD[MAX_MENU_NUMBER]; + UINT16 LegacyNET[MAX_MENU_NUMBER]; + UINT16 LegacyBEV[MAX_MENU_NUMBER]; +} LEGACY_BOOT_NV_DATA; + +/// +/// This is the structure that will be used to store the +/// question's current value. Use it at initialize time to +/// set default value for each question. When using at run +/// time, this map is returned by the callback function, +/// so dynamically changing the question's value will be +/// possible through this mechanism +/// +typedef struct { + // + // Legacy Device Order Selection Storage + // + LEGACY_BOOT_NV_DATA InitialNvData; + LEGACY_BOOT_NV_DATA CurrentNvData; + LEGACY_BOOT_NV_DATA LastTimeNvData; + UINT8 DisableMap[32]; +} LEGACY_BOOT_MAINTAIN_DATA; + +#pragma pack() + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h b/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h new file mode 100644 index 0000000000..e7bdde9def --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h @@ -0,0 +1,66 @@ +/** @file + +Copyright (c) 2011 - 2015, Intel 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_LEGACY_BM_H_ +#define _INTERNAL_LEGACY_BM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(1) +typedef struct { + UINT16 BbsIndex; +} LEGACY_BM_BOOT_OPTION_BBS_DATA; +#pragma pack() + +/** + Boot the legacy system with the boot option. + + @param BootOption The legacy boot option which have BBS device path + On return, BootOption->Status contains the boot status. + EFI_UNSUPPORTED There is no legacybios protocol, do not support + legacy boot. + EFI_STATUS The status of LegacyBios->LegacyBoot (). +**/ +VOID +EFIAPI +LegacyBmBoot ( + IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ); + +/** + Refresh all legacy boot options. + +**/ +VOID +EFIAPI +LegacyBmRefreshAllBootOption ( + VOID + ); + +#endif // _INTERNAL_LEGACY_BM_H_ \ No newline at end of file diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c b/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c new file mode 100644 index 0000000000..d3b48e8d0b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c @@ -0,0 +1,1536 @@ +/** @file + This function deal with the legacy boot option, it create, delete + and manage the legacy boot option, all legacy boot option is getting from + the legacy BBS table. + +Copyright (c) 2011 - 2016, Intel 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 "InternalLegacyBm.h" + +#define LEGACY_BM_BOOT_DESCRIPTION_LENGTH 32 + +/** + Initialize legacy boot manager library by call EfiBootManagerRegisterLegacyBootSupport + function to export two function pointer. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCCESS The legacy boot manager library is initialized correctly. + @return Other value if failed to initialize the legacy boot manager library. +**/ +EFI_STATUS +EFIAPI +LegacyBootManagerLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EfiBootManagerRegisterLegacyBootSupport ( + LegacyBmRefreshAllBootOption, + LegacyBmBoot + ); + return EFI_SUCCESS; +} + +/** + Get the device type from the input legacy device path. + + @param DevicePath The legacy device path. + + @retval The legacy device type. +**/ +UINT16 +LegacyBmDeviceType ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ASSERT ((DevicePathType (DevicePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (DevicePath) == BBS_BBS_DP)); + return ((BBS_BBS_DEVICE_PATH *) DevicePath)->DeviceType; +} + +/** + Validate the BbsEntry base on the Boot Priority info in the BbsEntry. + + @param BbsEntry The input bbs entry info. + + @retval TRUE The BbsEntry is valid. + @retval FALSE The BbsEntry is invalid. +**/ +BOOLEAN +LegacyBmValidBbsEntry ( + IN BBS_TABLE *BbsEntry + ) +{ + switch (BbsEntry->BootPriority) { + case BBS_IGNORE_ENTRY: + case BBS_DO_NOT_BOOT_FROM: + case BBS_LOWEST_PRIORITY: + return FALSE; + default: + return TRUE; + } +} + +/** + Build Legacy Device Name String according. + + @param CurBBSEntry BBS Table. + @param Index Index. + @param BufSize The buffer size. + @param BootString The output string. + +**/ +VOID +LegacyBmBuildLegacyDevNameString ( + IN BBS_TABLE *CurBBSEntry, + IN UINTN Index, + IN UINTN BufSize, + OUT CHAR16 *BootString + ) +{ + CHAR16 *Fmt; + CHAR16 *Type; + CHAR8 *StringDesc; + CHAR8 StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; + CHAR16 StringBufferU[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; + + 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 = (CHAR8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset); + if (NULL != StringDesc) { + // + // Only get fisrt 32 characters, this is suggested by BBS spec + // + CopyMem (StringBufferA, StringDesc, LEGACY_BM_BOOT_DESCRIPTION_LENGTH); + StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH] = 0; + AsciiStrToUnicodeStrS (StringBufferA, StringBufferU, sizeof (StringBufferU) / sizeof (StringBufferU[0])); + Fmt = L"%s"; + Type = StringBufferU; + } + + // + // 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); + } +} + +/** + Get the Bbs index for the input boot option. + + @param BootOption The input boot option info. + @param BbsTable The input Bbs table. + @param BbsCount The input total bbs entry number. + @param BbsIndexUsed The array shows how many BBS table indexs have been used. + + @retval The index for the input boot option. +**/ +UINT16 +LegacyBmFuzzyMatch ( + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, + BBS_TABLE *BbsTable, + UINT16 BbsCount, + BOOLEAN *BbsIndexUsed + ) +{ + UINT16 Index; + LEGACY_BM_BOOT_OPTION_BBS_DATA *BbsData; + CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; + + BbsData = (LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData; + + // + // Directly check the BBS index stored in BootOption + // + if ((BbsData->BbsIndex < BbsCount) && + (LegacyBmDeviceType (BootOption->FilePath) == BbsTable[BbsData->BbsIndex].DeviceType)) { + LegacyBmBuildLegacyDevNameString ( + &BbsTable[BbsData->BbsIndex], + BbsData->BbsIndex, + sizeof (Description), + Description + ); + if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[BbsData->BbsIndex]) { + // + // If devices with the same description string are connected, + // the BbsIndex of the first device is returned for the other device also. + // So, check if the BbsIndex is already being used, before assigning the BbsIndex. + // + BbsIndexUsed[BbsData->BbsIndex] = TRUE; + return BbsData->BbsIndex; + } + } + + // + // BBS table could be changed (entry removed/moved) + // find the correct BBS index + // + for (Index = 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&BbsTable[Index]) || + (BbsTable[Index].DeviceType != LegacyBmDeviceType (BootOption->FilePath))) { + continue; + } + + LegacyBmBuildLegacyDevNameString ( + &BbsTable[Index], + Index, + sizeof (Description), + Description + ); + if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[Index]) { + // + // If devices with the same description string are connected, + // the BbsIndex of the first device is assigned for the other device also. + // So, check if the BbsIndex is already being used, before assigning the corrected BbsIndex. + // + break; + } + } + + // + // Add the corrected BbsIndex in the UsedBbsIndex Buffer + // + if (Index != BbsCount) { + BbsIndexUsed[Index] = TRUE; + } + + return Index; +} + +/** + + Update legacy device order base on the input info. + + @param LegacyDevOrder Legacy device order data buffer. + @param LegacyDevOrderSize Legacy device order data buffer size. + @param DeviceType Device type which need to check. + @param OldBbsIndex Old Bds Index. + @param NewBbsIndex New Bds Index, if it is -1,means remove this option. + +**/ +VOID +LegacyBmUpdateBbsIndex ( + LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder, + UINTN *LegacyDevOrderSize, + UINT16 DeviceType, + UINT16 OldBbsIndex, + UINT16 NewBbsIndex // Delete entry if -1 + ) +{ + LEGACY_DEV_ORDER_ENTRY *Entry; + UINTN Index; + + ASSERT (((LegacyDevOrder == NULL) && (*LegacyDevOrderSize == 0)) || + ((LegacyDevOrder != NULL) && (*LegacyDevOrderSize != 0)) + ); + + for (Entry = LegacyDevOrder; + Entry < (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) LegacyDevOrder + *LegacyDevOrderSize); + Entry = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) Entry + sizeof (BBS_TYPE) + Entry->Length) + ) { + if (Entry->BbsType == DeviceType) { + for (Index = 0; Index < Entry->Length / sizeof (UINT16) - 1; Index++) { + if (Entry->Data[Index] == OldBbsIndex) { + if (NewBbsIndex == (UINT16) -1) { + // + // Delete the old entry + // + CopyMem ( + &Entry->Data[Index], + &Entry->Data[Index + 1], + (UINT8 *) LegacyDevOrder + *LegacyDevOrderSize - (UINT8 *) &Entry->Data[Index + 1] + ); + Entry->Length -= sizeof (UINT16); + *LegacyDevOrderSize -= sizeof(UINT16); + } else { + Entry->Data[Index] = NewBbsIndex; + } + break; + } + } + break; + } + } +} + +/** + Delete all the legacy boot options. + + @retval EFI_SUCCESS All legacy boot options are deleted. +**/ +EFI_STATUS +LegacyBmDeleteAllBootOptions ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + + BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + for (Index = 0; Index < BootOptionCount; Index++) { + if ((DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)) { + Status = EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } + } + + Status = gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + 0, + 0, + NULL + ); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND); + + return EFI_SUCCESS; +} + + +/** + 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 +LegacyBmDeleteAllInvalidBootOptions ( + VOID + ) +{ + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *HddInfo; + BBS_TABLE *BbsTable; + UINT16 BbsIndex; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder; + UINTN LegacyDevOrderSize; + BOOLEAN *BbsIndexUsed; + + HddCount = 0; + BbsCount = 0; + HddInfo = NULL; + BbsTable = NULL; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &HddInfo, + &BbsCount, + &BbsTable + ); + if (EFI_ERROR (Status)) { + return Status; + } + + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &LegacyDevOrder, &LegacyDevOrderSize); + + BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + + BbsIndexUsed = AllocateZeroPool (BbsCount * sizeof (BOOLEAN)); + ASSERT (BbsIndexUsed != NULL); + + for (Index = 0; Index < BootOptionCount; Index++) { + // + // Skip non legacy boot option + // + if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) || + (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP)) { + continue; + } + + BbsIndex = LegacyBmFuzzyMatch (&BootOption[Index], BbsTable, BbsCount, BbsIndexUsed); + if (BbsIndex == BbsCount) { + DEBUG ((EFI_D_INFO, "[LegacyBds] Delete Boot Option Boot%04x: %s\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description)); + // + // Delete entry from LegacyDevOrder + // + LegacyBmUpdateBbsIndex ( + LegacyDevOrder, + &LegacyDevOrderSize, + LegacyBmDeviceType (BootOption[Index].FilePath), + ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, + (UINT16) -1 + ); + EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType); + } else { + if (((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex != BbsIndex) { + DEBUG ((EFI_D_INFO, "[LegacyBds] Update Boot Option Boot%04x: %s Bbs0x%04x->Bbs0x%04x\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description, + (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, (UINTN) BbsIndex)); + // + // Update the BBS index in LegacyDevOrder + // + LegacyBmUpdateBbsIndex ( + LegacyDevOrder, + &LegacyDevOrderSize, + LegacyBmDeviceType (BootOption[Index].FilePath), + ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, + BbsIndex + ); + + // + // Update the OptionalData in the Boot#### variable + // + ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex = BbsIndex; + EfiBootManagerLoadOptionToVariable (&BootOption[Index]); + } + } + } + EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); + + if (LegacyDevOrder != NULL) { + Status = gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + LegacyDevOrderSize, + LegacyDevOrder + ); + // + // Shrink variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + FreePool (LegacyDevOrder); + } + FreePool(BbsIndexUsed); + return Status; +} + +/** + Create legacy boot option. + + @param BootOption Ponter to the boot option which will be crated. + @param BbsEntry The input bbs entry info. + @param BbsIndex The BBS index. + + @retval EFI_SUCCESS Create legacy boot option successfully. + @retval EFI_INVALID_PARAMETER Invalid input parameter. + +**/ +EFI_STATUS +LegacyBmCreateLegacyBootOption ( + IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, + IN BBS_TABLE *BbsEntry, + IN UINT16 BbsIndex + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; + CHAR8 HelpString[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; + UINTN StringLen; + LEGACY_BM_BOOT_OPTION_BBS_DATA *OptionalData; + BBS_BBS_DEVICE_PATH *BbsNode; + + if ((BootOption == NULL) || (BbsEntry == NULL)) { + return EFI_INVALID_PARAMETER; + } + + LegacyBmBuildLegacyDevNameString (BbsEntry, BbsIndex, sizeof (Description), Description); + + // + // Create the BBS device path with description string + // + UnicodeStrToAsciiStrS (Description, HelpString, sizeof (HelpString)); + StringLen = AsciiStrLen (HelpString); + DevicePath = AllocatePool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen + END_DEVICE_PATH_LENGTH); + ASSERT (DevicePath != NULL); + + BbsNode = (BBS_BBS_DEVICE_PATH *) DevicePath; + SetDevicePathNodeLength (BbsNode, sizeof (BBS_BBS_DEVICE_PATH) + StringLen); + BbsNode->Header.Type = BBS_DEVICE_PATH; + BbsNode->Header.SubType = BBS_BBS_DP; + BbsNode->DeviceType = BbsEntry->DeviceType; + CopyMem (&BbsNode->StatusFlag, &BbsEntry->StatusFlags, sizeof (BBS_STATUS_FLAGS)); + CopyMem (BbsNode->String, HelpString, StringLen + 1); + + SetDevicePathEndNode (NextDevicePathNode (BbsNode)); + + // + // Create the OptionalData + // + OptionalData = AllocatePool (sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA)); + ASSERT (OptionalData != NULL); + OptionalData->BbsIndex = BbsIndex; + + // + // Create the BootOption + // + Status = EfiBootManagerInitializeLoadOption ( + BootOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + LOAD_OPTION_ACTIVE, + Description, + DevicePath, + (UINT8 *) OptionalData, + sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA) + ); + FreePool (DevicePath); + FreePool (OptionalData); + + 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 * +LegacyBmFillDevOrderBuf ( + IN BBS_TABLE *BbsTable, + IN BBS_TYPE BbsType, + IN UINTN BbsCount, + OUT UINT16 *Buf + ) +{ + UINTN Index; + + for (Index = 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&BbsTable[Index])) { + 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 EfiLegacyDevOrderGuid 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 +LegacyBmCreateDevOrder ( + 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 (!LegacyBmValidBbsEntry (&BbsTable[Index])) { + 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 *) LegacyBmFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType = BBS_HARDDISK; + DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16)); + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType = BBS_CDROM; + DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16)); + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType = BBS_EMBED_NETWORK; + DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16)); + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (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 *) LegacyBmFillDevOrderBuf (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_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 +LegacyBmUpdateDevOrder ( + VOID + ) +{ + LEGACY_DEV_ORDER_ENTRY *DevOrder; + LEGACY_DEV_ORDER_ENTRY *NewDevOrder; + LEGACY_DEV_ORDER_ENTRY *Ptr; + LEGACY_DEV_ORDER_ENTRY *NewPtr; + 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; + } + + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, NULL); + if (NULL == DevOrder) { + return LegacyBmCreateDevOrder (LocalBbsTable, BbsCount); + } + // + // First we figure out how many boot devices with same device type respectively + // + for (Index = 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { + 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { + 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_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 +LegacyBmSetPriorityForSameTypeDev ( + 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; + + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, &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 *) ((UINTN) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length); + } + + if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) { + FreePool (DevOrder); + return EFI_NOT_FOUND; + } + + if (BbsIndex != (UINTN) -1) { + // + // In case the BBS entry isn't valid because devices were plugged or removed. + // + if (!LegacyBmValidBbsEntry (&LocalBbsTable[BbsIndex]) || (LocalBbsTable[BbsIndex].DeviceType != DeviceType)) { + FreePool (DevOrder); + return EFI_NOT_FOUND; + } + 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 +LegacyBmPrintBbsTable ( + IN BBS_TABLE *LocalBbsTable, + IN UINT16 BbsCount + ) +{ + UINT16 Index; + + DEBUG ((DEBUG_INFO, "\n")); + DEBUG ((DEBUG_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n")); + DEBUG ((DEBUG_INFO, "=============================================\n")); + for (Index = 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { + continue; + } + + DEBUG ( + (DEBUG_INFO, + " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n", + (UINTN) Index, + (UINTN) LocalBbsTable[Index].BootPriority, + (UINTN) LocalBbsTable[Index].Bus, + (UINTN) LocalBbsTable[Index].Device, + (UINTN) LocalBbsTable[Index].Function, + (UINTN) LocalBbsTable[Index].Class, + (UINTN) LocalBbsTable[Index].SubClass, + (UINTN) LocalBbsTable[Index].DeviceType, + (UINTN) * (UINT16 *) &LocalBbsTable[Index].StatusFlags, + (UINTN) LocalBbsTable[Index].BootHandlerSegment, + (UINTN) LocalBbsTable[Index].BootHandlerOffset, + (UINTN) ((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTable[Index].MfgStringOffset), + (UINTN) ((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTable[Index].DescStringOffset)) + ); + } + + DEBUG ((DEBUG_INFO, "\n")); +} + +/** + Set the boot priority for BBS entries based on boot option entry and boot order. + + @param BootOption 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 +LegacyBmRefreshBbsTableForBoot ( + IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ) +{ + 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 *DeviceType; + UINTN DeviceTypeCount; + UINTN DeviceTypeIndex; + EFI_BOOT_MANAGER_LOAD_OPTION *Option; + UINTN OptionCount; + + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + DevType = BBS_UNKNOWN; + + 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; + } + + // + // 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 (LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { + LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; + } + } + // + // boot priority always starts at 0 + // + Priority = 0; + if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) { + // + // If BootOption stands for a legacy boot option, we prioritize the devices with the same type first. + // + DevType = LegacyBmDeviceType (BootOption->FilePath); + BbsIndex = ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData)->BbsIndex; + Status = LegacyBmSetPriorityForSameTypeDev ( + 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 + // + Option = EfiBootManagerGetLoadOptions (&OptionCount, LoadOptionTypeBoot); + DeviceType = AllocatePool (sizeof (UINT16) * OptionCount); + ASSERT (DeviceType != NULL); + DeviceType[0] = DevType; + DeviceTypeCount = 1; + for (Index = 0; Index < OptionCount; Index++) { + if ((DevicePathType (Option[Index].FilePath) != BBS_DEVICE_PATH) || + (DevicePathSubType (Option[Index].FilePath) != BBS_BBS_DP)) { + continue; + } + + DevType = LegacyBmDeviceType (Option[Index].FilePath); + 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 + // + continue; + } + + DeviceType[DeviceTypeCount] = DevType; + DeviceTypeCount++; + + Status = LegacyBmSetPriorityForSameTypeDev ( + DevType, + (UINTN) -1, + LocalBbsTable, + &Priority + ); + } + EfiBootManagerFreeLoadOptions (Option, OptionCount); + + DEBUG_CODE_BEGIN(); + LegacyBmPrintBbsTable (LocalBbsTable, BbsCount); + DEBUG_CODE_END(); + + return Status; +} + + +/** + Boot the legacy system with the boot option. + + @param BootOption The legacy boot option which have BBS device path + On return, BootOption->Status contains the boot status. + EFI_UNSUPPORTED There is no legacybios protocol, do not support + legacy boot. + EFI_STATUS The status of LegacyBios->LegacyBoot (). +**/ +VOID +EFIAPI +LegacyBmBoot ( + IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + // + // If no LegacyBios protocol we do not support legacy boot + // + BootOption->Status = EFI_UNSUPPORTED; + return; + } + // + // Notes: if we separate the int 19, then we don't need to refresh BBS + // + Status = LegacyBmRefreshBbsTableForBoot (BootOption); + if (EFI_ERROR (Status)) { + BootOption->Status = Status; + return; + } + + BootOption->Status = LegacyBios->LegacyBoot ( + LegacyBios, + (BBS_BBS_DEVICE_PATH *) BootOption->FilePath, + BootOption->OptionalDataSize, + BootOption->OptionalData + ); +} + +/** + This function enumerates all the legacy boot options. + + @param BootOptionCount Return the legacy boot option count. + + @retval Pointer to the legacy boot option buffer. +**/ +EFI_BOOT_MANAGER_LOAD_OPTION * +LegacyBmEnumerateAllBootOptions ( + UINTN *BootOptionCount + ) +{ + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *HddInfo; + BBS_TABLE *BbsTable; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 Index; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + + ASSERT (BootOptionCount != NULL); + + BootOptions = NULL; + *BootOptionCount = 0; + BbsCount = 0; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return NULL; + } + + Status = LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &HddInfo, + &BbsCount, + &BbsTable + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + for (Index = 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&BbsTable[Index])) { + continue; + } + + BootOptions = ReallocatePool ( + sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount), + sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1), + BootOptions + ); + ASSERT (BootOptions != NULL); + + Status = LegacyBmCreateLegacyBootOption (&BootOptions[(*BootOptionCount)++], &BbsTable[Index], Index); + ASSERT_EFI_ERROR (Status); + } + + return BootOptions; +} + +/** + Return the index of the boot option in the boot option array. + + The function compares the Description, FilePath, OptionalData. + + @param Key The input boot option which is compared with. + @param Array The input boot option array. + @param Count The count of the input boot options. + + @retval The index of the input boot option in the array. + +**/ +INTN +LegacyBmFindBootOption ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key, + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array, + IN UINTN Count + ) +{ + UINTN Index; + + for (Index = 0; Index < Count; Index++) { + if ((StrCmp (Key->Description, Array[Index].Description) == 0) && + (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) && + (Key->OptionalDataSize == Array[Index].OptionalDataSize) && + (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) { + return (INTN) Index; + } + } + + return -1; +} + +/** + Refresh all legacy boot options. + +**/ +VOID +EFIAPI +LegacyBmRefreshAllBootOption ( + VOID + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN RootBridgeHandleCount; + EFI_HANDLE *RootBridgeHandleBuffer; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN RootBridgeIndex; + UINTN Index; + UINTN Flags; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + EFI_BOOT_MANAGER_LOAD_OPTION *ExistingBootOptions; + UINTN ExistingBootOptionCount; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + LegacyBmDeleteAllBootOptions (); + return; + } + PERF_START (NULL, "LegacyBootOptionEnum", "BDS", 0); + + // + // Before enumerating the legacy boot option, we need to dispatch all the legacy option roms + // to ensure the GetBbsInfo() counts all the legacy devices. + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &RootBridgeHandleCount, + &RootBridgeHandleBuffer + ); + for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) { + gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE); + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + for (Index = 0; Index < HandleCount; Index++) { + // + // Start the thunk driver so that the legacy option rom gets dispatched. + // Note: We don't directly call InstallPciRom because some thunk drivers + // (e.g. BlockIo thunk driver) depend on the immediate result after dispatching + // + Status = LegacyBios->CheckPciRom ( + LegacyBios, + HandleBuffer[Index], + NULL, + NULL, + &Flags + ); + if (!EFI_ERROR (Status)) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); + } + } + } + + // + // Same algorithm pattern as the EfiBootManagerRefreshAllBootOption + // Firstly delete the invalid legacy boot options, + // then enumreate and save the newly appeared legacy boot options + // the last step is legacy boot option special action to refresh the LegacyDevOrder variable + // + LegacyBmDeleteAllInvalidBootOptions (); + + ExistingBootOptions = EfiBootManagerGetLoadOptions (&ExistingBootOptionCount, LoadOptionTypeBoot); + BootOptions = LegacyBmEnumerateAllBootOptions (&BootOptionCount); + + for (Index = 0; Index < BootOptionCount; Index++) { + if (LegacyBmFindBootOption (&BootOptions[Index], ExistingBootOptions, ExistingBootOptionCount) == -1) { + Status = EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1); + DEBUG (( + EFI_D_INFO, "[LegacyBds] New Boot Option: Boot%04x Bbs0x%04x %s %r\n", + (UINTN) BootOptions[Index].OptionNumber, + (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOptions[Index].OptionalData)->BbsIndex, + BootOptions[Index].Description, + Status + )); + // + // Continue upon failure to add boot option. + // + } + } + + EfiBootManagerFreeLoadOptions (ExistingBootOptions, ExistingBootOptionCount); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + + // + // Failure to create LegacyDevOrder variable only impacts the boot order. + // + LegacyBmUpdateDevOrder (); + + PERF_END (NULL, "LegacyBootOptionEnum", "BDS", 0); +} diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf b/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf new file mode 100644 index 0000000000..4025c82886 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf @@ -0,0 +1,64 @@ +## @file +# Legacy Boot Manager module is library for BDS phase. +# +# Copyright (c) 2011 - 2015, Intel 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 = LegacyBootManagerLib + MODULE_UNI_FILE = LegacyBootManagerLib.uni + FILE_GUID = F1B87BE4-0ACC-409A-A52B-7BFFABCC96A0 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION + CONSTRUCTOR = LegacyBootManagerLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + LegacyBm.c + InternalLegacyBm.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + MemoryAllocationLib + UefiLib + DebugLib + PrintLib + PerformanceLib + UefiBootManagerLib + +[Guids] + gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"Boot####" (Boot option variable) + ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array) + gEfiLegacyDevOrderVariableGuid + +[Protocols] + gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES + +[FeaturePcd] + +[Pcd] diff --git a/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.uni b/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.uni new file mode 100644 index 0000000000..2585c93496 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c new file mode 100644 index 0000000000..ada9a809fa --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c @@ -0,0 +1,218 @@ +/** @file + LZMA Decompress GUIDed Section Extraction Library, which produces LZMA custom + decompression algorithm with the converter for the different arch code. + It wraps Lzma decompress interfaces to GUIDed Section Extraction interfaces + and registers them into GUIDed handler table. + + 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. + +**/ + +#include "LzmaDecompressLibInternal.h" +#include "Sdk/C/Bra.h" + +/** + Examines a GUIDed section and returns the size of the decoded buffer and the + size of an scratch buffer required to actually decode the data in a GUIDed section. + + Examines a GUIDed section specified by InputSection. + If GUID for InputSection does not match the GUID that this handler supports, + then RETURN_UNSUPPORTED is returned. + If the required information can not be retrieved from InputSection, + then RETURN_INVALID_PARAMETER is returned. + If the GUID of InputSection does match the GUID that this handler supports, + then the size required to hold the decoded buffer is returned in OututBufferSize, + the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field + from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute. + + If InputSection is NULL, then ASSERT(). + If OutputBufferSize is NULL, then ASSERT(). + If ScratchBufferSize is NULL, then ASSERT(). + If SectionAttribute is NULL, then ASSERT(). + + + @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. + @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required + if the buffer specified by InputSection were decoded. + @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space + if the buffer specified by InputSection were decoded. + @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes + field of EFI_GUID_DEFINED_SECTION in the PI Specification. + + @retval RETURN_SUCCESS The information about InputSection was returned. + @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. + @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection. + +**/ +RETURN_STATUS +EFIAPI +LzmaArchGuidedSectionGetInfo ( + IN CONST VOID *InputSection, + OUT UINT32 *OutputBufferSize, + OUT UINT32 *ScratchBufferSize, + OUT UINT16 *SectionAttribute + ) +{ + ASSERT (InputSection != NULL); + ASSERT (OutputBufferSize != NULL); + ASSERT (ScratchBufferSize != NULL); + ASSERT (SectionAttribute != NULL); + + if (IS_SECTION2 (InputSection)) { + if (!CompareGuid ( + &gLzmaF86CustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + + *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes; + + return LzmaUefiDecompressGetInfo ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + OutputBufferSize, + ScratchBufferSize + ); + } else { + if (!CompareGuid ( + &gLzmaF86CustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + + *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes; + + return LzmaUefiDecompressGetInfo ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + OutputBufferSize, + ScratchBufferSize + ); + } +} + +/** + Decompress a LZAM compressed GUIDed section into a caller allocated output buffer. + + Decodes the GUIDed section specified by InputSection. + If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned. + If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned. + If the GUID of InputSection does match the GUID that this handler supports, then InputSection + is decoded into the buffer specified by OutputBuffer and the authentication status of this + decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the + data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise, + the decoded data will be placed in caller allocated buffer specified by OutputBuffer. + + If InputSection is NULL, then ASSERT(). + If OutputBuffer is NULL, then ASSERT(). + If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT(). + If AuthenticationStatus is NULL, then ASSERT(). + + + @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. + @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation. + @param[out] ScratchBuffer A caller allocated buffer that may be required by this function + as a scratch buffer to perform the decode operation. + @param[out] AuthenticationStatus + A pointer to the authentication status of the decoded output buffer. + See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI + section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must + never be set by this handler. + + @retval RETURN_SUCCESS The buffer specified by InputSection was decoded. + @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. + @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded. + +**/ +RETURN_STATUS +EFIAPI +LzmaArchGuidedSectionExtraction ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + OUT VOID *ScratchBuffer, OPTIONAL + OUT UINT32 *AuthenticationStatus + ) +{ + EFI_GUID *InputGuid; + VOID *Source; + UINTN SourceSize; + EFI_STATUS Status; + UINT32 X86State; + UINT32 OutputBufferSize; + UINT32 ScratchBufferSize; + + ASSERT (OutputBuffer != NULL); + ASSERT (InputSection != NULL); + + if (IS_SECTION2 (InputSection)) { + InputGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid); + Source = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset; + SourceSize = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset; + } else { + InputGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid); + Source = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset; + SourceSize = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset; + } + + if (!CompareGuid (&gLzmaF86CustomDecompressGuid, InputGuid)) { + return RETURN_INVALID_PARAMETER; + } + + // + // Authentication is set to Zero, which may be ignored. + // + *AuthenticationStatus = 0; + + Status = LzmaUefiDecompress ( + Source, + SourceSize, + *OutputBuffer, + ScratchBuffer + ); + + // + // After decompress, the data need to be converted to the raw data. + // + if (!EFI_ERROR (Status)) { + Status = LzmaUefiDecompressGetInfo ( + Source, + (UINT32) SourceSize, + &OutputBufferSize, + &ScratchBufferSize + ); + + if (!EFI_ERROR (Status)) { + x86_Convert_Init(X86State); + x86_Convert(*OutputBuffer, OutputBufferSize, 0, &X86State, 0); + } + } + + return Status; +} + + +/** + Register LzmaArchDecompress and LzmaArchDecompressGetInfo handlers with LzmaF86CustomDecompressGuid. + + @retval RETURN_SUCCESS Register successfully. + @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler. +**/ +EFI_STATUS +EFIAPI +LzmaArchDecompressLibConstructor ( + ) +{ + return ExtractGuidedSectionRegisterHandlers ( + &gLzmaF86CustomDecompressGuid, + LzmaArchGuidedSectionGetInfo, + LzmaArchGuidedSectionExtraction + ); +} + diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/GuidedSectionExtraction.c b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/GuidedSectionExtraction.c new file mode 100644 index 0000000000..f19e0d28cd --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/GuidedSectionExtraction.c @@ -0,0 +1,201 @@ +/** @file + LZMA Decompress GUIDed Section Extraction Library. + It wraps Lzma decompress interfaces to GUIDed Section Extraction interfaces + and registers them into GUIDed handler table. + + Copyright (c) 2009 - 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 "LzmaDecompressLibInternal.h" + +/** + Examines a GUIDed section and returns the size of the decoded buffer and the + size of an scratch buffer required to actually decode the data in a GUIDed section. + + Examines a GUIDed section specified by InputSection. + If GUID for InputSection does not match the GUID that this handler supports, + then RETURN_UNSUPPORTED is returned. + If the required information can not be retrieved from InputSection, + then RETURN_INVALID_PARAMETER is returned. + If the GUID of InputSection does match the GUID that this handler supports, + then the size required to hold the decoded buffer is returned in OututBufferSize, + the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field + from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute. + + If InputSection is NULL, then ASSERT(). + If OutputBufferSize is NULL, then ASSERT(). + If ScratchBufferSize is NULL, then ASSERT(). + If SectionAttribute is NULL, then ASSERT(). + + + @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. + @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required + if the buffer specified by InputSection were decoded. + @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space + if the buffer specified by InputSection were decoded. + @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes + field of EFI_GUID_DEFINED_SECTION in the PI Specification. + + @retval RETURN_SUCCESS The information about InputSection was returned. + @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. + @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection. + +**/ +RETURN_STATUS +EFIAPI +LzmaGuidedSectionGetInfo ( + IN CONST VOID *InputSection, + OUT UINT32 *OutputBufferSize, + OUT UINT32 *ScratchBufferSize, + OUT UINT16 *SectionAttribute + ) +{ + ASSERT (InputSection != NULL); + ASSERT (OutputBufferSize != NULL); + ASSERT (ScratchBufferSize != NULL); + ASSERT (SectionAttribute != NULL); + + if (IS_SECTION2 (InputSection)) { + if (!CompareGuid ( + &gLzmaCustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + + *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes; + + return LzmaUefiDecompressGetInfo ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + OutputBufferSize, + ScratchBufferSize + ); + } else { + if (!CompareGuid ( + &gLzmaCustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + + *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes; + + return LzmaUefiDecompressGetInfo ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + OutputBufferSize, + ScratchBufferSize + ); + } +} + +/** + Decompress a LZAM compressed GUIDed section into a caller allocated output buffer. + + Decodes the GUIDed section specified by InputSection. + If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned. + If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned. + If the GUID of InputSection does match the GUID that this handler supports, then InputSection + is decoded into the buffer specified by OutputBuffer and the authentication status of this + decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the + data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise, + the decoded data will be placed in caller allocated buffer specified by OutputBuffer. + + If InputSection is NULL, then ASSERT(). + If OutputBuffer is NULL, then ASSERT(). + If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT(). + If AuthenticationStatus is NULL, then ASSERT(). + + + @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. + @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation. + @param[out] ScratchBuffer A caller allocated buffer that may be required by this function + as a scratch buffer to perform the decode operation. + @param[out] AuthenticationStatus + A pointer to the authentication status of the decoded output buffer. + See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI + section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must + never be set by this handler. + + @retval RETURN_SUCCESS The buffer specified by InputSection was decoded. + @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. + @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded. + +**/ +RETURN_STATUS +EFIAPI +LzmaGuidedSectionExtraction ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + OUT VOID *ScratchBuffer, OPTIONAL + OUT UINT32 *AuthenticationStatus + ) +{ + ASSERT (OutputBuffer != NULL); + ASSERT (InputSection != NULL); + + if (IS_SECTION2 (InputSection)) { + if (!CompareGuid ( + &gLzmaCustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + + // + // Authentication is set to Zero, which may be ignored. + // + *AuthenticationStatus = 0; + + return LzmaUefiDecompress ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, + *OutputBuffer, + ScratchBuffer + ); + } else { + if (!CompareGuid ( + &gLzmaCustomDecompressGuid, + &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { + return RETURN_INVALID_PARAMETER; + } + + // + // Authentication is set to Zero, which may be ignored. + // + *AuthenticationStatus = 0; + + return LzmaUefiDecompress ( + (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, + *OutputBuffer, + ScratchBuffer + ); + } +} + + +/** + Register LzmaDecompress and LzmaDecompressGetInfo handlers with LzmaCustomerDecompressGuid. + + @retval RETURN_SUCCESS Register successfully. + @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler. +**/ +EFI_STATUS +EFIAPI +LzmaDecompressLibConstructor ( + ) +{ + return ExtractGuidedSectionRegisterHandlers ( + &gLzmaCustomDecompressGuid, + LzmaGuidedSectionGetInfo, + LzmaGuidedSectionExtraction + ); +} + diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt new file mode 100644 index 0000000000..e05b3bb853 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt @@ -0,0 +1,4 @@ +LzmaCustomDecompressLib is based on the LZMA SDK 4.65. +LZMA SDK 4.65 was placed in the public domain on +2009-02-03. It was released on the +http://www.7-zip.org/sdk.html website. \ No newline at end of file diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf new file mode 100644 index 0000000000..ec7585d55b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf @@ -0,0 +1,66 @@ +## @file +# LzmaArchCustomDecompressLib produces LZMA custom decompression algorithm with the converter for the different arch code. +# +# It is based on the LZMA SDK 4.65. +# LZMA SDK 4.65 was placed in the public domain on 2009-02-03. +# It was released on the http://www.7-zip.org/sdk.html website. +# +# Copyright (c) 2012 - 2015, Intel 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 = LzmaArchDecompressLib + MODULE_UNI_FILE = LzmaArchDecompressLib.uni + FILE_GUID = A853C1D2-E003-4cc4-9DD1-8824AD79FE48 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + CONSTRUCTOR = LzmaArchDecompressLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + LzmaDecompress.c + Sdk/C/Bra.h + Sdk/C/LzFind.c + Sdk/C/LzmaDec.c + Sdk/C/7zVersion.h + Sdk/C/CpuArch.h + Sdk/C/LzFind.h + Sdk/C/LzHash.h + Sdk/C/LzmaDec.h + Sdk/C/Types.h + UefiLzma.h + LzmaDecompressLibInternal.h + +[Sources.Ia32, Sources.X64] + Sdk/C/Bra86.c + F86GuidedSectionExtraction.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[Guids.Ia32, Guids.X64] + gLzmaF86CustomDecompressGuid ## PRODUCES ## GUID # specifies LZMA custom decompress algorithm with converter for x86 code. + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + ExtractGuidedSectionLib + diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchDecompressLib.uni b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchDecompressLib.uni new file mode 100644 index 0000000000..1830dae73c Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchDecompressLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf new file mode 100644 index 0000000000..f5624fd039 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf @@ -0,0 +1,62 @@ +## @file +# LzmaCustomDecompressLib produces LZMA custom decompression algorithm. +# +# It is based on the LZMA SDK 4.65. +# LZMA SDK 4.65 was placed in the public domain on 2009-02-03. +# It was released on the http://www.7-zip.org/sdk.html website. +# +# Copyright (c) 2009 - 2015, Intel 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 = LzmaDecompressLib + MODULE_UNI_FILE = LzmaDecompressLib.uni + FILE_GUID = 35194660-7421-44ad-9636-e44885f092d1 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + CONSTRUCTOR = LzmaDecompressLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + LzmaDecompress.c + Sdk/C/LzFind.c + Sdk/C/LzmaDec.c + Sdk/C/7zVersion.h + Sdk/C/CpuArch.h + Sdk/C/LzFind.h + Sdk/C/LzHash.h + Sdk/C/LzmaDec.h + Sdk/C/Types.h + GuidedSectionExtraction.c + UefiLzma.h + LzmaDecompressLibInternal.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[Guids] + gLzmaCustomDecompressGuid ## PRODUCES ## UNDEFINED # specifies LZMA custom decompress algorithm. + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + ExtractGuidedSectionLib + diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c new file mode 100644 index 0000000000..e32b6a3025 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c @@ -0,0 +1,220 @@ +/** @file + LZMA Decompress interfaces + + Copyright (c) 2009 - 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 "LzmaDecompressLibInternal.h" +#include "Sdk/C/Types.h" +#include "Sdk/C/7zVersion.h" +#include "Sdk/C/LzmaDec.h" + +#define SCRATCH_BUFFER_REQUEST_SIZE SIZE_64KB + +typedef struct +{ + ISzAlloc Functions; + VOID *Buffer; + UINTN BufferSize; +} ISzAllocWithData; + +/** + Allocation routine used by LZMA decompression. + + @param P Pointer to the ISzAlloc instance + @param Size The size in bytes to be allocated + + @return The allocated pointer address, or NULL on failure +**/ +VOID * +SzAlloc ( + VOID *P, + size_t Size + ) +{ + VOID *Addr; + ISzAllocWithData *Private; + + Private = (ISzAllocWithData*) P; + + if (Private->BufferSize >= Size) { + Addr = Private->Buffer; + Private->Buffer = (VOID*) ((UINT8*)Addr + Size); + Private->BufferSize -= Size; + return Addr; + } else { + ASSERT (FALSE); + return NULL; + } +} + +/** + Free routine used by LZMA decompression. + + @param P Pointer to the ISzAlloc instance + @param Address The address to be freed +**/ +VOID +SzFree ( + VOID *P, + VOID *Address + ) +{ + // + // We use the 'scratch buffer' for allocations, so there is no free + // operation required. The scratch buffer will be freed by the caller + // of the decompression code. + // +} + +#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) + +/** + Get the size of the uncompressed buffer by parsing EncodeData header. + + @param EncodedData Pointer to the compressed data. + + @return The size of the uncompressed buffer. +**/ +UINT64 +GetDecodedSizeOfBuf( + UINT8 *EncodedData + ) +{ + UINT64 DecodedSize; + INTN Index; + + /* Parse header */ + DecodedSize = 0; + for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--) + DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index]; + + return DecodedSize; +} + +// +// LZMA functions and data as defined in local LzmaDecompressLibInternal.h +// + +/** + Given a Lzma compressed source buffer, this function retrieves the size of + the uncompressed buffer and the size of the scratch buffer required + to decompress the compressed source buffer. + + Retrieves the size of the uncompressed buffer and the temporary scratch buffer + required to decompress the buffer specified by Source and SourceSize. + The size of the uncompressed buffer is returned in DestinationSize, + the size of the scratch buffer is returned in ScratchSize, and RETURN_SUCCESS is returned. + This function does not have scratch buffer available to perform a thorough + checking of the validity of the source data. It just retrieves the "Original Size" + field from the LZMA_HEADER_SIZE beginning bytes of the source data and output it as DestinationSize. + And ScratchSize is specific to the decompression implementation. + + If SourceSize is less than LZMA_HEADER_SIZE, then ASSERT(). + + @param Source The source buffer containing the compressed data. + @param SourceSize The size, in bytes, of the source buffer. + @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer + that will be generated when the compressed buffer specified + by Source and SourceSize is decompressed. + @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that + is required to decompress the compressed buffer specified + by Source and SourceSize. + + @retval RETURN_SUCCESS The size of the uncompressed data was returned + in DestinationSize and the size of the scratch + buffer was returned in ScratchSize. + +**/ +RETURN_STATUS +EFIAPI +LzmaUefiDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +{ + UInt64 DecodedSize; + + ASSERT(SourceSize >= LZMA_HEADER_SIZE); + + DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source); + + *DestinationSize = (UINT32)DecodedSize; + *ScratchSize = SCRATCH_BUFFER_REQUEST_SIZE; + return RETURN_SUCCESS; +} + +/** + Decompresses a Lzma compressed source buffer. + + Extracts decompressed data to its original form. + If the compressed source data specified by Source is successfully decompressed + into Destination, then RETURN_SUCCESS is returned. If the compressed source data + specified by Source is not in a valid compressed data format, + then RETURN_INVALID_PARAMETER is returned. + + @param Source The source buffer containing the compressed data. + @param SourceSize The size of source buffer. + @param Destination The destination buffer to store the decompressed data + @param Scratch A temporary scratch buffer that is used to perform the decompression. + This is an optional parameter that may be NULL if the + required scratch buffer size is 0. + + @retval RETURN_SUCCESS Decompression completed successfully, and + the uncompressed buffer is returned in Destination. + @retval RETURN_INVALID_PARAMETER + The source buffer specified by Source is corrupted + (not in a valid compressed format). +**/ +RETURN_STATUS +EFIAPI +LzmaUefiDecompress ( + IN CONST VOID *Source, + IN UINTN SourceSize, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ) +{ + SRes LzmaResult; + ELzmaStatus Status; + SizeT DecodedBufSize; + SizeT EncodedDataSize; + ISzAllocWithData AllocFuncs; + + AllocFuncs.Functions.Alloc = SzAlloc; + AllocFuncs.Functions.Free = SzFree; + AllocFuncs.Buffer = Scratch; + AllocFuncs.BufferSize = SCRATCH_BUFFER_REQUEST_SIZE; + + DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source); + EncodedDataSize = (SizeT) (SourceSize - LZMA_HEADER_SIZE); + + LzmaResult = LzmaDecode( + Destination, + &DecodedBufSize, + (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE), + &EncodedDataSize, + Source, + LZMA_PROPS_SIZE, + LZMA_FINISH_END, + &Status, + &(AllocFuncs.Functions) + ); + + if (LzmaResult == SZ_OK) { + return RETURN_SUCCESS; + } else { + return RETURN_INVALID_PARAMETER; + } +} + diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLib.uni b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLib.uni new file mode 100644 index 0000000000..498e4e1088 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h new file mode 100644 index 0000000000..3096e91dbe --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h @@ -0,0 +1,96 @@ +/** @file + LZMA Decompress Library internal header file declares Lzma decompress interfaces. + + Copyright (c) 2009 - 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 __LZMADECOMPRESSLIB_INTERNAL_H__ +#define __LZMADECOMPRESSLIB_INTERNAL_H__ + +#include +#include +#include +#include +#include +#include + +/** + Given a Lzma compressed source buffer, this function retrieves the size of + the uncompressed buffer and the size of the scratch buffer required + to decompress the compressed source buffer. + + Retrieves the size of the uncompressed buffer and the temporary scratch buffer + required to decompress the buffer specified by Source and SourceSize. + The size of the uncompressed buffer is returned in DestinationSize, + the size of the scratch buffer is returned in ScratchSize, and RETURN_SUCCESS is returned. + This function does not have scratch buffer available to perform a thorough + checking of the validity of the source data. It just retrieves the "Original Size" + field from the LZMA_HEADER_SIZE beginning bytes of the source data and output it as DestinationSize. + And ScratchSize is specific to the decompression implementation. + + If SourceSize is less than LZMA_HEADER_SIZE, then ASSERT(). + + @param Source The source buffer containing the compressed data. + @param SourceSize The size, in bytes, of the source buffer. + @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer + that will be generated when the compressed buffer specified + by Source and SourceSize is decompressed. + @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that + is required to decompress the compressed buffer specified + by Source and SourceSize. + + @retval RETURN_SUCCESS The size of the uncompressed data was returned + in DestinationSize and the size of the scratch + buffer was returned in ScratchSize. + +**/ +RETURN_STATUS +EFIAPI +LzmaUefiDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +/** + Decompresses a Lzma compressed source buffer. + + Extracts decompressed data to its original form. + If the compressed source data specified by Source is successfully decompressed + into Destination, then RETURN_SUCCESS is returned. If the compressed source data + specified by Source is not in a valid compressed data format, + then RETURN_INVALID_PARAMETER is returned. + + @param Source The source buffer containing the compressed data. + @param SourceSize The size of source buffer. + @param Destination The destination buffer to store the decompressed data + @param Scratch A temporary scratch buffer that is used to perform the decompression. + This is an optional parameter that may be NULL if the + required scratch buffer size is 0. + + @retval RETURN_SUCCESS Decompression completed successfully, and + the uncompressed buffer is returned in Destination. + @retval RETURN_INVALID_PARAMETER + The source buffer specified by Source is corrupted + (not in a valid compressed format). +**/ +RETURN_STATUS +EFIAPI +LzmaUefiDecompress ( + IN CONST VOID *Source, + IN UINTN SourceSize, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h new file mode 100644 index 0000000000..5a6bcadac6 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h @@ -0,0 +1,7 @@ +#define MY_VER_MAJOR 4 +#define MY_VER_MINOR 65 +#define MY_VER_BUILD 0 +#define MY_VERSION "4.65" +#define MY_DATE "2009-02-03" +#define MY_COPYRIGHT ": Igor Pavlov : Public domain" +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h new file mode 100644 index 0000000000..b9018eb991 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h @@ -0,0 +1,60 @@ +/* Bra.h -- Branch converters for executables +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "Types.h" + +/* +These functions convert relative addresses to absolute addresses +in CALL instructions to increase the compression ratio. + + In: + data - data buffer + size - size of data + ip - current virtual Instruction Pinter (IP) value + state - state variable for x86 converter + encoding - 0 (for decoding), 1 (for encoding) + + Out: + state - state variable for x86 converter + + Returns: + The number of processed bytes. If you call these functions with multiple calls, + you must start next call with first byte after block of processed bytes. + + Type Endian Alignment LookAhead + + x86 little 1 4 + ARMT little 2 2 + ARM little 4 0 + PPC big 4 0 + SPARC big 4 0 + IA64 little 16 0 + + size must be >= Alignment + LookAhead, if it's not last block. + If (size < Alignment + LookAhead), converter returns 0. + + Example: + + UInt32 ip = 0; + for () + { + ; size must be >= Alignment + LookAhead, if it's not last block + SizeT processed = Convert(data, size, ip, 1); + data += processed; + size -= processed; + ip += processed; + } +*/ + +#define x86_Convert_Init(state) { state = 0; } +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c new file mode 100644 index 0000000000..93566cb212 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c @@ -0,0 +1,85 @@ +/* Bra86.c -- Converter for x86 code (BCJ) +2008-10-04 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) + +const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; +const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; + +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +{ + SizeT bufferPos = 0, prevPosT; + UInt32 prevMask = *state & 0x7; + if (size < 5) + return 0; + ip += 5; + prevPosT = (SizeT)0 - 1; + + for (;;) + { + Byte *p = data + bufferPos; + Byte *limit = data + size - 4; + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + bufferPos = (SizeT)(p - data); + if (p >= limit) + break; + prevPosT = bufferPos - prevPosT; + if (prevPosT > 3) + prevMask = 0; + else + { + prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; + if (prevMask != 0) + { + Byte b = p[4 - kMaskToBitNumber[prevMask]]; + if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) + { + prevPosT = bufferPos; + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + continue; + } + } + } + prevPosT = bufferPos; + + if (Test86MSByte(p[4])) + { + UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 dest; + for (;;) + { + Byte b; + int index; + if (encoding) + dest = (ip + (UInt32)bufferPos) + src; + else + dest = src - (ip + (UInt32)bufferPos); + if (prevMask == 0) + break; + index = kMaskToBitNumber[prevMask] * 8; + b = (Byte)(dest >> (24 - index)); + if (!Test86MSByte(b)) + break; + src = dest ^ ((1 << (32 - index)) - 1); + } + p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); + p[3] = (Byte)(dest >> 16); + p[2] = (Byte)(dest >> 8); + p[1] = (Byte)dest; + bufferPos += 5; + } + else + { + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + } + } + prevPosT = bufferPos - prevPosT; + *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); + return bufferPos; +} diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h new file mode 100644 index 0000000000..006361f2f2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h @@ -0,0 +1,69 @@ +/* CpuArch.h +2008-08-05 +Igor Pavlov +Public domain */ + +#ifndef __CPUARCH_H +#define __CPUARCH_H + +/* +LITTLE_ENDIAN_UNALIGN means: + 1) CPU is LITTLE_ENDIAN + 2) it's allowed to make unaligned memory accesses +if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know +about these properties of platform. +*/ + +#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) +#define LITTLE_ENDIAN_UNALIGN +#endif + +#ifdef LITTLE_ENDIAN_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(p)) +#define GetUi32(p) (*(const UInt32 *)(p)) +#define GetUi64(p) (*(const UInt64 *)(p)) +#define SetUi32(p, d) *(UInt32 *)(p) = (d); + +#else + +#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) + +#define GetUi32(p) ( \ + ((const Byte *)(p))[0] | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((UInt32)((const Byte *)(p))[2] << 16) | \ + ((UInt32)((const Byte *)(p))[3] << 24)) + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + +#define SetUi32(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ + ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ + ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } + +#endif + +#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) + +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) +#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) + +#else + +#define GetBe32(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 24) | \ + ((UInt32)((const Byte *)(p))[1] << 16) | \ + ((UInt32)((const Byte *)(p))[2] << 8) | \ + ((const Byte *)(p))[3] ) + +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) + +#endif + +#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c new file mode 100644 index 0000000000..492cea2e41 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c @@ -0,0 +1,770 @@ +/** @file + LzFind.c + + Based on LZMA SDK 4.65: + LzFind.c -- Match finder for LZ algorithms + 2008-10-04 : Igor Pavlov : Public domain + + Copyright (c) 2009, Intel 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 EFIAPI + +#include + +#endif // !EFIAPI + +#include "LzFind.h" +#include "LzHash.h" + +#define kEmptyHashValue 0 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ +#define kNormalizeMask (~(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)3 << 30) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + if (!p->directInput) + { + alloc->Free(alloc, p->bufferBase); + p->bufferBase = 0; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (p->bufferBase == 0 || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != 0); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } + +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +{ + p->posLimit -= subValue; + p->pos -= subValue; + p->streamPos -= subValue; +} + +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + for (;;) + { + Byte *dest = p->buffer + (p->streamPos - p->pos); + size_t size = (p->bufferBase + p->blockSize - dest); + if (size == 0) + return; + p->result = p->stream->Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (p->streamPos - p->pos > p->keepSizeAfter) + return; + } +} + +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, + (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); + p->buffer = p->bufferBase + p->keepSizeBefore; +} + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->streamEndWasReached) + return; + if (p->keepSizeAfter >= p->streamPos - p->pos) + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +{ + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + /* p->skipModeBits = 0; */ + p->directInput = 0; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + UInt32 i; + p->bufferBase = 0; + p->directInput = 0; + p->hash = 0; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hash); + p->hash = 0; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return 0; + return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc) +{ + UInt32 sizeReserv; + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + sizeReserv = historySize >> 1; + if (historySize > ((UInt32)2 << 30)) + sizeReserv = historySize >> 2; + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); + + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ + if (LzInWindow_Create(p, sizeReserv, alloc)) + { + UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + p->fixedHashSize = 0; + if (p->numHashBytes == 2) + hs = (1 << 16) - 1; + else + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + /* hs >>= p->skipModeBits; */ + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ + if (hs > (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + } + } + p->hashMask = hs; + hs++; + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + hs += p->fixedHashSize; + } + + { + UInt32 prevSize = p->hashSizeSum + p->numSons; + UInt32 newSize; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); + newSize = p->hashSizeSum + p->numSons; + if (p->hash != 0 && prevSize == newSize) + return 1; + MatchFinder_FreeThisClassMemory(p, alloc); + p->hash = AllocRefs(newSize, alloc); + if (p->hash != 0) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + MatchFinder_Free(p, alloc); + return 0; +} + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 limit = kMaxValForNormalize - p->pos; + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + if (limit2 < limit) + limit = limit2; + limit2 = p->streamPos - p->pos; + if (limit2 <= p->keepSizeAfter) + { + if (limit2 > 0) + limit2 = 1; + } + else + limit2 -= p->keepSizeAfter; + if (limit2 < limit) + limit = limit2; + { + UInt32 lenLimit = p->streamPos - p->pos; + if (lenLimit > p->matchMaxLen) + lenLimit = p->matchMaxLen; + p->lenLimit = lenLimit; + } + p->posLimit = p->pos + limit; +} + +void MatchFinder_Init(CMatchFinder *p) +{ + UInt32 i; + for (i = 0; i < p->hashSizeSum; i++) + p->hash[i] = kEmptyHashValue; + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + MatchFinder_ReadBlock(p); + MatchFinder_SetLimits(p); +} + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +{ + UInt32 i; + for (i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } +} + +static void MatchFinder_Normalize(CMatchFinder *p) +{ + UInt32 subValue = MatchFinder_GetSubValue(p); + MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); + MatchFinder_ReduceOffsets(p, subValue); +} + +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (p->pos == kMaxValForNormalize) + MatchFinder_Normalize(p); + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) + MatchFinder_CheckAndMoveAndRead(p); + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); +} + +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return distances; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + return distances; + } + } + } + } +} + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return distances; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return distances; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +#define MOVE_POS_RET MOVE_POS return offset; + +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define GET_MATCHES_FOOTER(offset, maxLen) \ + offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ + distances + offset, maxLen) - distances); MOVE_POS_RET; + +#define SKIP_FOOTER \ + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 1) +} + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, delta2, maxLen, offset; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + delta2 = p->pos - p->hash[hash2Value]; + curMatch = p->hash[kFix3HashSize + hashValue]; + + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + + + maxLen = 2; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[0] = maxLen; + distances[1] = delta2 - 1; + offset = 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances, 2) - (distances)); + MOVE_POS_RET +} + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value; + SKIP_HEADER(3) + HASH3_CALC; + curMatch = p->hash[kFix3HashSize + hashValue]; + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = p->pos; + p->hash[kFix4HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } +} diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h new file mode 100644 index 0000000000..423d67e0c3 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h @@ -0,0 +1,107 @@ +/* LzFind.h -- Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZFIND_H +#define __LZFIND_H + +#include "Types.h" + +typedef UInt32 CLzRef; + +typedef struct _CMatchFinder +{ + Byte *buffer; + UInt32 pos; + UInt32 posLimit; + UInt32 streamPos; + UInt32 lenLimit; + + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + int streamEndWasReached; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + int directInput; + int btMode; + /* int skipModeBits; */ + int bigHash; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + UInt32 numSons; + SRes result; + UInt32 crc[256]; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +int MatchFinder_NeedMove(CMatchFinder *p); +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +void MatchFinder_MoveBlock(CMatchFinder *p); +void MatchFinder_ReadIfRequired(CMatchFinder *p); + +void MatchFinder_Construct(CMatchFinder *p); + +/* Conditions: + historySize <= 3 GB + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +*/ +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 maxLen); + +/* +Conditions: + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +*/ + +typedef void (*Mf_Init_Func)(void *object); +typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetIndexByte_Func GetIndexByte; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +void MatchFinder_Init(CMatchFinder *p); +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h new file mode 100644 index 0000000000..c923417501 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h @@ -0,0 +1,54 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZHASH_H +#define __LZHASH_H + +#define kHash2Size (1 << 10) +#define kHash3Size (1 << 16) +#define kHash4Size (1 << 20) + +#define kFix3HashSize (kHash2Size) +#define kFix4HashSize (kHash2Size + kHash3Size) +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) + +#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); + +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ + hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ + hash4Value &= (kHash4Size - 1); } + +/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +#define MT_HASH2_CALC \ + hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c new file mode 100644 index 0000000000..e3db4edbb4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c @@ -0,0 +1,1026 @@ +/** @file + LzmaDec.c + + Based on LZMA SDK 4.65: + LzmaDec.c -- LZMA Decoder + 2008-11-06 : Igor Pavlov : Public domain + + Copyright (c) 2009, Intel 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 "LzmaDec.h" + +#ifndef EFIAPI + +#include + +#endif // !EFIAPI + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +static const Byte kLiteralNextStates[kNumStates * 2] = +{ + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, + 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 +}; + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.lc; + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); + + if (state < kNumLitStates) + { + symbol = 1; + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + + state = kLiteralNextStates[state]; + /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + { + unsigned limit2, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit2 = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit2 = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit2 = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit2, len); + len += offset; + } + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while (--numDirectBits != 0); + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + /* state = kLiteralNextStates[state]; */ + } + + len += kMatchMinLen; + + if (limit == dicPos) + return SZ_ERROR_DATA; + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *((volatile Byte *)dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + NORMALIZE; + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len-- != 0) + { + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += (LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while (--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + p->needInitState = 0; +} + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + checkEndMarkNow = 0; + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->needInitState) + LzmaDec_InitStateReal(p); + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT inSize = *srcLen; + SizeT outSize = *destLen; + *srcLen = *destLen = 0; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + + LzmaDec_Construct(&p); + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); + if (res != 0) + return res; + p.dic = dest; + p.dicBufSize = outSize; + + LzmaDec_Init(&p); + + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + (*destLen) = p.dicPos; + LzmaDec_FreeProbs(&p, alloc); + return res; +} + diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.h new file mode 100644 index 0000000000..ad7d7057a4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.h @@ -0,0 +1,223 @@ +/* LzmaDec.h -- LZMA Decoder +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZMADEC_H +#define __LZMADEC_H + +#include "Types.h" + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); + +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Constr() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Types.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Types.h new file mode 100644 index 0000000000..30b16e3bb0 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Types.h @@ -0,0 +1,231 @@ +/** @file + Types.h + + Based on LZMA SDK 4.65: + Types.h -- Basic types + 2008-11-23 : Igor Pavlov : Public domain + + Copyright (c) 2009, Intel 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 __7Z_TYPES_H +#define __7Z_TYPES_H + +#ifdef EFIAPI + +#include "UefiLzma.h" + +#else + +#include + +#ifdef _WIN32 +#include +#endif + +#endif + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_STD_CALL __stdcall +#define MY_FAST_CALL MY_NO_INLINE __fastcall + +#else + +#define MY_CDECL +#define MY_STD_CALL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#endif diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/history.txt b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/history.txt new file mode 100644 index 0000000000..9bed5ebbef --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/history.txt @@ -0,0 +1,236 @@ +HISTORY of the LZMA SDK +----------------------- + +4.65 2009-02-03 +------------------------- +- Some minor fixes + + +4.63 2008-12-31 +------------------------- +- Some minor fixes + + +4.61 beta 2008-11-23 +------------------------- +- The bug in ANSI-C LZMA Decoder was fixed: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. +- Some changes in ANSI-C 7z Decoder interfaces. +- LZMA SDK is placed in the public domain. + + +4.60 beta 2008-08-19 +------------------------- +- Some minor fixes. + + +4.59 beta 2008-08-13 +------------------------- +- The bug was fixed: + LZMA Encoder in fast compression mode could access memory outside of + allocated range in some rare cases. + + +4.58 beta 2008-05-05 +------------------------- +- ANSI-C LZMA Decoder was rewritten for speed optimizations. +- ANSI-C LZMA Encoder was included to LZMA SDK. +- C++ LZMA code now is just wrapper over ANSI-C code. + + +4.57 2007-12-12 +------------------------- +- Speed optimizations in Ñ++ LZMA Decoder. +- Small changes for more compatibility with some C/C++ compilers. + + +4.49 beta 2007-07-05 +------------------------- +- .7z ANSI-C Decoder: + - now it supports BCJ and BCJ2 filters + - now it supports files larger than 4 GB. + - now it supports "Last Write Time" field for files. +- C++ code for .7z archives compressing/decompressing from 7-zip + was included to LZMA SDK. + + +4.43 2006-06-04 +------------------------- +- Small changes for more compatibility with some C/C++ compilers. + + +4.42 2006-05-15 +------------------------- +- Small changes in .h files in ANSI-C version. + + +4.39 beta 2006-04-14 +------------------------- +- The bug in versions 4.33b:4.38b was fixed: + C++ version of LZMA encoder could not correctly compress + files larger than 2 GB with HC4 match finder (-mfhc4). + + +4.37 beta 2005-04-06 +------------------------- +- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. + + +4.35 beta 2005-03-02 +------------------------- +- The bug was fixed in C++ version of LZMA Decoder: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. + + +4.34 beta 2006-02-27 +------------------------- +- Compressing speed and memory requirements for compressing were increased +- LZMA now can use only these match finders: HC4, BT2, BT3, BT4 + + +4.32 2005-12-09 +------------------------- +- Java version of LZMA SDK was included + + +4.30 2005-11-20 +------------------------- +- Compression ratio was improved in -a2 mode +- Speed optimizations for compressing in -a2 mode +- -fb switch now supports values up to 273 +- The bug in 7z_C (7zIn.c) was fixed: + It used Alloc/Free functions from different memory pools. + So if program used two memory pools, it worked incorrectly. +- 7z_C: .7z format supporting was improved +- LZMA# SDK (C#.NET version) was included + + +4.27 (Updated) 2005-09-21 +------------------------- +- Some GUIDs/interfaces in C++ were changed. + IStream.h: + ISequentialInStream::Read now works as old ReadPart + ISequentialOutStream::Write now works as old WritePart + + +4.27 2005-08-07 +------------------------- +- The bug in LzmaDecodeSize.c was fixed: + if _LZMA_IN_CB and _LZMA_OUT_READ were defined, + decompressing worked incorrectly. + + +4.26 2005-08-05 +------------------------- +- Fixes in 7z_C code and LzmaTest.c: + previous versions could work incorrectly, + if malloc(0) returns 0 + + +4.23 2005-06-29 +------------------------- +- Small fixes in C++ code + + +4.22 2005-06-10 +------------------------- +- Small fixes + + +4.21 2005-06-08 +------------------------- +- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed +- New additional version of ANSI-C LZMA Decoder with zlib-like interface: + - LzmaStateDecode.h + - LzmaStateDecode.c + - LzmaStateTest.c +- ANSI-C LZMA Decoder now can decompress files larger than 4 GB + + +4.17 2005-04-18 +------------------------- +- New example for RAM->RAM compressing/decompressing: + LZMA + BCJ (filter for x86 code): + - LzmaRam.h + - LzmaRam.cpp + - LzmaRamDecode.h + - LzmaRamDecode.c + - -f86 switch for lzma.exe + + +4.16 2005-03-29 +------------------------- +- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): + If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, + decoder could access memory outside of allocated range. +- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). + Old version of LZMA Decoder now is in file LzmaDecodeSize.c. + LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c +- Small speed optimization in LZMA C++ code +- filter for SPARC's code was added +- Simplified version of .7z ANSI-C Decoder was included + + +4.06 2004-09-05 +------------------------- +- The bug in v4.05 was fixed: + LZMA-Encoder didn't release output stream in some cases. + + +4.05 2004-08-25 +------------------------- +- Source code of filters for x86, IA-64, ARM, ARM-Thumb + and PowerPC code was included to SDK +- Some internal minor changes + + +4.04 2004-07-28 +------------------------- +- More compatibility with some C++ compilers + + +4.03 2004-06-18 +------------------------- +- "Benchmark" command was added. It measures compressing + and decompressing speed and shows rating values. + Also it checks hardware errors. + + +4.02 2004-06-10 +------------------------- +- C++ LZMA Encoder/Decoder code now is more portable + and it can be compiled by GCC on Linux. + + +4.01 2004-02-15 +------------------------- +- Some detection of data corruption was enabled. + LzmaDecode.c / RangeDecoderReadByte + ..... + { + rd->ExtraBytes = 1; + return 0xFF; + } + + +4.00 2004-02-13 +------------------------- +- Original version of LZMA SDK + + + +HISTORY of the LZMA +------------------- + 2001-2008: Improvements to LZMA compressing/decompressing code, + keeping compatibility with original LZMA format + 1996-2001: Development of LZMA compression format + + Some milestones: + + 2001-08-30: LZMA compression was added to 7-Zip + 1999-01-02: First version of 7-Zip was released + + +End of document diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/lzma.txt b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/lzma.txt new file mode 100644 index 0000000000..d4f4af929a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/lzma.txt @@ -0,0 +1,594 @@ +LZMA SDK 4.65 +------------- + +LZMA SDK provides the documentation, samples, header files, libraries, +and tools you need to develop applications that use LZMA compression. + +LZMA is default and general compression method of 7z format +in 7-Zip compression program (www.7-zip.org). LZMA provides high +compression ratio and very fast decompression. + +LZMA is an improved version of famous LZ77 compression algorithm. +It was improved in way of maximum increasing of compression ratio, +keeping high decompression speed and low memory requirements for +decompressing. + + + +LICENSE +------- + +LZMA SDK is written and placed in the public domain by Igor Pavlov. + + +LZMA SDK Contents +----------------- + +LZMA SDK includes: + + - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing + - Compiled file->file LZMA compressing/decompressing program for Windows system + + +UNIX/Linux version +------------------ +To compile C++ version of file->file LZMA encoding, go to directory +C++/7zip/Compress/LZMA_Alone +and call make to recompile it: + make -f makefile.gcc clean all + +In some UNIX/Linux versions you must compile LZMA with static libraries. +To compile with static libraries, you can use +LIB = -lm -static + + +Files +--------------------- +lzma.txt - LZMA SDK description (this file) +7zFormat.txt - 7z Format description +7zC.txt - 7z ANSI-C Decoder description +methods.txt - Compression method IDs for .7z +lzma.exe - Compiled file->file LZMA encoder/decoder for Windows +history.txt - history of the LZMA SDK + + +Source code structure +--------------------- + +C/ - C files + 7zCrc*.* - CRC code + Alloc.* - Memory allocation functions + Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code + LzFind.* - Match finder for LZ (LZMA) encoders + LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding + LzHash.h - Additional file for LZ match finder + LzmaDec.* - LZMA decoding + LzmaEnc.* - LZMA encoding + LzmaLib.* - LZMA Library for DLL calling + Types.h - Basic types for another .c files + Threads.* - The code for multithreading. + + LzmaLib - LZMA Library (.DLL for Windows) + + LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). + + Archive - files related to archiving + 7z - 7z ANSI-C Decoder + +CPP/ -- CPP files + + Common - common files for C++ projects + Windows - common files for Windows related code + + 7zip - files related to 7-Zip Project + + Common - common files for 7-Zip + + Compress - files related to compression/decompression + + Copy - Copy coder + RangeCoder - Range Coder (special code of compression/decompression) + LZMA - LZMA compression/decompression on C++ + LZMA_Alone - file->file LZMA compression/decompression + Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code + + Archive - files related to archiving + + Common - common files for archive handling + 7z - 7z C++ Encoder/Decoder + + Bundles - Modules that are bundles of other modules + + Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 + Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 + Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. + + UI - User Interface files + + Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll + Common - Common UI files + Console - Code for console archiver + + + +CS/ - C# files + 7zip + Common - some common files for 7-Zip + Compress - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + LzmaAlone - file->file LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + +Java/ - Java files + SevenZip + Compression - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + + +C/C++ source code of LZMA SDK is part of 7-Zip project. +7-Zip source code can be downloaded from 7-Zip's SourceForge page: + + http://sourceforge.net/projects/sevenzip/ + + + +LZMA features +------------- + - Variable dictionary size (up to 1 GB) + - Estimated compressing speed: about 2 MB/s on 2 GHz CPU + - Estimated decompressing speed: + - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 + - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC + - Small memory requirements for decompressing (16 KB + DictionarySize) + - Small code size for decompressing: 5-8 KB + +LZMA decoder uses only integer operations and can be +implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). + +Some critical operations that affect the speed of LZMA decompression: + 1) 32*16 bit integer multiply + 2) Misspredicted branches (penalty mostly depends from pipeline length) + 3) 32-bit shift and arithmetic operations + +The speed of LZMA decompressing mostly depends from CPU speed. +Memory speed has no big meaning. But if your CPU has small data cache, +overall weight of memory speed will slightly increase. + + +How To Use +---------- + +Using LZMA encoder/decoder executable +-------------------------------------- + +Usage: LZMA inputFile outputFile [...] + + e: encode file + + d: decode file + + b: Benchmark. There are two tests: compressing and decompressing + with LZMA method. Benchmark shows rating in MIPS (million + instructions per second). Rating value is calculated from + measured speed and it is normalized with Intel's Core 2 results. + Also Benchmark checks possible hardware errors (RAM + errors in most cases). Benchmark uses these settings: + (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. + Also you can change the number of iterations. Example for 30 iterations: + LZMA b 30 + Default number of iterations is 10. + + + + + -a{N}: set compression mode 0 = fast, 1 = normal + default: 1 (normal) + + d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) + The maximum value for dictionary size is 1 GB = 2^30 bytes. + Dictionary size is calculated as DictionarySize = 2^N bytes. + For decompressing file compressed by LZMA method with dictionary + size D = 2^N you need about D bytes of memory (RAM). + + -fb{N}: set number of fast bytes - [5, 273], default: 128 + Usually big number gives a little bit better compression ratio + and slower compression process. + + -lc{N}: set number of literal context bits - [0, 8], default: 3 + Sometimes lc=4 gives gain for big files. + + -lp{N}: set number of literal pos bits - [0, 4], default: 0 + lp switch is intended for periodical data when period is + equal 2^N. For example, for 32-bit (4 bytes) + periodical data you can use lp=2. Often it's better to set lc0, + if you change lp switch. + + -pb{N}: set number of pos bits - [0, 4], default: 2 + pb switch is intended for periodical data + when period is equal 2^N. + + -mf{MF_ID}: set Match Finder. Default: bt4. + Algorithms from hc* group doesn't provide good compression + ratio, but they often works pretty fast in combination with + fast mode (-a0). + + Memory requirements depend from dictionary size + (parameter "d" in table below). + + MF_ID Memory Description + + bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. + bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. + bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. + hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. + + -eos: write End Of Stream marker. By default LZMA doesn't write + eos marker, since LZMA decoder knows uncompressed size + stored in .lzma file header. + + -si: Read data from stdin (it will write End Of Stream marker). + -so: Write data to stdout + + +Examples: + +1) LZMA e file.bin file.lzma -d16 -lc0 + +compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) +and 0 literal context bits. -lc0 allows to reduce memory requirements +for decompression. + + +2) LZMA e file.bin file.lzma -lc0 -lp2 + +compresses file.bin to file.lzma with settings suitable +for 32-bit periodical data (for example, ARM or MIPS code). + +3) LZMA d file.lzma file.bin + +decompresses file.lzma to file.bin. + + +Compression ratio hints +----------------------- + +Recommendations +--------------- + +To increase the compression ratio for LZMA compressing it's desirable +to have aligned data (if it's possible) and also it's desirable to locate +data in such order, where code is grouped in one place and data is +grouped in other place (it's better than such mixing: code, data, code, +data, ...). + + +Filters +------- +You can increase the compression ratio for some data types, using +special filters before compressing. For example, it's possible to +increase the compression ratio on 5-10% for code for those CPU ISAs: +x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. + +You can find C source code of such filters in C/Bra*.* files + +You can check the compression ratio gain of these filters with such +7-Zip commands (example for ARM code): +No filter: + 7z a a1.7z a.bin -m0=lzma + +With filter for little-endian ARM code: + 7z a a2.7z a.bin -m0=arm -m1=lzma + +It works in such manner: +Compressing = Filter_encoding + LZMA_encoding +Decompressing = LZMA_decoding + Filter_decoding + +Compressing and decompressing speed of such filters is very high, +so it will not increase decompressing time too much. +Moreover, it reduces decompression time for LZMA_decoding, +since compression ratio with filtering is higher. + +These filters convert CALL (calling procedure) instructions +from relative offsets to absolute addresses, so such data becomes more +compressible. + +For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. + + +LZMA compressed file format +--------------------------- +Offset Size Description + 0 1 Special LZMA properties (lc,lp, pb in encoded form) + 1 4 Dictionary size (little endian) + 5 8 Uncompressed size (little endian). -1 means unknown size + 13 Compressed data + + +ANSI-C LZMA Decoder +~~~~~~~~~~~~~~~~~~~ + +Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. +If you want to use old interfaces you can download previous version of LZMA SDK +from sourceforge.net site. + +To use ANSI-C LZMA Decoder you need the following files: +1) LzmaDec.h + LzmaDec.c + Types.h +LzmaUtil/LzmaUtil.c is example application that uses these files. + + +Memory requirements for LZMA decoding +------------------------------------- + +Stack usage of LZMA decoding function for local variables is not +larger than 200-400 bytes. + +LZMA Decoder uses dictionary buffer and internal state structure. +Internal state structure consumes + state_size = (4 + (1.5 << (lc + lp))) KB +by default (lc=3, lp=0), state_size = 16 KB. + + +How To decompress data +---------------------- + +LZMA Decoder (ANSI-C version) now supports 2 interfaces: +1) Single-call Decompressing +2) Multi-call State Decompressing (zlib-like interface) + +You must use external allocator: +Example: +void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } +void SzFree(void *p, void *address) { p = p; free(address); } +ISzAlloc alloc = { SzAlloc, SzFree }; + +You can use p = p; operator to disable compiler warnings. + + +Single-call Decompressing +------------------------- +When to use: RAM->RAM decompressing +Compile files: LzmaDec.h + LzmaDec.c + Types.h +Compile defines: no defines +Memory Requirements: + - Input buffer: compressed size + - Output buffer: uncompressed size + - LZMA Internal Structures: state_size (16 KB for default settings) + +Interface: + int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size + propData - LZMA properties (5 bytes) + propSize - size of propData buffer (5 bytes) + finishMode - It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + You can use LZMA_FINISH_END, when you know that + current output buffer covers last bytes of stream. + alloc - Memory allocator. + + Out: + destLen - processed output size + srcLen - processed input size + + Output: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + If LZMA decoder sees end_marker before reaching output limit, it returns OK result, + and output value of destLen will be less than output buffer size limit. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + + +Multi-call State Decompressing (zlib-like interface) +---------------------------------------------------- + +When to use: file->file decompressing +Compile files: LzmaDec.h + LzmaDec.c + Types.h + +Memory Requirements: + - Buffer for input stream: any size (for example, 16 KB) + - Buffer for output stream: any size (for example, 16 KB) + - LZMA Internal Structures: state_size (16 KB for default settings) + - LZMA dictionary (dictionary size is encoded in LZMA properties header) + +1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: + unsigned char header[LZMA_PROPS_SIZE + 8]; + ReadFile(inFile, header, sizeof(header) + +2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties + + CLzmaDec state; + LzmaDec_Constr(&state); + res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); + if (res != SZ_OK) + return res; + +3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop + + LzmaDec_Init(&state); + for (;;) + { + ... + int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); + ... + } + + +4) Free all allocated structures + LzmaDec_Free(&state, &g_Alloc); + +For full code example, look at C/LzmaUtil/LzmaUtil.c code. + + +How To compress data +-------------------- + +Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + +LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h + +Memory Requirements: + - (dictSize * 11.5 + 6 MB) + state_size + +Lzma Encoder can use two memory allocators: +1) alloc - for small arrays. +2) allocBig - for big arrays. + +For example, you can use Large RAM Pages (2 MB) in allocBig allocator for +better compression speed. Note that Windows has bad implementation for +Large RAM Pages. +It's OK to use same allocator for alloc and allocBig. + + +Single-call Compression with callbacks +-------------------------------------- + +Check C/LzmaUtil/LzmaUtil.c as example, + +When to use: file->file decompressing + +1) you must implement callback structures for interfaces: +ISeqInStream +ISeqOutStream +ICompressProgress +ISzAlloc + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + + CFileSeqInStream inStream; + CFileSeqOutStream outStream; + + inStream.funcTable.Read = MyRead; + inStream.file = inFile; + outStream.funcTable.Write = MyWrite; + outStream.file = outFile; + + +2) Create CLzmaEncHandle object; + + CLzmaEncHandle enc; + + enc = LzmaEnc_Create(&g_Alloc); + if (enc == 0) + return SZ_ERROR_MEM; + + +3) initialize CLzmaEncProps properties; + + LzmaEncProps_Init(&props); + + Then you can change some properties in that structure. + +4) Send LZMA properties to LZMA Encoder + + res = LzmaEnc_SetProps(enc, &props); + +5) Write encoded properties to header + + Byte header[LZMA_PROPS_SIZE + 8]; + size_t headerSize = LZMA_PROPS_SIZE; + UInt64 fileSize; + int i; + + res = LzmaEnc_WriteProperties(enc, header, &headerSize); + fileSize = MyGetFileLength(inFile); + for (i = 0; i < 8; i++) + header[headerSize++] = (Byte)(fileSize >> (8 * i)); + MyWriteFileAndCheck(outFile, header, headerSize) + +6) Call encoding function: + res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, + NULL, &g_Alloc, &g_Alloc); + +7) Destroy LZMA Encoder Object + LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); + + +If callback function return some error code, LzmaEnc_Encode also returns that code. + + +Single-call RAM->RAM Compression +-------------------------------- + +Single-call RAM->RAM Compression is similar to Compression with callbacks, +but you provide pointers to buffers instead of pointers to stream callbacks: + +HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) + + + +LZMA Defines +------------ + +_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. + +_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for + some structures will be doubled in that case. + +_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. + +_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. + + +C++ LZMA Encoder/Decoder +~~~~~~~~~~~~~~~~~~~~~~~~ +C++ LZMA code use COM-like interfaces. So if you want to use it, +you can study basics of COM/OLE. +C++ LZMA code is just wrapper over ANSI-C code. + + +C++ Notes +~~~~~~~~~~~~~~~~~~~~~~~~ +If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), +you must check that you correctly work with "new" operator. +7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. +So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: +operator new(size_t size) +{ + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} +If you use MSCV that throws exception for "new" operator, you can compile without +"NewHandler.cpp". So standard exception will be used. Actually some code of +7-Zip catches any exception in internal code and converts it to HRESULT code. +So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/UefiLzma.h b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/UefiLzma.h new file mode 100644 index 0000000000..863b3ef66b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/UefiLzma.h @@ -0,0 +1,47 @@ +/** @file + LZMA UEFI header file + + Allows LZMA code to build under UEFI (edk2) build environment + + Copyright (c) 2009, Intel 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 __UEFILZMA_H__ +#define __UEFILZMA_H__ + +#include +#include + +#ifdef _WIN32 +#undef _WIN32 +#endif + +#ifndef _SIZE_T_DEFINED +#if !defined(_WIN64) || defined(__GNUC__) +typedef unsigned int size_t; +#endif +#endif + +#ifdef _WIN64 +#undef _WIN64 +#endif + +#ifndef _PTRDIFF_T_DEFINED +typedef int ptrdiff_t; +#endif + +#define memcpy CopyMem +#define memmove CopyMem + +#define _LZMA_SIZE_OPT + +#endif // __UEFILZMA_H__ + diff --git a/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c b/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c new file mode 100644 index 0000000000..cfdd2f50d5 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c @@ -0,0 +1,468 @@ +/** @file + Debug Library based on report status code library. + + Note that if the debug message length is larger than the maximum allowable + record length, then the debug message will be ignored directly. + + Copyright (c) 2006 - 2015, Intel 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 + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + If the length of the message string specificed by Format is larger than the maximum allowable + record length, then directly return and not print it. + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param ... Variable argument list whose contents are accessed + based on the format string specified by Format. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + ... + ) +{ + UINT64 Buffer[(EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof (UINT64)) + 1]; + EFI_DEBUG_INFO *DebugInfo; + UINTN TotalSize; + UINTN DestBufferSize; + VA_LIST VaListMarker; + BASE_LIST BaseListMarker; + CHAR8 *FormatString; + BOOLEAN Long; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver Debug Level value and global debug level + // + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { + return; + } + + // + // Compute the total size of the record. + // Note that the passing-in format string and variable parameters will be constructed to + // the following layout: + // + // Buffer->|------------------------| + // | Padding | 4 bytes + // DebugInfo->|------------------------| + // | EFI_DEBUG_INFO | sizeof(EFI_DEBUG_INFO) + // BaseListMarker->|------------------------| + // | ... | + // | variable arguments | 12 * sizeof (UINT64) + // | ... | + // |------------------------| + // | Format String | + // |------------------------|<- (UINT8 *)Buffer + sizeof(Buffer) + // + TotalSize = 4 + sizeof (EFI_DEBUG_INFO) + 12 * sizeof (UINT64) + AsciiStrSize (Format); + + // + // If the TotalSize is larger than the maximum record size, then return + // + if (TotalSize > sizeof (Buffer)) { + return; + } + + // + // Fill in EFI_DEBUG_INFO + // + // Here we skip the first 4 bytes of Buffer, because we must ensure BaseListMarker is + // 64-bit aligned, otherwise retrieving 64-bit parameter from BaseListMarker will cause + // exception on IPF. Buffer starts at 64-bit aligned address, so skipping 4 types (sizeof(EFI_DEBUG_INFO)) + // just makes address of BaseListMarker, which follows DebugInfo, 64-bit aligned. + // + DebugInfo = (EFI_DEBUG_INFO *)(Buffer) + 1; + DebugInfo->ErrorLevel = (UINT32)ErrorLevel; + BaseListMarker = (BASE_LIST)(DebugInfo + 1); + FormatString = (CHAR8 *)((UINT64 *)(DebugInfo + 1) + 12); + + // + // Copy the Format string into the record + // + // According to the content structure of Buffer shown above, the size of + // the FormatString buffer is the size of Buffer minus the Padding + // (4 bytes), minus the size of EFI_DEBUG_INFO, minus the size of + // variable arguments (12 * sizeof (UINT64)). + // + DestBufferSize = sizeof (Buffer) - 4 - sizeof (EFI_DEBUG_INFO) - 12 * sizeof (UINT64); + AsciiStrCpyS (FormatString, DestBufferSize / sizeof (CHAR8), Format); + + // + // The first 12 * sizeof (UINT64) bytes following EFI_DEBUG_INFO are for variable arguments + // of format in DEBUG string, which is followed by the DEBUG format string. + // Here we will process the variable arguments and pack them in this area. + // + VA_START (VaListMarker, Format); + for (; *Format != '\0'; Format++) { + // + // Only format with prefix % is processed. + // + if (*Format != '%') { + continue; + } + Long = FALSE; + // + // Parse Flags and Width + // + for (Format++; TRUE; Format++) { + if (*Format == '.' || *Format == '-' || *Format == '+' || *Format == ' ') { + // + // These characters in format field are omitted. + // + continue; + } + if (*Format >= '0' && *Format <= '9') { + // + // These characters in format field are omitted. + // + continue; + } + if (*Format == 'L' || *Format == 'l') { + // + // 'L" or "l" in format field means the number being printed is a UINT64 + // + Long = TRUE; + continue; + } + if (*Format == '*') { + // + // '*' in format field means the precision of the field is specified by + // a UINTN argument in the argument list. + // + BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN); + continue; + } + if (*Format == '\0') { + // + // Make no output if Format string terminates unexpectedly when + // looking up for flag, width, precision and type. + // + Format--; + } + // + // When valid argument type detected or format string terminates unexpectedly, + // the inner loop is done. + // + break; + } + + // + // Pack variable arguments into the storage area following EFI_DEBUG_INFO. + // + if ((*Format == 'p') && (sizeof (VOID *) > 4)) { + Long = TRUE; + } + if (*Format == 'p' || *Format == 'X' || *Format == 'x' || *Format == 'd' || *Format == 'u') { + if (Long) { + BASE_ARG (BaseListMarker, INT64) = VA_ARG (VaListMarker, INT64); + } else { + BASE_ARG (BaseListMarker, int) = VA_ARG (VaListMarker, int); + } + } else if (*Format == 's' || *Format == 'S' || *Format == 'a' || *Format == 'g' || *Format == 't') { + BASE_ARG (BaseListMarker, VOID *) = VA_ARG (VaListMarker, VOID *); + } else if (*Format == 'c') { + BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN); + } else if (*Format == 'r') { + BASE_ARG (BaseListMarker, RETURN_STATUS) = VA_ARG (VaListMarker, RETURN_STATUS); + } + + // + // If the converted BASE_LIST is larger than the 12 * sizeof (UINT64) allocated bytes, then ASSERT() + // This indicates that the DEBUG() macro is passing in more argument than can be handled by + // the EFI_DEBUG_INFO record + // + ASSERT ((CHAR8 *)BaseListMarker <= FormatString); + + // + // If the converted BASE_LIST is larger than the 12 * sizeof (UINT64) allocated bytes, then return + // + if ((CHAR8 *)BaseListMarker > FormatString) { + VA_END (VaListMarker); + return; + } + } + VA_END (VaListMarker); + + // + // Send the DebugInfo record + // + REPORT_STATUS_CODE_EX ( + EFI_DEBUG_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_DC_UNSPECIFIED), + 0, + NULL, + &gEfiStatusCodeDataTypeDebugGuid, + DebugInfo, + TotalSize + ); +} + +/** + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form "ASSERT (): \n" + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recursion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of "(NULL) Filename" is printed. + If Description is NULL, then a string of "(NULL) Description" is printed. + + @param FileName Pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description Pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof(UINT64)]; + EFI_DEBUG_ASSERT_DATA *AssertData; + UINTN HeaderSize; + UINTN TotalSize; + CHAR8 *Temp; + UINTN FileNameSize; + UINTN DescriptionSize; + + // + // Get string size + // + HeaderSize = sizeof (EFI_DEBUG_ASSERT_DATA); + FileNameSize = AsciiStrSize (FileName); + DescriptionSize = AsciiStrSize (Description); + + // + // Make sure it will all fit in the passed in buffer. + // + if (HeaderSize + FileNameSize + DescriptionSize > sizeof (Buffer)) { + // + // FileName + Description is too long to be filled into buffer. + // + if (HeaderSize + FileNameSize < sizeof (Buffer)) { + // + // Description has enough buffer to be truncated. + // + DescriptionSize = sizeof (Buffer) - HeaderSize - FileNameSize; + } else { + // + // FileName is too long to be filled into buffer. + // FileName will be truncated. Reserved one byte for Description NULL terminator. + // + DescriptionSize = 1; + FileNameSize = sizeof (Buffer) - HeaderSize - DescriptionSize; + } + } + + // + // Fill in EFI_DEBUG_ASSERT_DATA + // + AssertData = (EFI_DEBUG_ASSERT_DATA *)Buffer; + AssertData->LineNumber = (UINT32)LineNumber; + TotalSize = sizeof (EFI_DEBUG_ASSERT_DATA); + + // + // Copy Ascii FileName including NULL terminator. + // + Temp = CopyMem (AssertData + 1, FileName, FileNameSize); + Temp[FileNameSize - 1] = 0; + TotalSize += FileNameSize; + + // + // Copy Ascii Description include NULL terminator. + // + Temp = CopyMem (Temp + FileNameSize, Description, DescriptionSize); + Temp[DescriptionSize - 1] = 0; + TotalSize += DescriptionSize; + + REPORT_STATUS_CODE_EX ( + (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE), + 0, + NULL, + NULL, + AssertData, + TotalSize + ); + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings + // + if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} + + +/** + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer Pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (Buffer != NULL); + + return SetMem (Buffer, Length, PcdGet8 (PcdDebugClearMemoryValue)); +} + + +/** + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + + +/** + Returns TRUE if DEBUG() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + + +/** + Returns TRUE if DEBUG_CODE() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} + +/** + Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel. + + This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel. + + @retval TRUE Current ErrorLevel is supported. + @retval FALSE Current ErrorLevel is not supported. + +**/ +BOOLEAN +EFIAPI +DebugPrintLevelEnabled ( + IN CONST UINTN ErrorLevel + ) +{ + return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0); +} diff --git a/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf b/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf new file mode 100644 index 0000000000..55446672d7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf @@ -0,0 +1,54 @@ +## @file +# Debug Library based on report status code library +# +# Debug Library for PEIMs and DXE drivers that sends debug messages to ReportStatusCode +# Copyright (c) 2006 - 2015, Intel 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 = PeiDxeDebugLibReportStatusCode + MODULE_UNI_FILE = PeiDxeDebugLibReportStatusCode.uni + FILE_GUID = bda39d3a-451b-4350-8266-81ab10fa0523 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER SMM_CORE PEIM SEC PEI_CORE UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DebugLib.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PcdLib + ReportStatusCodeLib + BaseMemoryLib + BaseLib + DebugPrintErrorLevelLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + +[Guids] + gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## GUID + diff --git a/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.uni b/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.uni new file mode 100644 index 0000000000..fe2abee431 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.c b/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.c new file mode 100644 index 0000000000..fc729a899c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.c @@ -0,0 +1,50 @@ +/** @file + This Library uses Framework RecoveryModule PPI to do system recovery. + + This library instance is no longer used and module using this library + class should update to directly locate EFI_PEI_RECOVERY_MODULE_PPI defined + in PI 1.2 specification. + +Copyright (c) 2006 - 2009, Intel 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 + +/** + Calling this function causes the system do recovery. + + @retval EFI_SUCESS Sucess to do recovery. + @retval Others Fail to do recovery. +**/ +EFI_STATUS +EFIAPI +PeiRecoverFirmware ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; + + Status = PeiServicesLocatePpi ( + &gEfiPeiRecoveryModulePpiGuid, + 0, + NULL, + (VOID **)&PeiRecovery + ); + ASSERT_EFI_ERROR (Status); + + return PeiRecovery->LoadRecoveryCapsule ((EFI_PEI_SERVICES **) GetPeiServicesTablePointer(), PeiRecovery); +} + diff --git a/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf b/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf new file mode 100644 index 0000000000..9bd321e178 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf @@ -0,0 +1,50 @@ +## @file +# PEIM Recovery Library supports system recovery boot. +# +# This library instance is no longer used and module using this library +# class should update to directly locate EFI_PEI_RECOVERY_MODULE_PPI defined +# in PI 1.2 specification. +# +# 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 +# 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 = PeiRecoveryLib + MODULE_UNI_FILE = PeiRecoveryLib.uni + FILE_GUID = C0227547-0811-4cbb-ABEA-DECD22829122 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = RecoveryLib|PEIM + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + PeiRecoveryLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + PeiServicesTablePointerLib + DebugLib + +[Ppis] + gEfiPeiRecoveryModulePpiGuid ## CONSUMES + + \ No newline at end of file diff --git a/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.uni b/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.uni new file mode 100644 index 0000000000..11891e58e0 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.c b/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.c new file mode 100644 index 0000000000..d16e3cac24 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.c @@ -0,0 +1,51 @@ +/** @file + This library provides API to invoke the S3 resume vector in the APCI Table in S3 resume mode. + + This library instance is no longer used and module using this library + class should update to directly locate EFI_PEI_S3_RESUME_PPI defined + in PI 1.2 specification. + +Copyright (c) 2006 - 2008, Intel 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 function is responsible for calling the S3 resume vector in the ACPI Tables. + + @retval EFI_SUCESS Success to restore config from S3. + @retval Others Fail to restore config from S3. +**/ +EFI_STATUS +EFIAPI +AcpiS3ResumeOs ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PEI_S3_RESUME_PPI *S3Resume; + + Status = PeiServicesLocatePpi ( + &gEfiPeiS3ResumePpiGuid, + 0, + NULL, + (VOID **)&S3Resume + ); + ASSERT_EFI_ERROR (Status); + + return S3Resume->S3RestoreConfig ((EFI_PEI_SERVICES **) GetPeiServicesTablePointer()); +} + diff --git a/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf b/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf new file mode 100644 index 0000000000..b01e1860f4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf @@ -0,0 +1,49 @@ +## @file +# This library provides API to invoke the S3 resume vector in the ACPI Table in S3 resume mode. +# +# This library instance is no longer used and module using this library +# class should update to directly locate EFI_PEI_S3_RESUME_PPI defined +# in PI 1.2 specification. +# +# 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 +# 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 = PeiS3Lib + MODULE_UNI_FILE = PeiS3Lib.uni + FILE_GUID = EFB7D3A8-DEB9-4bed-B6D6-3B09BEEB835A + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = S3Lib|PEIM + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + PeiS3Lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + PeiServicesTablePointerLib + DebugLib + +[Ppis] + gEfiPeiS3ResumePpiGuid ## CONSUMES + diff --git a/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.uni b/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.uni new file mode 100644 index 0000000000..dceb0011c9 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c new file mode 100644 index 0000000000..9fb3b23282 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c @@ -0,0 +1,187 @@ +/** @file + This file include all platform action which can be customized by IBV/OEM. + +Copyright (c) 2004 - 2008, Intel 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 "BdsPlatform.h" + +// +// BDS Platform Functions +// +/** + Platform Bds init. Include the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformBdsInit ( + VOID + ) +{ +} + +/** + Connect the predefined platform default console device. Always try to find + and enable the vga device if have. + + @param PlatformConsole Predefined 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. + @return Return the status of BdsLibConnectAllDefaultConsoles () + +**/ +EFI_STATUS +PlatformBdsConnectConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole + ) +{ + return EFI_SUCCESS; +} + +/** + Connect with predefined platform connect sequence, + the OEM/IBV can customize with their own connect sequence. +**/ +VOID +PlatformBdsConnectSequence ( + VOID + ) +{ +} + +/** + 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. + +**/ +VOID +PlatformBdsGetDriverOption ( + IN OUT LIST_ENTRY *BdsDriverLists + ) +{ +} + +/** + Perform the platform diagnostic, such like test memory. OEM/IBV also + can customize this function 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() + +**/ +VOID +PlatformBdsDiagnostics ( + IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, + IN BOOLEAN QuietBoot, + IN BASEM_MEMORY_TEST BaseMemoryTest + ) +{ +} + +/** + The function will execute 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() + +**/ +VOID +EFIAPI +PlatformBdsPolicyBehavior ( + IN LIST_ENTRY *DriverOptionList, + IN LIST_ENTRY *BootOptionList, + IN PROCESS_CAPSULES ProcessCapsules, + IN BASEM_MEMORY_TEST BaseMemoryTest + ) +{ +} + +/** + 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 also a platform implementation and can be customized by IBV/OEM. + + @param Option Pointer to Boot Option that succeeded to boot. + +**/ +VOID +EFIAPI +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ) +{ +} + +/** + 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. + +**/ +VOID +EFIAPI +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ) +{ +} + +/** + This function locks platform flash that is not allowed to be updated during normal boot path. + The flash layout is platform specific. +**/ +VOID +EFIAPI +PlatformBdsLockNonUpdatableFlash ( + VOID + ) +{ + return ; +} + + +/** + 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; +} diff --git a/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h new file mode 100644 index 0000000000..38ea72ee6c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h @@ -0,0 +1,28 @@ +/** @file + Head file for BDS Platform specific code + +Copyright (c) 2004 - 2008, Intel 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 _BDS_PLATFORM_H_ +#define _BDS_PLATFORM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // _BDS_PLATFORM_H diff --git a/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLib.uni b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLib.uni new file mode 100644 index 0000000000..3ec1a92f63 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLib.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf new file mode 100644 index 0000000000..37c98cff00 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf @@ -0,0 +1,47 @@ +## @file +# NULL implementation for PlatformBdsLib library class interfaces. +# +# 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 +# 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 = PlatformBdsLib + MODULE_UNI_FILE = PlatformBdsLib.uni + FILE_GUID = 143B5044-7C1B-4904-9778-EA16F1F3D554 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + BdsPlatform.c + PlatformData.c + BdsPlatform.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + PcdLib + GenericBdsLib \ No newline at end of file diff --git a/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformData.c b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformData.c new file mode 100644 index 0000000000..131efab4d9 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformData.c @@ -0,0 +1,21 @@ +/** @file + Defined the platform specific device path which will be used by + platform Bbd to perform the platform policy connect. + +Copyright (c) 2004 - 2008, Intel 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 "BdsPlatform.h" + +/// +/// Predefined platform default time out value +/// +UINT16 gPlatformBootTimeOutDefault = 10; diff --git a/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLib.c b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLib.c new file mode 100644 index 0000000000..c49dacaeb1 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLib.c @@ -0,0 +1,493 @@ +/** @file + API implementation for instance of Report Status Code Library. + + Copyright (c) 2006 - 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 "ReportStatusCodeLibInternal.h" + +/** + Converts a status code to an 8-bit POST code value. + + Converts the status code specified by CodeType and Value to an 8-bit POST code + and returns the 8-bit POST code in PostCode. If CodeType is an + EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode + are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits + 24..26 of Value., and TRUE is returned. Otherwise, FALSE is returned. + + If PostCode is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param PostCode A pointer to the 8-bit POST code value to return. + + @retval TRUE The status code specified by CodeType and Value was converted + to an 8-bit POST code and returned in PostCode. + @retval FALSE The status code specified by CodeType and Value could not be + converted to an 8-bit POST code value. + +**/ +BOOLEAN +EFIAPI +CodeTypeToPostCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + OUT UINT8 *PostCode + ) +{ + // + // If PostCode is NULL, then ASSERT() + // + ASSERT (PostCode != NULL); + + // + // Convert Value to an 8 bit post code + // + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || + ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ) { + *PostCode = (UINT8) ((((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5) | + (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f)); + return TRUE; + } + return FALSE; +} + + +/** + Extracts ASSERT() information from a status code structure. + + Converts the status code specified by CodeType, Value, and Data to the ASSERT() + arguments specified by Filename, Description, and LineNumber. If CodeType is + an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and + Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract + Filename, Description, and LineNumber from the optional data area of the + status code buffer specified by Data. The optional data area of Data contains + a Null-terminated ASCII string for the FileName, followed by a Null-terminated + ASCII string for the Description, followed by a 32-bit LineNumber. If the + ASSERT() information could be extracted from Data, then return TRUE. + Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If Filename is NULL, then ASSERT(). + If Description is NULL, then ASSERT(). + If LineNumber is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param Data Pointer to status code data buffer. + @param Filename Pointer to the source file name that generated the ASSERT(). + @param Description Pointer to the description of the ASSERT(). + @param LineNumber Pointer to source line number that generated the ASSERT(). + + @retval TRUE The status code specified by CodeType, Value, and Data was + converted ASSERT() arguments specified by Filename, Description, + and LineNumber. + @retval FALSE The status code specified by CodeType, Value, and Data could + not be converted to ASSERT() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractAssertInfo ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST EFI_STATUS_CODE_DATA *Data, + OUT CHAR8 **Filename, + OUT CHAR8 **Description, + OUT UINT32 *LineNumber + ) +{ + EFI_DEBUG_ASSERT_DATA *AssertData; + + ASSERT (Data != NULL); + ASSERT (Filename != NULL); + ASSERT (Description != NULL); + ASSERT (LineNumber != NULL); + + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && + ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) && + ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) { + AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1); + *Filename = (CHAR8 *)(AssertData + 1); + *Description = *Filename + AsciiStrLen (*Filename) + 1; + *LineNumber = AssertData->LineNumber; + return TRUE; + } + return FALSE; +} + + +/** + Extracts DEBUG() information from a status code structure. + + Converts the status code specified by Data to the DEBUG() arguments specified + by ErrorLevel, Marker, and Format. If type GUID in Data is + EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and + Format from the optional data area of the status code buffer specified by Data. + The optional data area of Data contains a 32-bit ErrorLevel followed by Marker + which is 12 UINTN parameters, followed by a Null-terminated ASCII string for + the Format. If the DEBUG() information could be extracted from Data, then + return TRUE. Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If ErrorLevel is NULL, then ASSERT(). + If Marker is NULL, then ASSERT(). + If Format is NULL, then ASSERT(). + + @param Data Pointer to status code data buffer. + @param ErrorLevel Pointer to error level mask for a debug message. + @param Marker Pointer to the variable argument list associated with Format. + @param Format Pointer to a Null-terminated ASCII format string of a + debug message. + + @retval TRUE The status code specified by Data was converted DEBUG() arguments + specified by ErrorLevel, Marker, and Format. + @retval FALSE The status code specified by Data could not be converted to + DEBUG() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractDebugInfo ( + IN CONST EFI_STATUS_CODE_DATA *Data, + OUT UINT32 *ErrorLevel, + OUT BASE_LIST *Marker, + OUT CHAR8 **Format + ) +{ + EFI_DEBUG_INFO *DebugInfo; + + ASSERT (Data != NULL); + ASSERT (ErrorLevel != NULL); + ASSERT (Marker != NULL); + ASSERT (Format != NULL); + + // + // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE + // + if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) { + return FALSE; + } + + // + // Retrieve the debug information from the status code record + // + DebugInfo = (EFI_DEBUG_INFO *)(Data + 1); + + *ErrorLevel = DebugInfo->ErrorLevel; + + // + // The first 12 * sizeof (UINT64) bytes following EFI_DEBUG_INFO are for variable arguments + // of format in DEBUG string. Its address is returned in Marker and has to be 64-bit aligned. + // It must be noticed that EFI_DEBUG_INFO follows EFI_STATUS_CODE_DATA, whose size is + // 20 bytes. The size of EFI_DEBUG_INFO is 4 bytes, so we can ensure that Marker + // returned is 64-bit aligned. + // 64-bit aligned is a must, otherwise retrieving 64-bit parameter from BASE_LIST will + // cause unalignment exception. + // + *Marker = (BASE_LIST) (DebugInfo + 1); + *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12); + + return TRUE; +} + + +/** + Reports a status code. + + Reports the status code specified by the parameters Type and Value. Status + code also require an instance, caller ID, and extended data. This function + passed in a zero instance, NULL extended data, and a caller ID of + gEfiCallerIdGuid, which is the GUID for the module. + + ReportStatusCode()must actively prevent recusrsion. If ReportStatusCode() + is called while processing another any other Report Status Code Library function, + then ReportStatusCode() must return immediately. + + @param Type Status code type. + @param Value Status code value. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_DEVICE_ERROR There status code could not be reported due to a + device error. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value + ) +{ + return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL); +} + + +/** + Reports a status code with a Device Path Protocol as the extended data. + + Allocates and fills in the extended data section of a status code with the + Device Path Protocol specified by DevicePath. This function is responsible + for allocating a buffer large enough for the standard header and the device + path. The standard header is filled in with a GUID of + gEfiStatusCodeSpecificDataGuid. The status code is reported with a zero + instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithDevicePath()must actively prevent recursion. If + ReportStatusCodeWithDevicePath() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithDevicePath() + must return EFI_DEVICE_ERROR immediately. + + If DevicePath is NULL, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param DevicePath Pointer to the Device Path Protocol to be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by DevicePath. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithDevicePath ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ASSERT (DevicePath != NULL); + return ReportStatusCodeWithExtendedData ( + Type, + Value, + (VOID *)DevicePath, + GetDevicePathSize (DevicePath) + ); +} + + +/** + Reports a status code with an extended data buffer. + + Allocates and fills in the extended data section of a status code with the + extended data specified by ExtendedData and ExtendedDataSize. ExtendedData + is assumed to be one of the data structures specified in Related Definitions. + These data structure do not have the standard header, so this function is + responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled + in with a GUID of gEfiStatusCodeSpecificDataGuid. The status code is reported + with a zero instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithExtendedData()must actively prevent recursion. If + ReportStatusCodeWithExtendedData() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithExtendedData() + must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL, then ASSERT(). + If ExtendedDataSize is 0, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param ExtendedData Pointer to the extended data buffer to be reported. + @param ExtendedDataSize The size, in bytes, of the extended data buffer to + be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by ExtendedData and ExtendedDataSize. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithExtendedData ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST VOID *ExtendedData, + IN UINTN ExtendedDataSize + ) +{ + ASSERT (ExtendedData != NULL); + ASSERT (ExtendedDataSize != 0); + return ReportStatusCodeEx ( + Type, + Value, + 0, + NULL, + NULL, + ExtendedData, + ExtendedDataSize + ); +} + + +/** + Reports a status code with full parameters. + + The function reports a status code. If ExtendedData is NULL and ExtendedDataSize + is 0, then an extended data buffer is not reported. If ExtendedData is not + NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. + ExtendedData is assumed not have the standard status code header, so this function + is responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled in + with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a + GUID of gEfiStatusCodeSpecificDataGuid is used. The status code is reported with + an instance specified by Instance and a caller ID specified by CallerId. If + CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. + + ReportStatusCodeEx()must actively prevent recursion. If + ReportStatusCodeEx() is called while processing another any + other Report Status Code Library function, then + ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). + If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. If this parameter is NULL, then a caller + ID of gEfiCallerIdGuid is used. + @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. + If this parameter is NULL, then a the status code + standard header is filled in with + gEfiStatusCodeSpecificDataGuid. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate + the extended data section if it was specified. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeEx ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId OPTIONAL, + IN CONST EFI_GUID *ExtendedDataGuid OPTIONAL, + IN CONST VOID *ExtendedData OPTIONAL, + IN UINTN ExtendedDataSize + ) +{ + EFI_STATUS Status; + + ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); + ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); + + if (ExtendedDataSize > EFI_STATUS_CODE_DATA_MAX_SIZE) { + DEBUG ((EFI_D_ERROR, "Status code extended data is too large to be reported!\n")); + return EFI_OUT_OF_RESOURCES; + } + + // + // Fill in the extended data header + // + mStatusCodeData->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA); + mStatusCodeData->Size = (UINT16)ExtendedDataSize; + if (ExtendedDataGuid == NULL) { + ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid; + } + CopyGuid (&mStatusCodeData->Type, ExtendedDataGuid); + + // + // Fill in the extended data buffer + // + if (ExtendedData != NULL) { + CopyMem (mStatusCodeData + 1, ExtendedData, ExtendedDataSize); + } + + // + // Report the status code + // + if (CallerId == NULL) { + CallerId = &gEfiCallerIdGuid; + } + Status = InternalReportStatusCode (Type, Value, Instance, CallerId, mStatusCodeData); + + return Status; +} + + +/** + Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportProgressCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_ERROR_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportErrorCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportDebugCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} diff --git a/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLibInternal.h b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLibInternal.h new file mode 100644 index 0000000000..1f9a0c7e1d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLibInternal.h @@ -0,0 +1,73 @@ +/** @file + Internal Header file of Report Status Code Library for RUNTIME + DXE Phase. + + Copyright (c) 2006 - 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 __REPORT_STATUS_CODE_LIB_INTERNAL__H__ +#define __REPORT_STATUS_CODE_LIB_INTERNAL__H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + + +extern EFI_STATUS_CODE_DATA *mStatusCodeData; + +/** + Internal worker function that reports a status code through the status code service. + + If status code service is not cached, then this function checks if status code service is + available in system. If status code service is not available, then EFI_UNSUPPORTED is + returned. If status code service is present, then it is cached in mReportStatusCode. + Finally this function reports status code through the status code service. + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. This is an optional parameter that may be + NULL. + @param Data Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_UNSUPPORTED Status code service is not available. + @retval EFI_UNSUPPORTED Status code type is not supported. + +**/ +EFI_STATUS +InternalReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf new file mode 100644 index 0000000000..6964e44f34 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf @@ -0,0 +1,73 @@ +## @file +# Framework Report status code library instance which supports logging message in SMM, as well as DXE & runtime phase. +# +# This library instance supports status code report in SMM, as well as DXE & runtime phase. +# In SMM, it logs message via SMM Status Code Protocol. +# Otherwise, it logs message to ReportStatusCode() in framework runtime services table or runtime report status code 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 +# 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 = SmmRuntimeDxeReportStatusCodeLibFramework + MODULE_UNI_FILE = SmmRuntimeDxeReportStatusCodeLibFramework.uni + FILE_GUID = D65D9F72-7BCE-4f73-A673-47AF446A1A31 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ReportStatusCodeLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER + + CONSTRUCTOR = ReportStatusCodeLibConstruct + DESTRUCTOR = ReportStatusCodeLibDestruct +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + ReportStatusCodeLib.c + SmmRuntimeDxeSupport.c + ReportStatusCodeLibInternal.h + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + PcdLib + BaseMemoryLib + BaseLib + DebugLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + DevicePathLib + MemoryAllocationLib + +[Guids] + gEfiStatusCodeSpecificDataGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + + +[Protocols] + gEfiStatusCodeRuntimeProtocolGuid ## SOMETIMES_CONSUMES + gEfiSmmBaseProtocolGuid ## SOMETIMES_CONSUMES + gEfiSmmStatusCodeProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask ## CONSUMES + diff --git a/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.uni b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.uni new file mode 100644 index 0000000000..2268a3c094 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.uni differ diff --git a/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c new file mode 100644 index 0000000000..554be152b3 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c @@ -0,0 +1,335 @@ +/** @file + Library constructor & destructor, event handlers, and other internal worker functions. + + 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 "ReportStatusCodeLibInternal.h" + +EFI_EVENT mVirtualAddressChangeEvent; +EFI_EVENT mExitBootServicesEvent; +EFI_STATUS_CODE_DATA *mStatusCodeData; +BOOLEAN mInSmm; +EFI_SMM_BASE_PROTOCOL *mSmmBase; +EFI_RUNTIME_SERVICES *mInternalRT; +BOOLEAN mHaveExitedBootServices = FALSE; +EFI_REPORT_STATUS_CODE mReportStatusCode = NULL; +EFI_SMM_STATUS_CODE_PROTOCOL *mSmmStatusCodeProtocol; + +/** + Locates and caches SMM Status Code Protocol. + +**/ +VOID +SmmStatusCodeInitialize ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiSmmStatusCodeProtocolGuid, NULL, (VOID **) &mSmmStatusCodeProtocol); + if (EFI_ERROR (Status)) { + mSmmStatusCodeProtocol = NULL; + } +} + +/** + Report status code via SMM Status Code Protocol. + + @param Type Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to classify the entity + as well as an operation. For progress codes, the operation is the current activity. + For error codes, it is the exception. For debug codes, it is not defined at this time. + @param Instance The enumeration of a hardware or software entity within the system. + A system may contain multiple entities that match a class/subclass pairing. + The instance differentiates between them. An instance of 0 indicates that instance information is unavailable, + not meaningful, or not relevant. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to different callers. + @param Data This optional parameter may be used to pass additional data + + @retval EFI_SUCCESS Always return EFI_SUCCESS. + +**/ +EFI_STATUS +SmmStatusCodeReport ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + if (mSmmStatusCodeProtocol != NULL) { + (mSmmStatusCodeProtocol->ReportStatusCode) (mSmmStatusCodeProtocol, Type, Value, Instance, CallerId, Data); + } + return EFI_SUCCESS; +} + +/** + Locate the report status code service. + + In SMM, it tries to retrieve SMM Status Code Protocol. + Otherwise, it first tries to retrieve ReportStatusCode() in Runtime Services Table. + If not found, it then tries to retrieve ReportStatusCode() API of Report Status Code Protocol. + + @return Function pointer to the report status code service. + NULL is returned if no status code service is available. + +**/ +EFI_REPORT_STATUS_CODE +InternalGetReportStatusCode ( + VOID + ) +{ + EFI_STATUS_CODE_PROTOCOL *StatusCodeProtocol; + EFI_STATUS Status; + + if (mInSmm) { + return (EFI_REPORT_STATUS_CODE) SmmStatusCodeReport; + } else if (mInternalRT != NULL && mInternalRT->Hdr.Revision < 0x20000) { + return ((FRAMEWORK_EFI_RUNTIME_SERVICES*)mInternalRT)->ReportStatusCode; + } else if (!mHaveExitedBootServices) { + // + // Check gBS just in case. ReportStatusCode is called before gBS is initialized. + // + if (gBS != NULL) { + Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol); + if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) { + return StatusCodeProtocol->ReportStatusCode; + } + } + } + + return NULL; +} + +/** + Internal worker function that reports a status code through the status code service. + + If status code service is not cached, then this function checks if status code service is + available in system. If status code service is not available, then EFI_UNSUPPORTED is + returned. If status code service is present, then it is cached in mReportStatusCode. + Finally this function reports status code through the status code service. + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. This is an optional parameter that may be + NULL. + @param Data Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_UNSUPPORTED Status code service is not available. + @retval EFI_UNSUPPORTED Status code type is not supported. + +**/ +EFI_STATUS +InternalReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + if ((ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) || + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)) { + // + // If mReportStatusCode is NULL, then check if status code service is available in system. + // + if (mReportStatusCode == NULL) { + mReportStatusCode = InternalGetReportStatusCode (); + if (mReportStatusCode == NULL) { + return EFI_UNSUPPORTED; + } + } + + // + // A status code service is present in system, so pass in all the parameters to the service. + // + return (*mReportStatusCode) (Type, Value, Instance, (EFI_GUID *)CallerId, Data); + } + + return EFI_UNSUPPORTED; +} + +/** + Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context + +**/ +VOID +EFIAPI +ReportStatusCodeLibVirtualAddressChange ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + if (mReportStatusCode != NULL) { + mInternalRT->ConvertPointer (0, (VOID **) &mReportStatusCode); + } + mInternalRT->ConvertPointer (0, (VOID **) &mStatusCodeData); + mInternalRT->ConvertPointer (0, (VOID **) &mInternalRT); +} + +/** + Notification function of EVT_SIGNAL_EXIT_BOOT_SERVICES. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context + +**/ +VOID +EFIAPI +ReportStatusCodeLibExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // If mReportStatusCode is NULL, then see if a Status Code Protocol instance is present + // in the handle database. + // + if (mReportStatusCode == NULL) { + mReportStatusCode = InternalGetReportStatusCode (); + } + + mHaveExitedBootServices = TRUE; +} + +/** + The constructor function of SMM Runtime DXE Report Status Code Lib. + + This function allocates memory for extended status code data, caches + the report status code service, and registers events. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeLibConstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // If in SMM mode, then allocates memory from SMRAM for extended status code data. + // + Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase); + if (!EFI_ERROR (Status)) { + mSmmBase->InSmm (mSmmBase, &mInSmm); + if (mInSmm) { + Status = mSmmBase->SmmAllocatePool ( + mSmmBase, + EfiRuntimeServicesData, + sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, + (VOID **) &mStatusCodeData + ); + ASSERT_EFI_ERROR (Status); + SmmStatusCodeInitialize (); + return EFI_SUCCESS; + } + } + + + // + // If not in SMM mode, then allocate runtime memory for extended status code data. + // + // Library should not use the gRT directly, for it may be converted by other library instance. + // + mInternalRT = gRT; + mInSmm = FALSE; + + mStatusCodeData = AllocateRuntimePool (sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE); + ASSERT (mStatusCodeData != NULL); + // + // Cache the report status code service + // + mReportStatusCode = InternalGetReportStatusCode (); + + // + // Register notify function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ReportStatusCodeLibVirtualAddressChange, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mVirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Register notify function for EVT_SIGNAL_EXIT_BOOT_SERVICES + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ReportStatusCodeLibExitBootServices, + NULL, + &gEfiEventExitBootServicesGuid, + &mExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + The destructor function of SMM Runtime DXE Report Status Code Lib. + + The destructor function frees memory allocated by constructor, and closes related events. + It will ASSERT() if that related 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 always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeLibDestruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (!mInSmm) { + ASSERT (gBS != NULL); + Status = gBS->CloseEvent (mVirtualAddressChangeEvent); + ASSERT_EFI_ERROR (Status); + Status = gBS->CloseEvent (mExitBootServicesEvent); + ASSERT_EFI_ERROR (Status); + + FreePool (mStatusCodeData); + } else { + mSmmBase->SmmFreePool (mSmmBase, mStatusCodeData); + } + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/License.txt b/Core/IntelFrameworkModulePkg/License.txt new file mode 100644 index 0000000000..be68999be6 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/License.txt @@ -0,0 +1,25 @@ +Copyright (c) 2012, Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c new file mode 100644 index 0000000000..177a73bc78 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c @@ -0,0 +1,643 @@ +/** @file + This is an implementation of the ACPI S3 Save protocol. This is defined in + S3 boot path specification 0.9. + +Copyright (c) 2006 - 2015, Intel 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 + +#include "AcpiS3Save.h" + +// +// 8 extra pages for PF handler. +// +#define EXTRA_PAGE_TABLE_PAGES 8 + +/** + Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save. +**/ +VOID +InstallAcpiS3SaveThunk ( + VOID + ); + +/** + Hook point for AcpiVariableThunkPlatform for S3Ready. + + @param AcpiS3Context ACPI s3 context +**/ +VOID +S3ReadyThunkPlatform ( + IN ACPI_S3_CONTEXT *AcpiS3Context + ); + +UINTN mLegacyRegionSize; + +EFI_ACPI_S3_SAVE_PROTOCOL mS3Save = { + LegacyGetS3MemorySize, + S3Ready, +}; + +EFI_GUID mAcpiS3IdtrProfileGuid = { + 0xdea652b0, 0xd587, 0x4c54, { 0xb5, 0xb4, 0xc6, 0x82, 0xe7, 0xa0, 0xaa, 0x3d } +}; + +/** + Allocate memory below 4G memory address. + + This function allocates memory below 4G memory address. + + @param MemoryType Memory type of memory to allocate. + @param Size Size of memory to allocate. + + @return Allocated address for output. + +**/ +VOID* +AllocateMemoryBelow4G ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Size + ) +{ + UINTN Pages; + EFI_PHYSICAL_ADDRESS Address; + EFI_STATUS Status; + VOID* Buffer; + + Pages = EFI_SIZE_TO_PAGES (Size); + Address = 0xffffffff; + + Status = gBS->AllocatePages ( + AllocateMaxAddress, + MemoryType, + Pages, + &Address + ); + ASSERT_EFI_ERROR (Status); + + Buffer = (VOID *) (UINTN) Address; + ZeroMem (Buffer, Size); + + return Buffer; +} + +/** + + This function scan ACPI table in RSDT. + + @param Rsdt ACPI RSDT + @param Signature ACPI table signature + + @return ACPI table + +**/ +VOID * +ScanTableInRSDT ( + IN EFI_ACPI_DESCRIPTION_HEADER *Rsdt, + IN UINT32 Signature + ) +{ + UINTN Index; + UINT32 EntryCount; + UINT32 *EntryPtr; + EFI_ACPI_DESCRIPTION_HEADER *Table; + + if (Rsdt == NULL) { + return NULL; + } + + EntryCount = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32); + + EntryPtr = (UINT32 *)(Rsdt + 1); + for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) { + Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(*EntryPtr)); + if (Table->Signature == Signature) { + return Table; + } + } + + return NULL; +} + +/** + + This function scan ACPI table in XSDT. + + @param Xsdt ACPI XSDT + @param Signature ACPI table signature + + @return ACPI table + +**/ +VOID * +ScanTableInXSDT ( + IN EFI_ACPI_DESCRIPTION_HEADER *Xsdt, + IN UINT32 Signature + ) +{ + UINTN Index; + UINT32 EntryCount; + UINT64 EntryPtr; + UINTN BasePtr; + EFI_ACPI_DESCRIPTION_HEADER *Table; + + if (Xsdt == NULL) { + return NULL; + } + + EntryCount = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64); + + BasePtr = (UINTN)(Xsdt + 1); + for (Index = 0; Index < EntryCount; Index ++) { + CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64)); + Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(EntryPtr)); + if (Table->Signature == Signature) { + return Table; + } + } + + return NULL; +} + +/** + To find Facs in FADT. + + @param Fadt FADT table pointer + + @return Facs table pointer. +**/ +EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * +FindAcpiFacsFromFadt ( + IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt + ) +{ + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + UINT64 Data64; + + if (Fadt == NULL) { + return NULL; + } + + if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { + Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl; + } else { + if (Fadt->FirmwareCtrl != 0) { + Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl; + } else { + CopyMem (&Data64, &Fadt->XFirmwareCtrl, sizeof(UINT64)); + Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Data64; + } + } + return Facs; +} + +/** + To find Facs in Acpi tables. + + To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored + in the table. + + @param AcpiTableGuid The guid used to find ACPI table in UEFI ConfigurationTable. + + @return Facs table pointer. +**/ +EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * +FindAcpiFacsTableByAcpiGuid ( + IN EFI_GUID *AcpiTableGuid + ) +{ + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + EFI_ACPI_DESCRIPTION_HEADER *Rsdt; + EFI_ACPI_DESCRIPTION_HEADER *Xsdt; + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + UINTN Index; + + Rsdp = NULL; + // + // found ACPI table RSD_PTR from system table + // + for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { + if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), AcpiTableGuid)) { + // + // A match was found. + // + Rsdp = gST->ConfigurationTable[Index].VendorTable; + break; + } + } + + if (Rsdp == NULL) { + return NULL; + } + + // + // Search XSDT + // + if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) { + Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->XsdtAddress; + Fadt = ScanTableInXSDT (Xsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE); + if (Fadt != NULL) { + Facs = FindAcpiFacsFromFadt (Fadt); + if (Facs != NULL) { + return Facs; + } + } + } + + // + // Search RSDT + // + Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress; + Fadt = ScanTableInRSDT (Rsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE); + if (Fadt != NULL) { + Facs = FindAcpiFacsFromFadt (Fadt); + if (Facs != NULL) { + return Facs; + } + } + + return NULL; +} + +/** + To find Facs in Acpi tables. + + To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored + in the table. + + @return Facs table pointer. +**/ +EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * +FindAcpiFacsTable ( + VOID + ) +{ + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + + Facs = FindAcpiFacsTableByAcpiGuid (&gEfiAcpi20TableGuid); + if (Facs != NULL) { + return Facs; + } + + return FindAcpiFacsTableByAcpiGuid (&gEfiAcpi10TableGuid); +} + +/** + The function will check if long mode waking vector is supported. + + @param[in] Facs Pointer to FACS table. + + @retval TRUE Long mode waking vector is supported. + @retval FALSE Long mode waking vector is not supported. + +**/ +BOOLEAN +IsLongModeWakingVectorSupport ( + IN EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs + ) +{ + if ((Facs == NULL) || + (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ) { + // + // Something wrong with FACS. + // + return FALSE; + } + if (Facs->XFirmwareWakingVector != 0) { + if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && + ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0)) { + // + // BIOS supports 64bit waking vector. + // + if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { + return TRUE; + } + } + } + return FALSE; +} + +/** + Allocates page table buffer. + + @param[in] LongModeWakingVectorSupport Support long mode waking vector or not. + + If BootScriptExector driver will run in 64-bit mode, this function will establish the 1:1 + virtual to physical mapping page table when long mode waking vector is supported, otherwise + create 4G page table when long mode waking vector is not supported and let PF handler to + handle > 4G request. + If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. + + @return Page table base address. + +**/ +EFI_PHYSICAL_ADDRESS +S3AllocatePageTablesBuffer ( + IN BOOLEAN LongModeWakingVectorSupport + ) +{ + if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { + UINTN ExtraPageTablePages; + UINT32 RegEax; + UINT32 RegEdx; + UINT8 PhysicalAddressBits; + UINT32 NumberOfPml4EntriesNeeded; + UINT32 NumberOfPdpEntriesNeeded; + EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress; + UINTN TotalPageTableSize; + VOID *Hob; + BOOLEAN Page1GSupport; + + Page1GSupport = FALSE; + if (PcdGetBool(PcdUse1GPageTable)) { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000001) { + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT26) != 0) { + Page1GSupport = TRUE; + } + } + } + + // + // Get physical address bits supported. + // + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } else { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits = (UINT8) RegEax; + } else { + PhysicalAddressBits = 36; + } + } + + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. + // + ASSERT (PhysicalAddressBits <= 52); + if (PhysicalAddressBits > 48) { + PhysicalAddressBits = 48; + } + + ExtraPageTablePages = 0; + if (!LongModeWakingVectorSupport) { + // + // Create 4G page table when BIOS does not support long mode waking vector, + // and let PF handler to handle > 4G request. + // + PhysicalAddressBits = 32; + ExtraPageTablePages = EXTRA_PAGE_TABLE_PAGES; + } + + // + // Calculate the table entries needed. + // + if (PhysicalAddressBits <= 39 ) { + NumberOfPml4EntriesNeeded = 1; + NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); + } else { + NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); + NumberOfPdpEntriesNeeded = 512; + } + + // + // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs. + // + if (!Page1GSupport) { + TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded); + } else { + TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded); + } + + TotalPageTableSize += ExtraPageTablePages; + DEBUG ((EFI_D_ERROR, "AcpiS3Save TotalPageTableSize - 0x%x pages\n", TotalPageTableSize)); + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. + // + S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGES_TO_SIZE(TotalPageTableSize)); + ASSERT (S3NvsPageTableAddress != 0); + return S3NvsPageTableAddress; + } else { + // + // If DXE is running 32-bit mode, no need to establish page table. + // + return (EFI_PHYSICAL_ADDRESS) 0; + } +} + +/** + Gets the buffer of legacy memory below 1 MB + This function is to get the buffer in legacy memory below 1MB that is required during S3 resume. + + @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. + @param Size The returned size of legacy memory below 1 MB. + + @retval EFI_SUCCESS Size is successfully returned. + @retval EFI_INVALID_PARAMETER The pointer Size is NULL. + +**/ +EFI_STATUS +EFIAPI +LegacyGetS3MemorySize ( + IN EFI_ACPI_S3_SAVE_PROTOCOL *This, + OUT UINTN *Size + ) +{ + if (Size == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Size = mLegacyRegionSize; + return EFI_SUCCESS; +} + +/** + Prepares all information that is needed in the S3 resume boot path. + + Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path + + @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. + @param LegacyMemoryAddress The base address of legacy memory. + + @retval EFI_NOT_FOUND Some necessary information cannot be found. + @retval EFI_SUCCESS All information was saved successfully. + @retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information. + @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB. + +**/ +EFI_STATUS +EFIAPI +S3Ready ( + IN EFI_ACPI_S3_SAVE_PROTOCOL *This, + IN VOID *LegacyMemoryAddress + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS AcpiS3ContextBuffer; + ACPI_S3_CONTEXT *AcpiS3Context; + STATIC BOOLEAN AlreadyEntered; + IA32_DESCRIPTOR *Idtr; + IA32_IDT_GATE_DESCRIPTOR *IdtGate; + EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + + DEBUG ((EFI_D_INFO, "S3Ready!\n")); + + // + // Platform may invoke AcpiS3Save->S3Save() before ExitPmAuth, because we need save S3 information there, while BDS ReadyToBoot may invoke it again. + // So if 2nd S3Save() is triggered later, we need ignore it. + // + if (AlreadyEntered) { + return EFI_SUCCESS; + } + AlreadyEntered = TRUE; + + AcpiS3Context = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(*AcpiS3Context)); + ASSERT (AcpiS3Context != NULL); + AcpiS3ContextBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context; + + // + // Get ACPI Table because we will save its position to variable + // + Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) FindAcpiFacsTable (); + AcpiS3Context->AcpiFacsTable = (EFI_PHYSICAL_ADDRESS) (UINTN) Facs; + ASSERT (AcpiS3Context->AcpiFacsTable != 0); + + IdtGate = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR)); + Idtr = (IA32_DESCRIPTOR *)(IdtGate + 0x100); + Idtr->Base = (UINTN)IdtGate; + Idtr->Limit = (UINT16)(sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 - 1); + AcpiS3Context->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)Idtr; + + Status = SaveLockBox ( + &mAcpiS3IdtrProfileGuid, + (VOID *)(UINTN)Idtr, + (UINTN)sizeof(IA32_DESCRIPTOR) + ); + ASSERT_EFI_ERROR (Status); + + Status = SetLockBoxAttributes (&mAcpiS3IdtrProfileGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); + ASSERT_EFI_ERROR (Status); + + // + // Allocate page table + // + AcpiS3Context->S3NvsPageTableAddress = S3AllocatePageTablesBuffer (IsLongModeWakingVectorSupport (Facs)); + + // + // Allocate stack + // + AcpiS3Context->BootScriptStackSize = PcdGet32 (PcdS3BootScriptStackSize); + AcpiS3Context->BootScriptStackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3BootScriptStackSize)); + ASSERT (AcpiS3Context->BootScriptStackBase != 0); + + // + // Allocate a code buffer < 4G for S3 debug to load external code, set invalid code instructions in it. + // + AcpiS3Context->S3DebugBufferAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGE_SIZE); + SetMem ((VOID *)(UINTN)AcpiS3Context->S3DebugBufferAddress, EFI_PAGE_SIZE, 0xff); + + DEBUG((EFI_D_INFO, "AcpiS3Context: AcpiFacsTable is 0x%8x\n", AcpiS3Context->AcpiFacsTable)); + DEBUG((EFI_D_INFO, "AcpiS3Context: IdtrProfile is 0x%8x\n", AcpiS3Context->IdtrProfile)); + DEBUG((EFI_D_INFO, "AcpiS3Context: S3NvsPageTableAddress is 0x%8x\n", AcpiS3Context->S3NvsPageTableAddress)); + DEBUG((EFI_D_INFO, "AcpiS3Context: S3DebugBufferAddress is 0x%8x\n", AcpiS3Context->S3DebugBufferAddress)); + DEBUG((EFI_D_INFO, "AcpiS3Context: BootScriptStackBase is 0x%8x\n", AcpiS3Context->BootScriptStackBase)); + DEBUG((EFI_D_INFO, "AcpiS3Context: BootScriptStackSize is 0x%8x\n", AcpiS3Context->BootScriptStackSize)); + + Status = SaveLockBox ( + &gEfiAcpiVariableGuid, + &AcpiS3ContextBuffer, + sizeof(AcpiS3ContextBuffer) + ); + ASSERT_EFI_ERROR (Status); + + Status = SaveLockBox ( + &gEfiAcpiS3ContextGuid, + (VOID *)(UINTN)AcpiS3Context, + (UINTN)sizeof(*AcpiS3Context) + ); + ASSERT_EFI_ERROR (Status); + + Status = SetLockBoxAttributes (&gEfiAcpiS3ContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); + ASSERT_EFI_ERROR (Status); + + if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) { + S3ReadyThunkPlatform (AcpiS3Context); + } + + return EFI_SUCCESS; +} + +/** + The Driver Entry Point. + + The function is the driver Entry point which will produce AcpiS3SaveProtocol. + + @param ImageHandle A handle for the image that is initializing this driver + @param 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 +InstallAcpiS3Save ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (!FeaturePcdGet(PcdPlatformCsmSupport)) { + // + // More memory for no CSM tip, because GDT need relocation + // + mLegacyRegionSize = 0x250; + } else { + mLegacyRegionSize = 0x100; + } + + if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) { + InstallAcpiS3SaveThunk (); + } + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiAcpiS3SaveProtocolGuid, + EFI_NATIVE_INTERFACE, + &mS3Save + ); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h new file mode 100644 index 0000000000..65974a3402 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h @@ -0,0 +1,59 @@ +/** @file + This is an implementation of the ACPI S3 Save protocol. This is defined in + S3 boot path specification 0.9. + +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 _ACPI_S3_SAVE_H_ +#define _ACPI_S3_SAVE_H_ + +/** + Gets the buffer of legacy memory below 1 MB + This function is to get the buffer in legacy memory below 1MB that is required during S3 resume. + + @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. + @param Size The returned size of legacy memory below 1 MB. + + @retval EFI_SUCCESS Size is successfully returned. + @retval EFI_INVALID_PARAMETER The pointer Size is NULL. + +**/ +EFI_STATUS +EFIAPI +LegacyGetS3MemorySize ( + IN EFI_ACPI_S3_SAVE_PROTOCOL * This, + OUT UINTN * Size + ); + +/** + Prepares all information that is needed in the S3 resume boot path. + + Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path + + @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. + @param LegacyMemoryAddress The base address of legacy memory. + + @retval EFI_NOT_FOUND Some necessary information cannot be found. + @retval EFI_SUCCESS All information was saved successfully. + @retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information. + @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB. + +**/ +EFI_STATUS +EFIAPI +S3Ready ( + IN EFI_ACPI_S3_SAVE_PROTOCOL *This, + IN VOID *LegacyMemoryAddress + ); +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf new file mode 100644 index 0000000000..366eb147b7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf @@ -0,0 +1,89 @@ +## @file +# AcpiS3Save module installs ACPI S3 Save protocol to prepare S3 boot data. +# +# Copyright (c) 2006 - 2015, Intel 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 = AcpiS3SaveDxe + MODULE_UNI_FILE = AcpiS3SaveDxe.uni + FILE_GUID = 2BDED685-F733-455f-A840-43A22B791FB3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InstallAcpiS3Save + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + AcpiS3Save.h + AcpiS3Save.c + AcpiVariableThunkPlatform.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + PcdLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + HobLib + UefiLib + LockBoxLib + DebugLib + DxeServicesLib + +[Guids] + gEfiAcpiVariableGuid ## PRODUCES ## UNDEFINED # LockBox Save Data. + gEfiAcpiS3ContextGuid ## PRODUCES ## UNDEFINED # LockBox Save Data. + gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable + ## SOMETIMES_CONSUMES ## Variable:L"AcpiGlobalVariable" + ## SOMETIMES_PRODUCES ## Variable:L"AcpiGlobalVariable" + gEfiAcpiVariableCompatiblityGuid + +[Protocols] + gEfiAcpiS3SaveProtocolGuid ## PRODUCES + gFrameworkEfiMpServiceProtocolGuid ## SOMETIMES_CONSUMES + ## NOTIFY + ## SOMETIMES_CONSUMES + gEdkiiVariableLockProtocolGuid + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformCsmSupport ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize ## SOMETIMES_CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3BootScriptStackSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## CONSUMES + +[Depex] + # + # Note: the extra dependency of gEfiMpServiceProtocolGuid is to ensure that ACPI variable is set by MpDxe driver before + # AcpiS3SaveDxe module is executed. + # + gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid AND gEfiMpServiceProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + AcpiS3SaveDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni new file mode 100644 index 0000000000..05f1398985 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni new file mode 100644 index 0000000000..7b89727292 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c new file mode 100644 index 0000000000..7ad9eb4336 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c @@ -0,0 +1,224 @@ +/** @file + This is an implementation of the AcpiVariable platform field for ECP platform. + +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 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. + +== + +typedef struct { + EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase; <<=== + UINT32 AcpiReservedMemorySize; <<=== + EFI_PHYSICAL_ADDRESS S3ReservedLowMemoryBase; + EFI_PHYSICAL_ADDRESS AcpiBootScriptTable; + EFI_PHYSICAL_ADDRESS RuntimeScriptTableBase; + EFI_PHYSICAL_ADDRESS AcpiFacsTable; + UINT64 SystemMemoryLength; <<=== + ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData; + EFI_PHYSICAL_ADDRESS VideoOpromAddress; + UINT32 VideoOpromSize; + EFI_PHYSICAL_ADDRESS S3DebugBufferAddress; + EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint; +} ACPI_VARIABLE_SET_COMPATIBILITY; + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED +ACPI_VARIABLE_SET_COMPATIBILITY *mAcpiVariableSetCompatibility = NULL; + +/** + Allocate memory below 4G memory address. + + This function allocates memory below 4G memory address. + + @param MemoryType Memory type of memory to allocate. + @param Size Size of memory to allocate. + + @return Allocated address for output. + +**/ +VOID* +AllocateMemoryBelow4G ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Size + ); + +/** + Hook point for AcpiVariableThunkPlatform for S3Ready. + + @param AcpiS3Context ACPI s3 context +**/ +VOID +S3ReadyThunkPlatform ( + IN ACPI_S3_CONTEXT *AcpiS3Context + ) +{ + EFI_PHYSICAL_ADDRESS AcpiMemoryBase; + UINT32 AcpiMemorySize; + EFI_PEI_HOB_POINTERS Hob; + UINT64 MemoryLength; + + DEBUG ((EFI_D_INFO, "S3ReadyThunkPlatform\n")); + + if (mAcpiVariableSetCompatibility == NULL) { + return; + } + + // + // Allocate ACPI reserved memory under 4G + // + AcpiMemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3AcpiReservedMemorySize)); + ASSERT (AcpiMemoryBase != 0); + AcpiMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize); + + // + // Calculate the system memory length by memory hobs + // + MemoryLength = 0x100000; + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); + ASSERT (Hob.Raw != NULL); + while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) { + if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { + // + // Skip the memory region below 1MB + // + if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) { + MemoryLength += Hob.ResourceDescriptor->ResourceLength; + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); + } + + mAcpiVariableSetCompatibility->AcpiReservedMemoryBase = AcpiMemoryBase; + mAcpiVariableSetCompatibility->AcpiReservedMemorySize = AcpiMemorySize; + mAcpiVariableSetCompatibility->SystemMemoryLength = MemoryLength; + + DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemoryBase is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemoryBase)); + DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemorySize is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemorySize)); + DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: SystemMemoryLength is 0x%8x\n", mAcpiVariableSetCompatibility->SystemMemoryLength)); + + return ; +} + +/** + Register callback function upon VariableLockProtocol + to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. +**/ +VOID +EFIAPI +VariableLockAcpiGlobalVariable ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; + // + // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock protocol exists + // + Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); + if (!EFI_ERROR (Status)) { + Status = VariableLock->RequestToLock (VariableLock, ACPI_GLOBAL_VARIABLE, &gEfiAcpiVariableCompatiblityGuid); + ASSERT_EFI_ERROR (Status); + } +} + +/** + Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save. +**/ +VOID +InstallAcpiS3SaveThunk ( + VOID + ) +{ + EFI_STATUS Status; + FRAMEWORK_EFI_MP_SERVICES_PROTOCOL *FrameworkMpService; + UINTN VarSize; + VOID *Registration; + + Status = gBS->LocateProtocol ( + &gFrameworkEfiMpServiceProtocolGuid, + NULL, + (VOID**) &FrameworkMpService + ); + if (!EFI_ERROR (Status)) { + // + // On ECP platform, if framework CPU drivers are in use, The compatible version of ACPI variable set + // should be produced by CPU driver. + // + VarSize = sizeof (mAcpiVariableSetCompatibility); + Status = gRT->GetVariable ( + ACPI_GLOBAL_VARIABLE, + &gEfiAcpiVariableCompatiblityGuid, + NULL, + &VarSize, + &mAcpiVariableSetCompatibility + ); + if (EFI_ERROR (Status) || (VarSize != sizeof (mAcpiVariableSetCompatibility))) { + DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility was not saved by CPU driver correctly. OS S3 may fail!\n")); + mAcpiVariableSetCompatibility = NULL; + } + } else { + // + // Allocate/initialize the compatible version of Acpi Variable Set since Framework chipset/platform + // driver need this variable. ACPI_GLOBAL_VARIABLE variable is not used in runtime phase, + // so RT attribute is not needed for it. + // + mAcpiVariableSetCompatibility = AllocateMemoryBelow4G (EfiACPIMemoryNVS, sizeof(ACPI_VARIABLE_SET_COMPATIBILITY)); + Status = gRT->SetVariable ( + ACPI_GLOBAL_VARIABLE, + &gEfiAcpiVariableCompatiblityGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(mAcpiVariableSetCompatibility), + &mAcpiVariableSetCompatibility + ); + if (!EFI_ERROR (Status)) { + // + // Register callback function upon VariableLockProtocol + // to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it. + // + EfiCreateProtocolNotifyEvent ( + &gEdkiiVariableLockProtocolGuid, + TPL_CALLBACK, + VariableLockAcpiGlobalVariable, + NULL, + &Registration + ); + } else { + DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility cannot be saved: %r. OS S3 may fail!\n", Status)); + gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiVariableSetCompatibility, + EFI_SIZE_TO_PAGES (sizeof (ACPI_VARIABLE_SET_COMPATIBILITY)) + ); + mAcpiVariableSetCompatibility = NULL; + } + } + + DEBUG((EFI_D_INFO, "AcpiVariableSetCompatibility is 0x%8x\n", mAcpiVariableSetCompatibility)); +} diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.c b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.c new file mode 100644 index 0000000000..a8b1f06117 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.c @@ -0,0 +1,91 @@ +/** @file + This is an implementation of the ACPI Support protocol. This is defined in + the Tiano ACPI External Product Specification, revision 0.3.6. + +Copyright (c) 2006 - 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. + +**/ + +// +// Includes +// +#include "AcpiSupport.h" + +// +// Handle to install ACPI Table Protocol (and ACPI Suppport protocol). +// +EFI_HANDLE mHandle = NULL; + +/** + Entry point of the ACPI support driver. This function creates and initializes an instance of the ACPI Support + Protocol and installs it on a new handle. + + @param ImageHandle A handle for the image that is initializing this driver + @param 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 +InstallAcpiSupport ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + EFI_STATUS Status; + EFI_ACPI_SUPPORT_INSTANCE *PrivateData; + + // + // Initialize our protocol + // + PrivateData = AllocateZeroPool (sizeof (EFI_ACPI_SUPPORT_INSTANCE)); + ASSERT (PrivateData); + PrivateData->Signature = EFI_ACPI_SUPPORT_SIGNATURE; + + // + // Call all constructors per produced protocols + // + Status = AcpiSupportAcpiSupportConstructor (PrivateData); + if (EFI_ERROR (Status)) { + gBS->FreePool (PrivateData); + return EFI_LOAD_ERROR; + } + + // + // Install ACPI Table protocol and optional ACPI support protocol based on + // feature flag: PcdInstallAcpiSupportProtocol. + // + if (FeaturePcdGet (PcdInstallAcpiSupportProtocol)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiAcpiTableProtocolGuid, + &PrivateData->AcpiTableProtocol, + &gEfiAcpiSupportProtocolGuid, + &PrivateData->AcpiSupport, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiAcpiTableProtocolGuid, + &PrivateData->AcpiTableProtocol, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.h b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.h new file mode 100644 index 0000000000..1bcf1e6ee5 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.h @@ -0,0 +1,166 @@ +/** @file + This is an implementation of the ACPI Support protocol. + It is in compliance with the 0.9 definition of the protocol. + +Copyright (c) 2006 - 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 _ACPI_SUPPORT_H_ +#define _ACPI_SUPPORT_H_ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Statements that include other files +// +#include + + +// +// Private Driver Data +// +// +// ACPI Table Linked List Signature. +// +#define EFI_ACPI_TABLE_LIST_SIGNATURE SIGNATURE_32 ('E', 'A', 'T', 'L') + +// +// ACPI Table Linked List Entry definition. +// +// Signature must be set to EFI_ACPI_TABLE_LIST_SIGNATURE +// Link is the linked list data. +// Version is the versions of the ACPI tables that this table belongs in. +// Table is a pointer to the table. +// PageAddress is the address of the pages allocated for the table. +// NumberOfPages is the number of pages allocated at PageAddress. +// Handle is used to identify a particular table. +// +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + EFI_ACPI_TABLE_VERSION Version; + EFI_ACPI_COMMON_HEADER *Table; + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN NumberOfPages; + UINTN Handle; +} EFI_ACPI_TABLE_LIST; + +// +// Containment record for linked list. +// +#define EFI_ACPI_TABLE_LIST_FROM_LINK(_link) CR (_link, EFI_ACPI_TABLE_LIST, Link, EFI_ACPI_TABLE_LIST_SIGNATURE) + +// +// The maximum number of tables this driver supports +// +#define EFI_ACPI_MAX_NUM_TABLES 20 + +// +// Protocol private structure definition +// +// +// ACPI support protocol instance signature definition. +// +#define EFI_ACPI_SUPPORT_SIGNATURE SIGNATURE_32 ('S', 'S', 'A', 'E') + +// +// ACPI support protocol instance data structure +// +typedef struct { + UINTN Signature; + EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp1; // Pointer to RSD_PTR structure + EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp3; // Pointer to RSD_PTR structure + EFI_ACPI_DESCRIPTION_HEADER *Rsdt1; // Pointer to RSDT table header + EFI_ACPI_DESCRIPTION_HEADER *Rsdt3; // Pointer to RSDT table header + EFI_ACPI_DESCRIPTION_HEADER *Xsdt; // Pointer to XSDT table header + EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1; // Pointer to FADT table header + EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt3; // Pointer to FADT table header + EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1; // Pointer to FACS table header + EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs3; // Pointer to FACS table header + EFI_ACPI_DESCRIPTION_HEADER *Dsdt1; // Pointer to DSDT table header + EFI_ACPI_DESCRIPTION_HEADER *Dsdt3; // Pointer to DSDT table header + LIST_ENTRY TableList; + UINTN NumberOfTableEntries1; // Number of ACPI 1.0 tables + UINTN NumberOfTableEntries3; // Number of ACPI 3.0 tables + UINTN CurrentHandle; + BOOLEAN TablesInstalled1; // ACPI 1.0 tables published + BOOLEAN TablesInstalled3; // ACPI 3.0 tables published + EFI_ACPI_SUPPORT_PROTOCOL AcpiSupport; + EFI_ACPI_TABLE_PROTOCOL AcpiTableProtocol; +} EFI_ACPI_SUPPORT_INSTANCE; + +// +// ACPI support protocol instance containing record macro +// +#define EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS(a) \ + CR (a, \ + EFI_ACPI_SUPPORT_INSTANCE, \ + AcpiSupport, \ + EFI_ACPI_SUPPORT_SIGNATURE \ + ) +// +// ACPI table protocol instance containing record macro +// +#define EFI_ACPI_TABLE_INSTANCE_FROM_ACPI_SUPPORT_THIS(a) \ + CR (a, \ + EFI_ACPI_SUPPORT_INSTANCE, \ + AcpiTableProtocol, \ + EFI_ACPI_SUPPORT_SIGNATURE \ + ) + +/** + Constructor for the ACPI support protocol. + + Constructor for the ACPI support protocol to initializes instance data. + + @param AcpiSupportInstance Instance to construct + + @retval EFI_SUCCESS Instance initialized. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +AcpiSupportAcpiSupportConstructor ( + IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance + ); +/** + Entry point of the ACPI support driver. This function creates and initializes an instance of the ACPI Support + Protocol and installs it on a new handle. + + @param ImageHandle A handle for the image that is initializing this driver + @param 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 +InstallAcpiSupport ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportAcpiSupportProtocol.c b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportAcpiSupportProtocol.c new file mode 100644 index 0000000000..6443c3acd0 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportAcpiSupportProtocol.c @@ -0,0 +1,1918 @@ +/** @file + ACPI Support Protocol implementation + +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 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. + +**/ + +// +// Includes +// +#include "AcpiSupport.h" +// +// The maximum number of tables that pre-allocated. +// +UINTN mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES; +/** + This function adds an ACPI table to the table list. It will detect FACS and + allocate the correct type of memory and properly align the table. + + @param AcpiSupportInstance Instance of the protocol. + @param Table Table to add. + @param Checksum Does the table require checksumming. + @param Version The version of the list to add the table to. + @param Handle Pointer for returning the handle. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_OUT_OF_RESOURCES Could not allocate a required resource. + @return EFI_ABORTED The table is a duplicate of a table that is required + to be unique. +**/ +EFI_STATUS +AddTableToList ( + IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, + IN VOID *Table, + IN BOOLEAN Checksum, + IN EFI_ACPI_TABLE_VERSION Version, + OUT UINTN *Handle + ); +/** + This function finds and removes the table specified by the handle. + + @param AcpiSupportInstance Instance of the protocol. + @param Version Bitmask of which versions to remove. + @param Handle Table to remove. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_ABORTED An error occurred. + @return EFI_NOT_FOUND Handle not found in table list. +**/ +EFI_STATUS +RemoveTableFromList ( + IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, + IN EFI_ACPI_TABLE_VERSION Version, + IN UINTN Handle + ); +/** + This function calculates and updates an UINT8 checksum. + + @param Buffer Pointer to buffer to checksum + @param Size Number of bytes to checksum + @param ChecksumOffset Offset to place the checksum result in + + @return EFI_SUCCESS The function completed successfully. +**/ +EFI_STATUS +AcpiPlatformChecksum ( + IN VOID *Buffer, + IN UINTN Size, + IN UINTN ChecksumOffset + ); +/** + Checksum all versions of the common tables, RSDP, RSDT, XSDT. + + @param AcpiSupportInstance Protocol instance private data. + + @return EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +ChecksumCommonTables ( + IN OUT EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance + ); + +/** + This function returns a table specified by an index if it exists. + + The function returns a buffer containing the table that the caller must free. + The function also returns a handle used to identify the table for update or + deletion using the SetAcpiTable function. + + @param This Instance of the protocol. + @param Index Zero-based index of the table to retrieve. + @param Table Returned pointer to the table. + @param Version Versions that the table is currently used in. + @param Handle Handle of the table, used in updating tables. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The requested table does not exist. + +**/ +EFI_STATUS +EFIAPI +GetAcpiTable ( + IN EFI_ACPI_SUPPORT_PROTOCOL *This, + IN INTN Index, + OUT VOID **Table, + OUT EFI_ACPI_TABLE_VERSION *Version, + OUT UINTN *Handle + ) + +{ + EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; + INTN TempIndex; + LIST_ENTRY *CurrentLink; + LIST_ENTRY *StartLink; + EFI_ACPI_TABLE_LIST *CurrentTable; + + // + // Check for invalid input parameters + // + ASSERT (This); + ASSERT (Table); + ASSERT (Handle); + + // + // Get the instance of the protocol + // + AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); + + // + // Find the table + // + CurrentLink = AcpiSupportInstance->TableList.ForwardLink; + StartLink = &AcpiSupportInstance->TableList; + for (TempIndex = 0; (TempIndex < Index) && (CurrentLink != StartLink) && (CurrentLink != NULL); TempIndex++) { + CurrentLink = CurrentLink->ForwardLink; + } + + if (TempIndex != Index || CurrentLink == StartLink) { + return EFI_NOT_FOUND; + } + // + // Get handle and version + // + CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink); + *Handle = CurrentTable->Handle; + *Version = CurrentTable->Version; + + // + // Copy the table + // + *Table = AllocateCopyPool (CurrentTable->Table->Length, CurrentTable->Table); + ASSERT (*Table); + + return EFI_SUCCESS; +} +/** + This function adds, removes, or updates ACPI tables. If the address is not + null and the handle value is null, the table is added. If both the address and + handle are not null, the table at handle is updated with the table at address. + If the address is null and the handle is not, the table at handle is deleted. + + @param This Pointer of the protocol. + @param Table Pointer to a table. + @param Checksum Boolean indicating if the checksum should be calculated. + @param Version Version(s) to set. + @param Handle Handle of the table. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_INVALID_PARAMETER Both the Table and *Handle were NULL. + @return EFI_ABORTED Could not complete the desired request. + +**/ +EFI_STATUS +EFIAPI +SetAcpiTable ( + IN EFI_ACPI_SUPPORT_PROTOCOL *This, + IN VOID *Table OPTIONAL, + IN BOOLEAN Checksum, + IN EFI_ACPI_TABLE_VERSION Version, + IN OUT UINTN *Handle + ) +{ + EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; + UINTN SavedHandle; + EFI_STATUS Status; + + // + // Check for invalid input parameters + // + ASSERT (This); + ASSERT (Handle != NULL); + + // + // Get the instance of the protocol + // + AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); + + // + // Initialize locals + // + // + // Determine desired action + // + if (*Handle == 0) { + if (Table == NULL) { + // + // Invalid parameter combination + // + return EFI_INVALID_PARAMETER; + } else { + // + // Add table + // + Status = AddTableToList (AcpiSupportInstance, Table, Checksum, Version, Handle); + } + } else { + if (Table != NULL) { + // + // Update table + // + // + // Delete the table list entry + // + Status = RemoveTableFromList (AcpiSupportInstance, Version, *Handle); + if (EFI_ERROR (Status)) { + // + // Should not get an error here ever, but abort if we do. + // + return EFI_ABORTED; + } + // + // Set the handle to replace the table at the same handle + // + SavedHandle = AcpiSupportInstance->CurrentHandle; + AcpiSupportInstance->CurrentHandle = *Handle; + + // + // Add the table + // + Status = AddTableToList (AcpiSupportInstance, Table, Checksum, Version, Handle); + + // + // Restore the saved current handle + // + AcpiSupportInstance->CurrentHandle = SavedHandle; + } else { + // + // Delete table + // + Status = RemoveTableFromList (AcpiSupportInstance, Version, *Handle); + } + } + + if (EFI_ERROR (Status)) { + // + // Should not get an error here ever, but abort if we do. + // + return EFI_ABORTED; + } + // + // Done + // + return EFI_SUCCESS; +} +/** + This function publishes the specified versions of the ACPI tables by + installing EFI configuration table entries for them. Any combination of + table versions can be published. + + @param This Pointer of the protocol. + @param Version Version(s) to publish. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_ABORTED The function could not complete successfully. + +**/ +EFI_STATUS +EFIAPI +PublishTables ( + IN EFI_ACPI_SUPPORT_PROTOCOL *This, + IN EFI_ACPI_TABLE_VERSION Version + ) +{ + EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; + EFI_STATUS Status; + UINT32 *CurrentRsdtEntry; + VOID *CurrentXsdtEntry; + UINT64 Buffer64; + + // + // Get the instance of the protocol + // + AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); + + // + // Reorder tables as some operating systems don't seem to find the + // FADT correctly if it is not in the first few entries + // + + // + // Add FADT as the first entry + // + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { + CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiSupportInstance->Rsdt1 + sizeof (EFI_ACPI_DESCRIPTION_HEADER)); + *CurrentRsdtEntry = (UINT32) (UINTN) AcpiSupportInstance->Fadt1; + } + if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { + CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiSupportInstance->Rsdt3 + sizeof (EFI_ACPI_DESCRIPTION_HEADER)); + *CurrentRsdtEntry = (UINT32) (UINTN) AcpiSupportInstance->Fadt3; + CurrentXsdtEntry = (VOID *) ((UINT8 *) AcpiSupportInstance->Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER)); + // + // Add entry to XSDT, XSDT expects 64 bit pointers, but + // the table pointers in XSDT are not aligned on 8 byte boundary. + // + Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Fadt3; + CopyMem ( + CurrentXsdtEntry, + &Buffer64, + sizeof (UINT64) + ); + } + + // + // Do checksum again because Dsdt/Xsdt is updated. + // + ChecksumCommonTables (AcpiSupportInstance); + + // + // Add the RSD_PTR to the system table and store that we have installed the + // tables. + // + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && !AcpiSupportInstance->TablesInstalled1) { + Status = gBS->InstallConfigurationTable (&gEfiAcpi10TableGuid, AcpiSupportInstance->Rsdp1); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + AcpiSupportInstance->TablesInstalled1 = TRUE; + } + + if (((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) && + !AcpiSupportInstance->TablesInstalled3) { + Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, AcpiSupportInstance->Rsdp3); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + AcpiSupportInstance->TablesInstalled3= TRUE; + } + + return EFI_SUCCESS; +} +/** + Installs an ACPI table into the RSDT/XSDT. + Note that the ACPI table should be checksumed before installing it. + Otherwise it will assert. + + @param This Protocol instance pointer. + @param AcpiTableBuffer A pointer to a buffer containing the ACPI table to be installed. + @param AcpiTableBufferSize Specifies the size, in bytes, of the AcpiTableBuffer buffer. + @param TableKey Reurns a key to refer to the ACPI table. + + @return EFI_SUCCESS The table was successfully inserted. + @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize + and the size field embedded in the ACPI table pointed to by AcpiTableBuffer + are not in sync. + @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request. + @retval EFI_ACCESS_DENIED The table signature matches a table already + present in the system and platform policy + does not allow duplicate tables of this type. + +**/ +EFI_STATUS +EFIAPI +InstallAcpiTable ( + IN EFI_ACPI_TABLE_PROTOCOL *This, + IN VOID *AcpiTableBuffer, + IN UINTN AcpiTableBufferSize, + OUT UINTN *TableKey + ) +{ + EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; + EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport; + EFI_STATUS Status; + VOID *AcpiTableBufferConst; + + // + // Check for invalid input parameters + // + if ((AcpiTableBuffer == NULL) || (TableKey == NULL) + || (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer)->Length != AcpiTableBufferSize)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get the instance of the ACPI support protocol + // + AcpiSupportInstance = EFI_ACPI_TABLE_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); + AcpiSupport = &AcpiSupportInstance->AcpiSupport; + + // + // Install the ACPI table by using ACPI support protocol + // + AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize, AcpiTableBuffer); + *TableKey = 0; + Status = AddTableToList ( + AcpiSupportInstance, + AcpiTableBufferConst, + TRUE, + EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0, + TableKey + ); + if (!EFI_ERROR (Status)) { + Status = AcpiSupport->PublishTables ( + AcpiSupport, + EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0 + ); + } + FreePool (AcpiTableBufferConst); + + return Status; +} +/** + Removes an ACPI table from the RSDT/XSDT. + + @param This Protocol instance pointer. + @param TableKey Specifies the table to uninstall. The key was returned from InstallAcpiTable(). + + @return EFI_SUCCESS The table was successfully uninstalled. + @return EFI_NOT_FOUND TableKey does not refer to a valid key for a table entry. + +**/ +EFI_STATUS +EFIAPI +UninstallAcpiTable ( + IN EFI_ACPI_TABLE_PROTOCOL *This, + IN UINTN TableKey + ) +{ + EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; + EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport; + EFI_STATUS Status; + + // + // Get the instance of the ACPI support protocol + // + AcpiSupportInstance = EFI_ACPI_TABLE_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); + AcpiSupport = &AcpiSupportInstance->AcpiSupport; + + // + // Uninstall the ACPI table by using ACPI support protocol + // + Status = RemoveTableFromList ( + AcpiSupportInstance, + EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0, + TableKey + ); + if (!EFI_ERROR (Status)) { + Status = AcpiSupport->PublishTables ( + AcpiSupport, + EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0 + ); + } + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } +} +/** + If the number of APCI tables exceeds the preallocated max table number, enlarge the table buffer. + + @param AcpiSupportInstance ACPI support protocol instance data structure + + @return EFI_SUCCESS reallocate the table beffer successfully. + @return EFI_OUT_OF_RESOURCES Unable to allocate required resources. + +**/ +EFI_STATUS +ReallocateAcpiTableBuffer ( + IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance + ) +{ + UINTN NewMaxTableNumber; + UINTN TotalSize; + UINT8 *Pointer; + EFI_PHYSICAL_ADDRESS PageAddress; + EFI_ACPI_SUPPORT_INSTANCE TempPrivateData; + EFI_STATUS Status; + UINT64 CurrentData; + + CopyMem (&TempPrivateData, AcpiSupportInstance, sizeof (EFI_ACPI_SUPPORT_INSTANCE)); + // + // Enlarge the max table number from mEfiAcpiMaxNumTables to mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES + // + NewMaxTableNumber = mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES; + // + // Create RSDT, XSDT structures and allocate buffers. + // + TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT + NewMaxTableNumber * sizeof (UINT32) + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT + NewMaxTableNumber * sizeof (UINT32) + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT + NewMaxTableNumber * sizeof (UINT64); + + // + // Allocate memory in the lower 32 bit of address range for + // compatibility with ACPI 1.0 OS. + // + // This is done because ACPI 1.0 pointers are 32 bit values. + // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses. + // There is no architectural reason these should be below 4GB, it is purely + // for convenience of implementation that we force memory below 4GB. + // + PageAddress = 0xFFFFFFFF; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIReclaimMemory, + EFI_SIZE_TO_PAGES (TotalSize), + &PageAddress + ); + + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Pointer = (UINT8 *) (UINTN) PageAddress; + ZeroMem (Pointer, TotalSize); + + AcpiSupportInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; + Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32)); + AcpiSupportInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; + Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32)); + AcpiSupportInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; + + // + // Update RSDP to point to the new Rsdt and Xsdt address. + // + AcpiSupportInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt1; + AcpiSupportInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt3; + CurrentData = (UINT64) (UINTN) AcpiSupportInstance->Xsdt; + CopyMem (&AcpiSupportInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64)); + + // + // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer + // + CopyMem (AcpiSupportInstance->Rsdt1, TempPrivateData.Rsdt1, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); + CopyMem (AcpiSupportInstance->Rsdt3, TempPrivateData.Rsdt3, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); + CopyMem (AcpiSupportInstance->Xsdt, TempPrivateData.Xsdt, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT64))); + + // + // Calculate orignal ACPI table buffer size + // + TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT + mEfiAcpiMaxNumTables * sizeof (UINT32) + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT + mEfiAcpiMaxNumTables * sizeof (UINT32) + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT + mEfiAcpiMaxNumTables * sizeof (UINT64); + gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize)); + + // + // Update the Max ACPI table number + // + mEfiAcpiMaxNumTables = NewMaxTableNumber; + return EFI_SUCCESS; +} +/** + This function adds an ACPI table to the table list. It will detect FACS and + allocate the correct type of memory and properly align the table. + + @param AcpiSupportInstance Instance of the protocol. + @param Table Table to add. + @param Checksum Does the table require checksumming. + @param Version The version of the list to add the table to. + @param Handle Pointer for returning the handle. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_OUT_OF_RESOURCES Could not allocate a required resource. + @retval EFI_ACCESS_DENIED The table signature matches a table already + present in the system and platform policy + does not allow duplicate tables of this type. +**/ +EFI_STATUS +AddTableToList ( + IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, + IN VOID *Table, + IN BOOLEAN Checksum, + IN EFI_ACPI_TABLE_VERSION Version, + OUT UINTN *Handle + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_LIST *CurrentTableList; + UINT32 CurrentTableSignature; + UINT32 CurrentTableSize; + UINT32 *CurrentRsdtEntry; + VOID *CurrentXsdtEntry; + UINT64 Buffer64; + BOOLEAN AddToRsdt; + + // + // Check for invalid input parameters + // + ASSERT (AcpiSupportInstance); + ASSERT (Table); + ASSERT (Handle); + + // + // Init locals + // + AddToRsdt = TRUE; + + // + // Create a new list entry + // + CurrentTableList = AllocatePool (sizeof (EFI_ACPI_TABLE_LIST)); + ASSERT (CurrentTableList); + + // + // Determine table type and size + // + CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table)->Signature; + CurrentTableSize = ((EFI_ACPI_COMMON_HEADER *) Table)->Length; + + // + // Allocate a buffer for the table. All tables are allocated in the lower 32 bits of address space + // for backwards compatibility with ACPI 1.0 OS. + // + // This is done because ACPI 1.0 pointers are 32 bit values. + // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses. + // There is no architectural reason these should be below 4GB, it is purely + // for convenience of implementation that we force memory below 4GB. + // + CurrentTableList->PageAddress = 0xFFFFFFFF; + CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize); + + // + // Allocation memory type depends on the type of the table + // + if ((CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) || + (CurrentTableSignature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE)) { + // + // Allocate memory for the FACS. This structure must be aligned + // on a 64 byte boundary and must be ACPI NVS memory. + // Using AllocatePages should ensure that it is always aligned. + // Do not change signature for new ACPI version because they are same. + // + // UEFI table also need to be in ACPI NVS memory, because some data field + // could be updated by OS present agent. For example, BufferPtrAddress in + // SMM communication ACPI table. + // + ASSERT ((EFI_PAGE_SIZE % 64) == 0); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + CurrentTableList->NumberOfPages, + &CurrentTableList->PageAddress + ); + } else { + // + // All other tables are ACPI reclaim memory, no alignment requirements. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIReclaimMemory, + CurrentTableList->NumberOfPages, + &CurrentTableList->PageAddress + ); + } + // + // Check return value from memory alloc. + // + if (EFI_ERROR (Status)) { + gBS->FreePool (CurrentTableList); + return EFI_OUT_OF_RESOURCES; + } + // + // Update the table pointer with the allocated memory start + // + CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress; + + // + // Initialize the table contents + // + CurrentTableList->Signature = EFI_ACPI_TABLE_LIST_SIGNATURE; + CopyMem (CurrentTableList->Table, Table, CurrentTableSize); + CurrentTableList->Handle = AcpiSupportInstance->CurrentHandle++; + *Handle = CurrentTableList->Handle; + CurrentTableList->Version = Version; + + // + // Update internal pointers if this is a required table. If it is a required + // table and a table of that type already exists, return an error. + // + // Calculate the checksum if the table is not FACS. + // + switch (CurrentTableSignature) { + + case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: + // + // We don't add the FADT in the standard way because some + // OS expect the FADT to be early in the table list. + // So we always add it as the first element in the list. + // + AddToRsdt = FALSE; + + // + // Check that the table has not been previously added. + // + if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Fadt1 != NULL) || + ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiSupportInstance->Fadt3 != NULL) || + ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiSupportInstance->Fadt3 != NULL) + ) { + gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages); + gBS->FreePool (CurrentTableList); + return EFI_ACCESS_DENIED; + } + // + // Add the table to the appropriate table version + // + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { + // + // Save a pointer to the table + // + AcpiSupportInstance->Fadt1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table; + + // + // Update pointers in FADT. If tables don't exist this will put NULL pointers there. + // + AcpiSupportInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs1; + AcpiSupportInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt1; + + // + // RSDP OEM information is updated to match the FADT OEM information + // + CopyMem ( + &AcpiSupportInstance->Rsdp1->OemId, + &AcpiSupportInstance->Fadt1->Header.OemId, + 6 + ); + + // + // RSDT OEM information is updated to match the FADT OEM information. + // + CopyMem ( + &AcpiSupportInstance->Rsdt1->OemId, + &AcpiSupportInstance->Fadt1->Header.OemId, + 6 + ); + + CopyMem ( + &AcpiSupportInstance->Rsdt1->OemTableId, + &AcpiSupportInstance->Fadt1->Header.OemTableId, + sizeof (UINT64) + ); + AcpiSupportInstance->Rsdt1->OemRevision = AcpiSupportInstance->Fadt1->Header.OemRevision; + } + + if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || + (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { + // + // Save a pointer to the table + // + AcpiSupportInstance->Fadt3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table; + + // + // Update pointers in FADT. If tables don't exist this will put NULL pointers there. + // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and + // vice-versa. + // + if ((UINT64)(UINTN)AcpiSupportInstance->Facs3 < BASE_4GB) { + AcpiSupportInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs3; + ZeroMem ( + &AcpiSupportInstance->Fadt3->XFirmwareCtrl, + sizeof (UINT64) + ); + } else { + AcpiSupportInstance->Fadt3->FirmwareCtrl = 0; + Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Facs3; + CopyMem ( + &AcpiSupportInstance->Fadt3->XFirmwareCtrl, + &Buffer64, + sizeof (UINT64) + ); + } + AcpiSupportInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt3; + Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Dsdt3; + CopyMem ( + &AcpiSupportInstance->Fadt3->XDsdt, + &Buffer64, + sizeof (UINT64) + ); + + // + // RSDP OEM information is updated to match the FADT OEM information + // + CopyMem ( + &AcpiSupportInstance->Rsdp3->OemId, + &AcpiSupportInstance->Fadt3->Header.OemId, + 6 + ); + + // + // RSDT OEM information is updated to match FADT OEM information. + // + CopyMem ( + &AcpiSupportInstance->Rsdt3->OemId, + &AcpiSupportInstance->Fadt3->Header.OemId, + 6 + ); + CopyMem ( + &AcpiSupportInstance->Rsdt3->OemTableId, + &AcpiSupportInstance->Fadt3->Header.OemTableId, + sizeof (UINT64) + ); + AcpiSupportInstance->Rsdt3->OemRevision = AcpiSupportInstance->Fadt3->Header.OemRevision; + + // + // XSDT OEM information is updated to match FADT OEM information. + // + CopyMem ( + &AcpiSupportInstance->Xsdt->OemId, + &AcpiSupportInstance->Fadt3->Header.OemId, + 6 + ); + CopyMem ( + &AcpiSupportInstance->Xsdt->OemTableId, + &AcpiSupportInstance->Fadt3->Header.OemTableId, + sizeof (UINT64) + ); + AcpiSupportInstance->Xsdt->OemRevision = AcpiSupportInstance->Fadt3->Header.OemRevision; + } + + // + // Checksum the table + // + if (Checksum) { + AcpiPlatformChecksum ( + CurrentTableList->Table, + CurrentTableList->Table->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + break; + + case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE: + // + // Check that the table has not been previously added. + // + if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Facs1 != NULL) || + ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiSupportInstance->Facs3 != NULL) || + ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiSupportInstance->Facs3 != NULL) + ) { + gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages); + gBS->FreePool (CurrentTableList); + return EFI_ACCESS_DENIED; + } + // + // FACS is referenced by FADT and is not part of RSDT + // + AddToRsdt = FALSE; + + // + // Add the table to the appropriate table version + // + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { + // + // Save a pointer to the table + // + AcpiSupportInstance->Facs1 = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table; + + // + // If FADT already exists, update table pointers. + // + if (AcpiSupportInstance->Fadt1 != NULL) { + AcpiSupportInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs1; + + // + // Checksum FADT table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Fadt1, + AcpiSupportInstance->Fadt1->Header.Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + } + + if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || + (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { + // + // Save a pointer to the table + // + AcpiSupportInstance->Facs3 = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table; + + // + // If FADT already exists, update table pointers. + // + if (AcpiSupportInstance->Fadt3 != NULL) { + // + // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and + // vice-versa. + // + if ((UINT64)(UINTN)AcpiSupportInstance->Facs3 < BASE_4GB) { + AcpiSupportInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs3; + } else { + Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Facs3; + CopyMem ( + &AcpiSupportInstance->Fadt3->XFirmwareCtrl, + &Buffer64, + sizeof (UINT64) + ); + } + + // + // Checksum FADT table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Fadt3, + AcpiSupportInstance->Fadt3->Header.Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + } + + break; + + case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + // + // Check that the table has not been previously added. + // + if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Dsdt1 != NULL) || + ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiSupportInstance->Dsdt3 != NULL) || + ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiSupportInstance->Dsdt3 != NULL) + ) { + gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages); + gBS->FreePool (CurrentTableList); + return EFI_ACCESS_DENIED; + } + // + // DSDT is referenced by FADT and is not part of RSDT + // + AddToRsdt = FALSE; + + // + // Add the table to the appropriate table version + // + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { + // + // Save a pointer to the table + // + AcpiSupportInstance->Dsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table; + + // + // If FADT already exists, update table pointers. + // + if (AcpiSupportInstance->Fadt1 != NULL) { + AcpiSupportInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt1; + + // + // Checksum FADT table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Fadt1, + AcpiSupportInstance->Fadt1->Header.Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + } + + if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || + (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { + // + // Save a pointer to the table + // + AcpiSupportInstance->Dsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table; + + // + // If FADT already exists, update table pointers. + // + if (AcpiSupportInstance->Fadt3 != NULL) { + AcpiSupportInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt3; + Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Dsdt3; + CopyMem ( + &AcpiSupportInstance->Fadt3->XDsdt, + &Buffer64, + sizeof (UINT64) + ); + + // + // Checksum FADT table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Fadt3, + AcpiSupportInstance->Fadt3->Header.Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + } + // + // Checksum the table + // + if (Checksum) { + AcpiPlatformChecksum ( + CurrentTableList->Table, + CurrentTableList->Table->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + break; + + default: + // + // Checksum the table + // + if (Checksum) { + AcpiPlatformChecksum ( + CurrentTableList->Table, + CurrentTableList->Table->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + break; + } + // + // Add the table to the current list of tables + // + InsertTailList (&AcpiSupportInstance->TableList, &CurrentTableList->Link); + + // + // Add the table to RSDT and/or XSDT table entry lists. + // + // + // Add to ACPI 1.0b table tree + // + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { + if (AddToRsdt) { + // + // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer + // + if (AcpiSupportInstance->NumberOfTableEntries1 >= mEfiAcpiMaxNumTables) { + Status = ReallocateAcpiTableBuffer (AcpiSupportInstance); + ASSERT_EFI_ERROR (Status); + } + CurrentRsdtEntry = (UINT32 *) + ( + (UINT8 *) AcpiSupportInstance->Rsdt1 + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + + AcpiSupportInstance->NumberOfTableEntries1 * + sizeof (UINT32) + ); + + // + // Add entry to the RSDT unless its the FACS or DSDT + // + *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table; + + // + // Update RSDT length + // + AcpiSupportInstance->Rsdt1->Length = AcpiSupportInstance->Rsdt1->Length + sizeof (UINT32); + + AcpiSupportInstance->NumberOfTableEntries1++; + } + } + // + // Add to ACPI 2.0/3.0 table tree + // + if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { + if (AddToRsdt) { + // + // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer + // + if (AcpiSupportInstance->NumberOfTableEntries3 >= mEfiAcpiMaxNumTables) { + Status = ReallocateAcpiTableBuffer (AcpiSupportInstance); + ASSERT_EFI_ERROR (Status); + } + // + // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables. + // If it becomes necessary to maintain separate table lists, changes will be required. + // + CurrentRsdtEntry = (UINT32 *) + ( + (UINT8 *) AcpiSupportInstance->Rsdt3 + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + + AcpiSupportInstance->NumberOfTableEntries3 * + sizeof (UINT32) + ); + + // + // This pointer must not be directly dereferenced as the XSDT entries may not + // be 64 bit aligned resulting in a possible fault. Use CopyMem to update. + // + CurrentXsdtEntry = (VOID *) + ( + (UINT8 *) AcpiSupportInstance->Xsdt + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + + AcpiSupportInstance->NumberOfTableEntries3 * + sizeof (UINT64) + ); + + // + // Add entry to the RSDT + // + *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table; + + // + // Update RSDT length + // + AcpiSupportInstance->Rsdt3->Length = AcpiSupportInstance->Rsdt3->Length + sizeof (UINT32); + + // + // Add entry to XSDT, XSDT expects 64 bit pointers, but + // the table pointers in XSDT are not aligned on 8 byte boundary. + // + Buffer64 = (UINT64) (UINTN) CurrentTableList->Table; + CopyMem ( + CurrentXsdtEntry, + &Buffer64, + sizeof (UINT64) + ); + + // + // Update length + // + AcpiSupportInstance->Xsdt->Length = AcpiSupportInstance->Xsdt->Length + sizeof (UINT64); + + AcpiSupportInstance->NumberOfTableEntries3++; + } + } + + ChecksumCommonTables (AcpiSupportInstance); + return EFI_SUCCESS; +} +/** + This function finds the table specified by the handle and returns a pointer to it. + If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are + undefined. + + @param Handle Table to find. + @param TableList Table list to search + @param Table Pointer to table found. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND No table found matching the handle specified. + +**/ +EFI_STATUS +FindTableByHandle ( + IN UINTN Handle, + IN LIST_ENTRY *TableList, + OUT EFI_ACPI_TABLE_LIST **Table + ) +{ + LIST_ENTRY *CurrentLink; + EFI_ACPI_TABLE_LIST *CurrentTable; + + // + // Check for invalid input parameters + // + ASSERT (Table); + + // + // Find the table + // + CurrentLink = TableList->ForwardLink; + + while (CurrentLink != TableList) { + CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink); + if (CurrentTable->Handle == Handle) { + // + // Found handle, so return this table. + // + *Table = CurrentTable; + return EFI_SUCCESS; + } + + CurrentLink = CurrentLink->ForwardLink; + } + // + // Table not found + // + return EFI_NOT_FOUND; +} +/** + This function removes a basic table from the RSDT and/or XSDT. + For Acpi 1.0 tables, pass in the Rsdt. + For Acpi 2.0 tables, pass in both Rsdt and Xsdt. + + @param Table Pointer to table found. + @param NumberOfTableEntries Current number of table entries in the RSDT/XSDT + @param Rsdt Pointer to the RSDT to remove from + @param Xsdt Pointer to the Xsdt to remove from + + @return EFI_SUCCESS The function completed successfully. + @return EFI_INVALID_PARAMETER The table was not found in both Rsdt and Xsdt. + +**/ +EFI_STATUS +RemoveTableFromRsdt ( + IN OUT EFI_ACPI_TABLE_LIST * Table, + IN OUT UINTN *NumberOfTableEntries, + IN OUT EFI_ACPI_DESCRIPTION_HEADER * Rsdt, + IN OUT EFI_ACPI_DESCRIPTION_HEADER * Xsdt OPTIONAL + ) +{ + UINT32 *CurrentRsdtEntry; + VOID *CurrentXsdtEntry; + UINT64 CurrentTablePointer64; + UINTN TempIndex; + + // + // Check for invalid input parameters + // + ASSERT (Table); + ASSERT (NumberOfTableEntries); + ASSERT (Rsdt); + + // + // Find the table entry in the RSDT and XSDT + // + for (TempIndex = 0; TempIndex < *NumberOfTableEntries; TempIndex++) { + // + // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables. + // If it becomes necessary to maintain separate table lists, changes will be required. + // + CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + TempIndex * sizeof (UINT32)); + if (Xsdt != NULL) { + // + // This pointer must not be directly dereferenced as the XSDT entries may not + // be 64 bit aligned resulting in a possible fault. Use CopyMem to update. + // + CurrentXsdtEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + TempIndex * sizeof (UINT64)); + + // + // Read the entry value out of the XSDT + // + CopyMem (&CurrentTablePointer64, CurrentXsdtEntry, sizeof (UINT64)); + } else { + // + // Initialize to NULL + // + CurrentXsdtEntry = 0; + CurrentTablePointer64 = 0; + } + // + // Check if we have found the corresponding entry in both RSDT and XSDT + // + if (*CurrentRsdtEntry == (UINT32) (UINTN) Table->Table && + ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table) + ) { + // + // Found entry, so copy all following entries and shrink table + // We actually copy all + 1 to copy the initialized value of memory over + // the last entry. + // + CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - TempIndex) * sizeof (UINT32)); + Rsdt->Length = Rsdt->Length - sizeof (UINT32); + if (Xsdt != NULL) { + CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - TempIndex) * sizeof (UINT64)); + Xsdt->Length = Xsdt->Length - sizeof (UINT64); + } + break; + } else if (TempIndex + 1 == *NumberOfTableEntries) { + // + // At the last entry, and table not found + // + return EFI_INVALID_PARAMETER; + } + } + // + // Checksum the tables + // + AcpiPlatformChecksum ( + Rsdt, + Rsdt->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + + if (Xsdt != NULL) { + AcpiPlatformChecksum ( + Xsdt, + Xsdt->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + // + // Decrement the number of tables + // + (*NumberOfTableEntries)--; + + return EFI_SUCCESS; +} +/** + This function removes a table and frees any associated memory. + + @param AcpiSupportInstance Instance of the protocol. + @param Version Version(s) to delete. + @param Table Pointer to table found. + + @return EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +DeleteTable ( + IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, + IN EFI_ACPI_TABLE_VERSION Version, + IN OUT EFI_ACPI_TABLE_LIST *Table + ) +{ + UINT32 CurrentTableSignature; + BOOLEAN RemoveFromRsdt; + + // + // Check for invalid input parameters + // + ASSERT (AcpiSupportInstance); + ASSERT (Table); + + // + // Init locals + // + RemoveFromRsdt = TRUE; + + if (Table->Table != NULL) { + CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table->Table)->Signature; + + // + // Basic tasks to accomplish delete are: + // Determine removal requirements (in RSDT/XSDT or not) + // Remove entry from RSDT/XSDT + // Remove any table references to the table + // If no one is using the table + // Free the table (removing pointers from private data and tables) + // Remove from list + // Free list structure + // + // + // Determine if this table is in the RSDT or XSDT + // + if ((CurrentTableSignature == EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) || + (CurrentTableSignature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) || + (CurrentTableSignature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) + ) { + RemoveFromRsdt = FALSE; + } + // + // We don't remove the FADT in the standard way because some + // OS expect the FADT to be early in the table list. + // So we always put it as the first element in the list. + // + if (CurrentTableSignature == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { + RemoveFromRsdt = FALSE; + } + + // + // Remove the table from RSDT and XSDT + // + + // + // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt + // + if (Version & EFI_ACPI_TABLE_VERSION_NONE & Table->Version) { + // + // Remove this version from the table + // + Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_NONE; + } + + if (Version & EFI_ACPI_TABLE_VERSION_1_0B & Table->Version) { + // + // Remove this version from the table + // + Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_1_0B; + + // + // Remove from Rsdt. We don't care about the return value because it is + // acceptable for the table to not exist in Rsdt. + // We didn't add some tables so we don't remove them. + // + if (RemoveFromRsdt) { + RemoveTableFromRsdt ( + Table, + &AcpiSupportInstance->NumberOfTableEntries1, + AcpiSupportInstance->Rsdt1, + NULL + ); + } + } + + if ((Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) || + (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version)) { + // + // Remove this version from the table + // + if (Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) { + Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_2_0; + } + if (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version) { + Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_3_0; + } + + // + // Remove from Rsdt and Xsdt. We don't care about the return value + // because it is acceptable for the table to not exist in Rsdt/Xsdt. + // We didn't add some tables so we don't remove them. + // + if (RemoveFromRsdt) { + RemoveTableFromRsdt ( + Table, + &AcpiSupportInstance->NumberOfTableEntries3, + AcpiSupportInstance->Rsdt3, + AcpiSupportInstance->Xsdt + ); + } + } + // + // Free the table, clean up any dependent tables and our private data pointers. + // + switch (Table->Table->Signature) { + + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { + AcpiSupportInstance->Fadt1 = NULL; + } + + if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || + (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { + AcpiSupportInstance->Fadt3 = NULL; + } + break; + + case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE: + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { + AcpiSupportInstance->Facs1 = NULL; + + // + // Update FADT table pointers + // + if (AcpiSupportInstance->Fadt1 != NULL) { + AcpiSupportInstance->Fadt1->FirmwareCtrl = 0; + + // + // Checksum table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Fadt1, + AcpiSupportInstance->Fadt1->Header.Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + } + + if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || + (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { + AcpiSupportInstance->Facs3 = NULL; + + // + // Update FADT table pointers + // + if (AcpiSupportInstance->Fadt3 != NULL) { + AcpiSupportInstance->Fadt3->FirmwareCtrl = 0; + ZeroMem (&AcpiSupportInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64)); + + // + // Checksum table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Fadt3, + AcpiSupportInstance->Fadt3->Header.Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + } + break; + + case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { + AcpiSupportInstance->Dsdt1 = NULL; + + // + // Update FADT table pointers + // + if (AcpiSupportInstance->Fadt1 != NULL) { + AcpiSupportInstance->Fadt1->Dsdt = 0; + + // + // Checksum table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Fadt1, + AcpiSupportInstance->Fadt1->Header.Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + } + + + if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || + (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { + AcpiSupportInstance->Dsdt3 = NULL; + + // + // Update FADT table pointers + // + if (AcpiSupportInstance->Fadt3 != NULL) { + AcpiSupportInstance->Fadt3->Dsdt = 0; + ZeroMem (&AcpiSupportInstance->Fadt3->XDsdt, sizeof (UINT64)); + + // + // Checksum table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Fadt3, + AcpiSupportInstance->Fadt3->Header.Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + } + } + break; + + default: + // + // Do nothing + // + break; + } + } + // + // If no version is using this table anymore, remove and free list entry. + // + if (Table->Version == 0) { + // + // Free the Table + // + gBS->FreePages (Table->PageAddress, Table->NumberOfPages); + RemoveEntryList (&(Table->Link)); + gBS->FreePool (Table); + } + // + // Done + // + return EFI_SUCCESS; +} +/** + This function finds and removes the table specified by the handle. + + @param AcpiSupportInstance Instance of the protocol. + @param Version Bitmask of which versions to remove. + @param Handle Table to remove. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_ABORTED An error occurred. + @return EFI_NOT_FOUND Handle not found in table list. +**/ +EFI_STATUS +RemoveTableFromList ( + IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, + IN EFI_ACPI_TABLE_VERSION Version, + IN UINTN Handle + ) +{ + EFI_ACPI_TABLE_LIST *Table; + EFI_STATUS Status; + + Table = NULL; + + // + // Check for invalid input parameters + // + ASSERT (AcpiSupportInstance); + + // + // Find the table + // + Status = FindTableByHandle ( + Handle, + &AcpiSupportInstance->TableList, + &Table + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Remove the table + // + Status = DeleteTable (AcpiSupportInstance, Version, Table); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Completed successfully + // + return EFI_SUCCESS; +} +/** + This function calculates and updates an UINT8 checksum. + + @param Buffer Pointer to buffer to checksum + @param Size Number of bytes to checksum + @param ChecksumOffset Offset to place the checksum result in + + @return EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +AcpiPlatformChecksum ( + IN VOID *Buffer, + IN UINTN Size, + IN UINTN ChecksumOffset + ) +{ + UINT8 Sum; + UINT8 *Ptr; + + Sum = 0; + // + // Initialize pointer + // + Ptr = Buffer; + + // + // set checksum to 0 first + // + Ptr[ChecksumOffset] = 0; + + // + // add all content of buffer + // + while ((Size--) != 0) { + Sum = (UINT8) (Sum + (*Ptr++)); + } + // + // set checksum + // + Ptr = Buffer; + Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1); + + return EFI_SUCCESS; +} +/** + Checksum all versions of the common tables, RSDP, RSDT, XSDT. + + @param AcpiSupportInstance Protocol instance private data. + + @return EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +ChecksumCommonTables ( + IN OUT EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance + ) +{ + // + // RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Rsdp1, + sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER), + OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER, + Checksum) + ); + + // + // RSDP ACPI 1.0 checksum for 2.0/3.0 table. This is only the first 20 bytes of the structure + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Rsdp3, + sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER), + OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER, + Checksum) + ); + + // + // RSDP ACPI 2.0/3.0 checksum, this is the entire table + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Rsdp3, + sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER), + OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER, + ExtendedChecksum) + ); + + // + // RSDT checksums + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Rsdt1, + AcpiSupportInstance->Rsdt1->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + + AcpiPlatformChecksum ( + AcpiSupportInstance->Rsdt3, + AcpiSupportInstance->Rsdt3->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + + // + // XSDT checksum + // + AcpiPlatformChecksum ( + AcpiSupportInstance->Xsdt, + AcpiSupportInstance->Xsdt->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + + return EFI_SUCCESS; +} +/** + Constructor for the ACPI support protocol to initializes instance data. + + @param AcpiSupportInstance Instance to construct + + @retval EFI_SUCCESS Instance initialized. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +AcpiSupportAcpiSupportConstructor ( + IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance + ) +{ + EFI_STATUS Status; + UINT64 CurrentData; + UINTN TotalSize; + UINTN RsdpTableSize; + UINT8 *Pointer; + EFI_PHYSICAL_ADDRESS PageAddress; + + // + // Check for invalid input parameters + // + ASSERT (AcpiSupportInstance); + + InitializeListHead (&AcpiSupportInstance->TableList); + AcpiSupportInstance->CurrentHandle = 1; + AcpiSupportInstance->AcpiSupport.GetAcpiTable = GetAcpiTable; + AcpiSupportInstance->AcpiSupport.SetAcpiTable = SetAcpiTable; + AcpiSupportInstance->AcpiSupport.PublishTables = PublishTables; + + AcpiSupportInstance->AcpiTableProtocol.InstallAcpiTable = InstallAcpiTable; + AcpiSupportInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable; + + // + // Create RSDP table + // + RsdpTableSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) + + sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER); + + PageAddress = 0xFFFFFFFF; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIReclaimMemory, + EFI_SIZE_TO_PAGES (RsdpTableSize), + &PageAddress + ); + + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Pointer = (UINT8 *) (UINTN) PageAddress; + ZeroMem (Pointer, RsdpTableSize); + + AcpiSupportInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer; + Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER); + AcpiSupportInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer; + + // + // Create RSDT, XSDT structures + // + TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT + mEfiAcpiMaxNumTables * sizeof (UINT32) + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT + mEfiAcpiMaxNumTables * sizeof (UINT32) + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT + mEfiAcpiMaxNumTables * sizeof (UINT64); + + // + // Allocate memory in the lower 32 bit of address range for + // compatibility with ACPI 1.0 OS. + // + // This is done because ACPI 1.0 pointers are 32 bit values. + // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses. + // There is no architectural reason these should be below 4GB, it is purely + // for convenience of implementation that we force memory below 4GB. + // + PageAddress = 0xFFFFFFFF; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIReclaimMemory, + EFI_SIZE_TO_PAGES (TotalSize), + &PageAddress + ); + + if (EFI_ERROR (Status)) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiSupportInstance->Rsdp1, EFI_SIZE_TO_PAGES (RsdpTableSize)); + return EFI_OUT_OF_RESOURCES; + } + + Pointer = (UINT8 *) (UINTN) PageAddress; + ZeroMem (Pointer, TotalSize); + + AcpiSupportInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; + Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32)); + AcpiSupportInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; + Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32)); + AcpiSupportInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; + + // + // Initialize RSDP + // + CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE; + CopyMem (&AcpiSupportInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64)); + CopyMem (AcpiSupportInstance->Rsdp1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdp1->OemId)); + AcpiSupportInstance->Rsdp1->Reserved = EFI_ACPI_RESERVED_BYTE; + AcpiSupportInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt1; + + CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE; + CopyMem (&AcpiSupportInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64)); + CopyMem (AcpiSupportInstance->Rsdp3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdp3->OemId)); + AcpiSupportInstance->Rsdp3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION; + AcpiSupportInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt3; + AcpiSupportInstance->Rsdp3->Length = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER); + CurrentData = (UINT64) (UINTN) AcpiSupportInstance->Xsdt; + CopyMem (&AcpiSupportInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64)); + SetMem (AcpiSupportInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE); + + // + // Initialize Rsdt + // + // Note that we "reserve" one entry for the FADT so it can always be + // at the beginning of the list of tables. Some OS don't seem + // to find it correctly if it is too far down the list. + // + AcpiSupportInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE; + AcpiSupportInstance->Rsdt1->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER); + AcpiSupportInstance->Rsdt1->Revision = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION; + CopyMem (AcpiSupportInstance->Rsdt1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdt1->OemId)); + CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId); + CopyMem (&AcpiSupportInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64)); + AcpiSupportInstance->Rsdt1->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); + AcpiSupportInstance->Rsdt1->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); + AcpiSupportInstance->Rsdt1->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); + // + // We always reserve first one for FADT + // + AcpiSupportInstance->NumberOfTableEntries1 = 1; + AcpiSupportInstance->Rsdt1->Length = AcpiSupportInstance->Rsdt1->Length + sizeof(UINT32); + + AcpiSupportInstance->Rsdt3->Signature = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE; + AcpiSupportInstance->Rsdt3->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER); + AcpiSupportInstance->Rsdt3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION; + CopyMem (AcpiSupportInstance->Rsdt3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdt3->OemId)); + CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId); + CopyMem (&AcpiSupportInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64)); + AcpiSupportInstance->Rsdt3->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); + AcpiSupportInstance->Rsdt3->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); + AcpiSupportInstance->Rsdt3->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); + // + // We always reserve first one for FADT + // + AcpiSupportInstance->NumberOfTableEntries3 = 1; + AcpiSupportInstance->Rsdt3->Length = AcpiSupportInstance->Rsdt3->Length + sizeof(UINT32); + + // + // Initialize Xsdt + // + AcpiSupportInstance->Xsdt->Signature = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE; + AcpiSupportInstance->Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER); + AcpiSupportInstance->Xsdt->Revision = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION; + CopyMem (AcpiSupportInstance->Xsdt->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Xsdt->OemId)); + CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId); + CopyMem (&AcpiSupportInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64)); + AcpiSupportInstance->Xsdt->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); + AcpiSupportInstance->Xsdt->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); + AcpiSupportInstance->Xsdt->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); + // + // We always reserve first one for FADT + // + AcpiSupportInstance->Xsdt->Length = AcpiSupportInstance->Xsdt->Length + sizeof(UINT64); + + ChecksumCommonTables (AcpiSupportInstance); + + // + // Completed successfully + // + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf new file mode 100644 index 0000000000..32ca4f648f --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf @@ -0,0 +1,81 @@ +## @file +# Acpi Support Dirver to install Framework Acpi Support Protocol. +# +# This driver initializes ACPI support protocol instance data structure and intstall +# ACPI support protocol to provide Get, Set and Publish Table services. +# +# 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 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 = AcpiSupportDxe + MODULE_UNI_FILE = AcpiSupportDxe.uni + FILE_GUID = 506533a6-e626-4500-b14f-17939c0e5b60 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InstallAcpiSupport + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + AcpiSupportAcpiSupportProtocol.c + AcpiSupport.h + AcpiSupport.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + UefiDriverEntryPoint + BaseMemoryLib + UefiLib + DebugLib + BaseLib + PcdLib + + +[Guids] + gEfiAcpi10TableGuid ## PRODUCES ## SystemTable + gEfiAcpiTableGuid ## PRODUCES ## SystemTable + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdInstallAcpiSupportProtocol ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES + +[Protocols] + gEfiAcpiTableProtocolGuid ## PRODUCES + gEfiAcpiSupportProtocolGuid ## SOMETIMES_PRODUCES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + AcpiSupportDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.uni b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.uni new file mode 100644 index 0000000000..7916f6b9a2 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni new file mode 100644 index 0000000000..13539ce1be Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h new file mode 100644 index 0000000000..93bafd2dd8 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h @@ -0,0 +1,237 @@ +/** @file + Head file for BDS Architectural Protocol implementation + +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 +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 _BDS_MODULE_H_ +#define _BDS_MODULE_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 +#include +#include + +#include +#include + +#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() + +/** + + Show progress bar with title above it. It only works in Graphics mode. + + @param TitleForeground Foreground color for Title. + @param TitleBackground Background color for Title. + @param Title Title above progress bar. + @param ProgressColor Progress bar color. + @param Progress Progress (0-100) + @param PreviousValue The previous value of the progress. + + @retval EFI_STATUS Success update the progress bar + +**/ +EFI_STATUS +PlatformBdsShowProgress ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, + IN CHAR16 *Title, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, + IN UINTN Progress, + IN UINTN PreviousValue + ); + +// +// Prototypes +// + +/** + + Install Boot Device Selection Protocol + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCEESS BDS has finished initializing. + Return the dispatcher and recall BDS.Entry + @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface + +**/ +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + + Service routine for BdsInstance->Entry(). Devices are connected, the + consoles are initialized, and the boot options are tried. + + @param This Protocol Instance structure. + +**/ +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ); + + +/** + Perform the memory test base on the memory test intensive level, + and update the memory resource. + + @param Level The memory test intensive level. + + @retval EFI_STATUS Success test all the system memory and update + the memory resource + +**/ +EFI_STATUS +EFIAPI +BdsMemoryTest ( + IN EXTENDMEM_COVERAGE_LEVEL Level + ); + +/** + + This routine is called to see if there are any capsules we need to process. + If the boot mode is not UPDATE, then we do nothing. Otherwise find the + capsule HOBS and produce firmware volumes for them via the DXE service. + Then call the dispatcher to dispatch drivers from them. Finally, check + the status of the updates. + + This function should be called by BDS in case we need to do some + sort of processing even if there is no capsule to process. We + need to do this if an earlier update went away and we need to + clear the capsule variable so on the next reset PEI does not see it and + think there is a capsule available. + + @param BootMode the current boot mode + + @retval EFI_INVALID_PARAMETER boot mode is not correct for an update + @retval EFI_SUCCESS There is no error when processing capsule + +**/ +EFI_STATUS +EFIAPI +BdsProcessCapsules ( + EFI_BOOT_MODE BootMode + ); + +/** + Set the variable and report the error through status code upon failure. + + @param VariableName A Null-terminated string that is the name of the vendor's variable. + Each VariableName is unique for each VendorGuid. VariableName must + contain 1 or more characters. If VariableName is an empty string, + then EFI_INVALID_PARAMETER is returned. + @param VendorGuid A unique identifier for the vendor. + @param Attributes Attributes bitmask to set for the variable. + @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero + causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is + set, then a SetVariable() call with a DataSize of zero will not cause any change to + the variable value (the timestamp associated with the variable may be updated however + even if no new data value is provided,see the description of the + EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not + be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). + @param Data The contents for the variable. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as + defined by the Attributes. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the + DataSize exceeds the maximum allowed. + @retval EFI_INVALID_PARAMETER VariableName is an empty string. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + @retval EFI_WRITE_PROTECTED The variable in question is read-only. + @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. + @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS + or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo + does NOT pass the validation check carried out by the firmware. + + @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. +**/ +EFI_STATUS +BdsDxeSetVariableAndReportStatusCodeOnError ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf new file mode 100644 index 0000000000..6afb8a09df --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf @@ -0,0 +1,228 @@ +## @file +# BDSDxe module is core driver for BDS phase. +# +# When DxeCore dispatching all DXE driver, this module will produce architecture protocol +# gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry +# interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered. +# +# Generally, this module take reposiblity to connect all necessary devices for platform boot, +# these boot device path are hold in PlatformBdsLib library instance produced by platform. +# For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is select. +# For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI, +# EFI\BOOT\BOOTIA64.EFI file from selected boot device and transfer control to boot loader. +# +# BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, Device Manager" which +# is used for user to configure boot option or maintain hardware device. +# +# Copyright (c) 2008 - 2015, Intel 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 = BdsDxe + MODULE_UNI_FILE = BdsDxe.uni + FILE_GUID = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = BdsInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + FrontPage.h + Language.h + Bds.h + Hotkey.h + BootMaint/BBSsupport.h + BootMngr/BootManager.h + BootMaint/BootMaint.h + String.h + BootMaint/FormGuid.h + HwErrRecSupport.c + HwErrRecSupport.h + + DeviceMngr/DeviceManager.h + DeviceMngr/DeviceManagerVfr.h + DeviceMngr/DeviceManagerVfr.Vfr + DeviceMngr/DriverHealthVfr.Vfr + DeviceMngr/DeviceManagerStrings.uni + DeviceMngr/DeviceManager.c + BootMngr/BootManagerVfr.Vfr + BootMngr/BootManagerStrings.uni + BootMngr/BootManager.c + BootMaint/FE.vfr + BootMaint/FileExplorer.c + BootMaint/BootMaint.c + BootMaint/BBSsupport.c + BootMaint/UpdatePage.c + BootMaint/Variable.c + BootMaint/Data.c + BootMaint/ConsoleOption.c + BootMaint/BootOption.c + BootMaint/BmLib.c + BootMaint/Bm.vfr + BootMaint/Bmstring.uni + Hotkey.c + MemoryTest.c + Capsules.c + Strings.uni + String.c + Language.c + FrontPageVfr.Vfr + FrontPageStrings.uni + FrontPage.c + BdsEntry.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + DevicePathLib + BaseLib + HobLib + UefiRuntimeServicesTableLib + GenericBdsLib + ReportStatusCodeLib + PerformanceLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + PrintLib + HiiLib + UefiDriverEntryPoint + PlatformBdsLib + CapsuleLib + PcdLib + UefiHiiServicesLib + +[Guids] + ## SOMETIMES_PRODUCES ## Variable:L"BootXXXX" # Boot option variable + ## SOMETIMES_PRODUCES ## Variable:L"DriverXXXX" # Driver load option. + ## SOMETIMES_PRODUCES ## Variable:L"PlatformLang" # Platform supported languange in Rfc4646 format + ## SOMETIMES_PRODUCES ## Variable:L"Lang" # Platform supported languange in Iso639 format + ## SOMETIMES_PRODUCES ## Variable:L"LangCodes" # Value of PcdUefiVariableDefaultLangCodes + ## PRODUCES ## Variable:L"PlatformLangCodes" # Value of PcdUefiVariableDefaultPlatformLangCodes + ## SOMETIMES_PRODUCES ## Variable:L"KeyXXXX" # Hotkey option variable + ## PRODUCES ## Variable:L"HwErrRecSupport" # The level of platform supported hardware Error Record Persistence + ## PRODUCES ## Variable:L"Timeout" # The time out value in second of showing progress bar + ## SOMETIMES_PRODUCES ## Variable:L"BootOptionSupport" # The feature supported in boot option menu, value could be: EFI_BOOT_OPTION_SUPPORT_KEY, EFI_BOOT_OPTION_SUPPORT_APP + ## SOMETIMES_PRODUCES ## Variable:L"BootOrder" # The boot option array + ## SOMETIMES_PRODUCES ## Variable:L"DriverOrder" # The driver order list + ## SOMETIMES_CONSUMES ## Variable:L"ConIn" # The device path of console in device + ## SOMETIMES_PRODUCES ## Variable:L"ConIn" # The device path of console in device + ## SOMETIMES_CONSUMES ## Variable:L"ConOut" # The device path of console out device + ## SOMETIMES_PRODUCES ## Variable:L"ConOut" # The device path of console out device + ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" # The device path of error out device + ## SOMETIMES_PRODUCES ## Variable:L"ErrOut" # The device path of error out device + ## SOMETIMES_CONSUMES ## Variable:L"ConInDev" # The device path of console in device + ## SOMETIMES_CONSUMES ## Variable:L"ConOutDev" # The device path of console out device + ## SOMETIMES_CONSUMES ## Variable:L"ErrOutDev" # The device path of error out device + ## SOMETIMES_PRODUCES ## Variable:L"BootNext" # The number of next boot option + gEfiGlobalVariableGuid + gEfiFileSystemVolumeLabelInfoIdGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the information type is volume + gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the information type is file + gEfiHiiPlatformSetupFormsetGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the formset class guid to be displayed + gEfiIfrTianoGuid ## SOMETIMES_PRODUCES ## UNDEFINED # Extended IFR Guid Opcode + gEfiHiiDriverHealthFormsetGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the Driver Health formset class guid to be displayed + ## SOMETIMES_PRODUCES ## Variable:L"LegacyDevOrder" + ## SOMETIMES_CONSUMES ## Variable:L"LegacyDevOrder" + gEfiLegacyDevOrderVariableGuid + gFrontPageFormSetGuid ## SOMETIMES_CONSUMES ## HII # FrontPage HII Package + gBootMaintFormSetGuid ## SOMETIMES_CONSUMES ## HII # BootMaint HII Package + gFileExploreFormSetGuid ## SOMETIMES_CONSUMES ## HII # FileExplore HII Package + gBootManagerFormSetGuid ## SOMETIMES_CONSUMES ## HII # BootManager HII Package + gDeviceManagerFormSetGuid ## SOMETIMES_CONSUMES ## HII # DeviceManager HII Package + gDriverHealthFormSetGuid ## SOMETIMES_CONSUMES ## HII # DriverHealth HII Package + ## SOMETIMES_PRODUCES ## Event + ## SOMETIMES_CONSUMES ## Event + gConnectConInEventGuid + gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID # FMP Capsule + gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID + gEfiUartDevicePathGuid ## SOMETIMES_CONSUMES ## GUID (Identify the device path for UARD device) + +[Protocols] + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadFileProtocolGuid ## SOMETIMES_CONSUMES + gEfiBdsArchProtocolGuid ## PRODUCES + gEfiSmbiosProtocolGuid ## CONSUMES + gEfiGenericMemTestProtocolGuid ## SOMETIMES_CONSUMES + gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES + gEfiUgaDrawProtocolGuid |gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES + ## CONSUMES + ## NOTIFY + gEfiSimpleTextInputExProtocolGuid + gEfiHiiConfigAccessProtocolGuid ## SOMETIMES_PRODUCES + gEfiFormBrowser2ProtocolGuid ## CONSUMES + gEfiSerialIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiDevicePathProtocolGuid ## CONSUMES + gEfiDriverHealthProtocolGuid ## SOMETIMES_CONSUMES + gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES + gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootlogoOnlyEnable ## CONSUMES + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang ## SOMETIMES_CONSUMES + ## CONSUMES + ## PRODUCES + gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn ## PRODUCES + ## SOMETIMES_CONSUMES + ## SOMETIMES_PRODUCES + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + ## CONSUMES + ## PRODUCES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand ## SOMETIMES_CONSUMES + ## CONSUMES + ## SOMETIMES_PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn + ## CONSUMES + ## SOMETIMES_PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## CONSUMES + +[Depex] + TRUE + +# +# [BootMode] +# FLASH_UPDATE ## SOMETIMES_CONSUMES # Update Capsule Image +# + +[UserExtensions.TianoCore."ExtraFiles"] + BdsDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.uni b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.uni new file mode 100644 index 0000000000..a120733895 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxeExtra.uni new file mode 100644 index 0000000000..9aee074abe Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c new file mode 100644 index 0000000000..ae7ad2153c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c @@ -0,0 +1,754 @@ +/** @file + This module produce main entry for BDS phase - BdsEntry. + When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed + which contains interface of BdsEntry. + After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked + to enter BDS phase. + +Copyright (c) 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 +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 "Bds.h" +#include "Language.h" +#include "FrontPage.h" +#include "Hotkey.h" +#include "HwErrRecSupport.h" + +/// +/// BDS arch protocol instance initial value. +/// +/// Note: Current BDS not directly get the BootMode, DefaultBoot, +/// TimeoutDefault, MemoryTestLevel value from the BDS arch protocol. +/// Please refer to the library useage of BdsLibGetBootMode, BdsLibGetTimeout +/// and PlatformBdsDiagnostics in BdsPlatform.c +/// +EFI_HANDLE gBdsHandle = NULL; + +EFI_BDS_ARCH_PROTOCOL gBds = { + BdsEntry +}; + +UINT16 *mBootNext = NULL; + +/// +/// The read-only variables defined in UEFI Spec. +/// +CHAR16 *mReadOnlyVariables[] = { + L"PlatformLangCodes", + L"LangCodes", + L"BootOptionSupport", + L"HwErrRecSupport", + L"OsIndicationsSupported" + }; + +/** + + Install Boot Device Selection Protocol + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCEESS BDS has finished initializing. + Return the dispatcher and recall BDS.Entry + @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface + +**/ +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install protocol interface + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gBdsHandle, + &gEfiBdsArchProtocolGuid, &gBds, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + + +/** + 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 +BdsEmptyCallbackFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + +/** + + This function attempts to boot for the boot order specified + by platform policy. + +**/ +VOID +BdsBootDeviceSelect ( + VOID + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + BDS_COMMON_OPTION *BootOption; + UINTN ExitDataSize; + CHAR16 *ExitData; + UINT16 Timeout; + LIST_ENTRY BootLists; + CHAR16 Buffer[20]; + BOOLEAN BootNextExist; + LIST_ENTRY *LinkBootNext; + EFI_EVENT ConnectConInEvent; + + // + // Got the latest boot option + // + BootNextExist = FALSE; + LinkBootNext = NULL; + ConnectConInEvent = NULL; + InitializeListHead (&BootLists); + + // + // First check the boot next option + // + ZeroMem (Buffer, sizeof (Buffer)); + + // + // Create Event to signal ConIn connection request + // + if (PcdGetBool (PcdConInConnectOnDemand)) { + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + BdsEmptyCallbackFunction, + NULL, + &gConnectConInEventGuid, + &ConnectConInEvent + ); + if (EFI_ERROR(Status)) { + ConnectConInEvent = NULL; + } + } + + if (mBootNext != NULL) { + // + // Indicate we have the boot next variable, so this time + // boot will always have this boot option + // + BootNextExist = TRUE; + + // + // Clear the this variable so it's only exist in this time boot + // + Status = gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + // + // Add the boot next boot option + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext); + BootOption = BdsLibVariableToOption (&BootLists, Buffer); + + // + // If fail to get boot option from variable, just return and do nothing. + // + if (BootOption == NULL) { + return; + } + + BootOption->BootCurrent = *mBootNext; + } + // + // Parse the boot order to get boot option + // + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + + // + // When we didn't have chance to build boot option variables in the first + // full configuration boot (e.g.: Reset in the first page or in Device Manager), + // we have no boot options in the following mini configuration boot. + // Give the last chance to enumerate the boot options. + // + if (IsListEmpty (&BootLists)) { + BdsLibEnumerateAllBootOption (&BootLists); + } + + Link = BootLists.ForwardLink; + + // + // Parameter check, make sure the loop will be valid + // + if (Link == NULL) { + return ; + } + // + // Here we make the boot in a loop, every boot success will + // return to the front page + // + for (;;) { + // + // Check the boot option list first + // + if (Link == &BootLists) { + // + // When LazyConIn enabled, signal connect ConIn event before enter UI + // + if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) { + gBS->SignalEvent (ConnectConInEvent); + } + + // + // There are two ways to enter here: + // 1. There is no active boot option, give user chance to + // add new boot option + // 2. All the active boot option processed, and there is no + // one is success to boot, then we back here to allow user + // add new active boot option + // + Timeout = 0xffff; + PlatformBdsEnterFrontPage (Timeout, FALSE); + InitializeListHead (&BootLists); + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + Link = BootLists.ForwardLink; + continue; + } + // + // Get the boot option from the link list + // + BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + // + // According to EFI Specification, if a load option is not marked + // as LOAD_OPTION_ACTIVE, the boot manager will not automatically + // load the option. + // + if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { + // + // skip the header of the link list, because it has no boot option + // + Link = Link->ForwardLink; + continue; + } + // + // Make sure the boot option device path connected, + // but ignore the BBS device path + // + if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { + // + // Notes: the internal shell can not been connected with device path + // so we do not check the status here + // + BdsLibConnectDevicePath (BootOption->DevicePath); + } + + // + // Restore to original mode before launching boot option. + // + BdsSetConsoleMode (FALSE); + + // + // All the driver options should have been processed since + // now boot will be performed. + // + Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); + if (Status != EFI_SUCCESS) { + // + // Call platform action to indicate the boot fail + // + BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); + PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize); + + // + // Check the next boot option + // + Link = Link->ForwardLink; + + } else { + // + // Call platform action to indicate the boot success + // + BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); + PlatformBdsBootSuccess (BootOption); + + // + // Boot success, then stop process the boot order, and + // present the boot manager menu, front page + // + + // + // When LazyConIn enabled, signal connect ConIn Event before enter UI + // + if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) { + gBS->SignalEvent (ConnectConInEvent); + } + + Timeout = 0xffff; + PlatformBdsEnterFrontPage (Timeout, FALSE); + + // + // Rescan the boot option list, avoid potential risk of the boot + // option change in front page + // + if (BootNextExist) { + LinkBootNext = BootLists.ForwardLink; + } + + InitializeListHead (&BootLists); + if (LinkBootNext != NULL) { + // + // Reserve the boot next option + // + InsertTailList (&BootLists, LinkBootNext); + } + + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + Link = BootLists.ForwardLink; + } + } + +} + +/** + + Validate input console variable data. + + If found the device path is not a valid device path, remove the variable. + + @param VariableName Input console variable name. + +**/ +VOID +BdsFormalizeConsoleVariable ( + IN CHAR16 *VariableName + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN VariableSize; + EFI_STATUS Status; + + DevicePath = BdsLibGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &VariableSize + ); + if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) { + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } +} + +/** + + Formalize Bds global variables. + + 1. For ConIn/ConOut/ConErr, if found the device path is not a valid device path, remove the variable. + 2. For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps + 3. Delete OsIndications variable if it is not NV/BS/RT UINT64 + Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable. + +**/ +VOID +BdsFormalizeEfiGlobalVariable ( + VOID + ) +{ + EFI_STATUS Status; + UINT64 OsIndicationSupport; + UINT64 OsIndication; + UINTN DataSize; + UINT32 Attributes; + + // + // Validate Console variable. + // + BdsFormalizeConsoleVariable (L"ConIn"); + BdsFormalizeConsoleVariable (L"ConOut"); + BdsFormalizeConsoleVariable (L"ErrOut"); + + // + // OS indicater support variable + // + OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI \ + | EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED; + + BdsDxeSetVariableAndReportStatusCodeOnError ( + L"OsIndicationsSupported", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(UINT64), + &OsIndicationSupport + ); + + // + // If OsIndications is invalid, remove it. + // Invalid case + // 1. Data size != UINT64 + // 2. OsIndication value inconsistence + // 3. OsIndication attribute inconsistence + // + OsIndication = 0; + Attributes = 0; + DataSize = sizeof(UINT64); + Status = gRT->GetVariable ( + L"OsIndications", + &gEfiGlobalVariableGuid, + &Attributes, + &DataSize, + &OsIndication + ); + + if (!EFI_ERROR(Status)) { + if (DataSize != sizeof(UINT64) || + (OsIndication & ~OsIndicationSupport) != 0 || + Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE)){ + + DEBUG ((EFI_D_ERROR, "Unformalized OsIndications variable exists. Delete it\n")); + Status = gRT->SetVariable ( + L"OsIndications", + &gEfiGlobalVariableGuid, + 0, + 0, + NULL + ); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } + } + +} + +/** + + Allocate a block of memory that will contain performance data to OS. + +**/ +VOID +BdsAllocateMemoryForPerformanceData ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; + + AcpiLowMemoryBase = 0x0FFFFFFFFULL; + + // + // Allocate a block of memory that will contain performance data to OS. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH), + &AcpiLowMemoryBase + ); + if (!EFI_ERROR (Status)) { + // + // Save the pointer to variable for use in S3 resume. + // + BdsDxeSetVariableAndReportStatusCodeOnError ( + L"PerfDataMemAddr", + &gPerformanceProtocolGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (EFI_PHYSICAL_ADDRESS), + &AcpiLowMemoryBase + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase)); + } + // + // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists + // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code. + // + Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); + if (!EFI_ERROR (Status)) { + Status = VariableLock->RequestToLock (VariableLock, L"PerfDataMemAddr", &gPerformanceProtocolGuid); + ASSERT_EFI_ERROR (Status); + } + } +} + +/** + + Service routine for BdsInstance->Entry(). Devices are connected, the + consoles are initialized, and the boot options are tried. + + @param This Protocol Instance structure. + +**/ +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ) +{ + LIST_ENTRY DriverOptionList; + LIST_ENTRY BootOptionList; + UINTN BootNextSize; + CHAR16 *FirmwareVendor; + EFI_STATUS Status; + UINT16 BootTimeOut; + UINTN Index; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; + + // + // Insert the performance probe + // + PERF_END (NULL, "DXE", NULL, 0); + PERF_START (NULL, "BDS", NULL, 0); + + PERF_CODE ( + BdsAllocateMemoryForPerformanceData (); + ); + + // + // Initialize the global system boot option and driver option + // + InitializeListHead (&DriverOptionList); + InitializeListHead (&BootOptionList); + + // + // Initialize hotkey service + // + InitializeHotkeyService (); + + // + // Fill in FirmwareVendor and FirmwareRevision from PCDs + // + FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor); + gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor); + ASSERT (gST->FirmwareVendor != NULL); + gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision); + + // + // Fixup Tasble CRC after we updated Firmware Vendor and Revision + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ((VOID *)gST, sizeof(EFI_SYSTEM_TABLE), &gST->Hdr.CRC32); + + // + // Validate Variable. + // + BdsFormalizeEfiGlobalVariable(); + + // + // Mark the read-only variables if the Variable Lock protocol exists + // + Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); + DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status)); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < sizeof (mReadOnlyVariables) / sizeof (mReadOnlyVariables[0]); Index++) { + Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Report Status Code to indicate connecting drivers will happen + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS) + ); + + InitializeHwErrRecSupport(); + + // + // Initialize L"Timeout" EFI global variable. + // + BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); + if (BootTimeOut != 0xFFFF) { + // + // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification + // define same behavior between no value or 0xFFFF value for L"Timeout". + // + BdsDxeSetVariableAndReportStatusCodeOnError ( + L"Timeout", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &BootTimeOut + ); + } + + // + // bugbug: platform specific code + // Initialize the platform specific string and language + // + InitializeStringSupport (); + InitializeLanguage (TRUE); + InitializeFrontPage (TRUE); + + // + // Do the platform init, can be customized by OEM/IBV + // + PERF_START (NULL, "PlatformBds", "BDS", 0); + PlatformBdsInit (); + + // + // Set up the device list based on EFI 1.1 variables + // process Driver#### and Load the driver's in the + // driver option list + // + BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder"); + if (!IsListEmpty (&DriverOptionList)) { + BdsLibLoadDrivers (&DriverOptionList); + } + // + // Check if we have the boot next option + // + mBootNext = BdsLibGetVariableAndSize ( + L"BootNext", + &gEfiGlobalVariableGuid, + &BootNextSize + ); + + // + // Setup some platform policy here + // + PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList, BdsProcessCapsules, BdsMemoryTest); + PERF_END (NULL, "PlatformBds", "BDS", 0); + + // + // BDS select the boot device to load OS + // + BdsBootDeviceSelect (); + + // + // Only assert here since this is the right behavior, we should never + // return back to DxeCore. + // + ASSERT (FALSE); + + return ; +} + + +/** + Set the variable and report the error through status code upon failure. + + @param VariableName A Null-terminated string that is the name of the vendor's variable. + Each VariableName is unique for each VendorGuid. VariableName must + contain 1 or more characters. If VariableName is an empty string, + then EFI_INVALID_PARAMETER is returned. + @param VendorGuid A unique identifier for the vendor. + @param Attributes Attributes bitmask to set for the variable. + @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero + causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is + set, then a SetVariable() call with a DataSize of zero will not cause any change to + the variable value (the timestamp associated with the variable may be updated however + even if no new data value is provided,see the description of the + EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not + be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). + @param Data The contents for the variable. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as + defined by the Attributes. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the + DataSize exceeds the maximum allowed. + @retval EFI_INVALID_PARAMETER VariableName is an empty string. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + @retval EFI_WRITE_PROTECTED The variable in question is read-only. + @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. + @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS + or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo + does NOT pass the validation check carried out by the firmware. + + @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. +**/ +EFI_STATUS +BdsDxeSetVariableAndReportStatusCodeOnError ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + EFI_STATUS Status; + EDKII_SET_VARIABLE_STATUS *SetVariableStatus; + UINTN NameSize; + + Status = gRT->SetVariable ( + VariableName, + VendorGuid, + Attributes, + DataSize, + Data + ); + if (EFI_ERROR (Status)) { + NameSize = StrSize (VariableName); + SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize); + if (SetVariableStatus != NULL) { + CopyGuid (&SetVariableStatus->Guid, VendorGuid); + SetVariableStatus->NameSize = NameSize; + SetVariableStatus->DataSize = DataSize; + SetVariableStatus->SetStatus = Status; + SetVariableStatus->Attributes = Attributes; + CopyMem (SetVariableStatus + 1, VariableName, NameSize); + CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data, DataSize); + + REPORT_STATUS_CODE_EX ( + EFI_ERROR_CODE, + PcdGet32 (PcdErrorCodeSetVariable), + 0, + NULL, + &gEdkiiStatusCodeDataTypeVariableGuid, + SetVariableStatus, + sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize + ); + + FreePool (SetVariableStatus); + } + } + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c new file mode 100644 index 0000000000..6a0b525f15 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c @@ -0,0 +1,254 @@ +/** @file + This function deal with the legacy boot option, it create, delete + and manage the legacy boot option, all legacy boot option is getting from + the legacy BBS table. + +Copyright (c) 2004 - 2015, Intel 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 "BBSsupport.h" + +#pragma pack(1) +typedef struct { + BBS_TABLE BbsEntry; + UINT16 BbsIndex; +} LEGACY_BOOT_OPTION_BBS_DATA; +#pragma pack() + +/** + Re-order the Boot Option according to the DevOrder. + + The routine re-orders the Boot Option in BootOption array according to + the order specified by DevOrder. + + @param DevOrder Pointer to buffer containing the BBS Index, + high 8-bit value 0xFF indicating a disabled boot option + @param DevOrderCount Count of the BBS Index + @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers + @param EnBootOptionCount Count of the enabled Boot Option Numbers + @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers + @param DisBootOptionCount Count of the disabled Boot Option Numbers +**/ +VOID +OrderLegacyBootOption4SameType ( + UINT16 *DevOrder, + UINTN DevOrderCount, + UINT16 **EnBootOption, + UINTN *EnBootOptionCount, + UINT16 **DisBootOption, + UINTN *DisBootOptionCount + ) +{ + EFI_STATUS Status; + UINT16 *NewBootOption; + UINT16 *BootOrder; + UINTN BootOrderSize; + UINTN Index; + UINTN StartPosition; + + BDS_COMMON_OPTION *BootOption; + + CHAR16 OptionName[sizeof ("Boot####")]; + UINT16 *BbsIndexArray; + UINT16 *DeviceTypeArray; + LIST_ENTRY List; + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + ASSERT (BootOrder != NULL); + + BbsIndexArray = AllocatePool (BootOrderSize); + DeviceTypeArray = AllocatePool (BootOrderSize); + *EnBootOption = AllocatePool (BootOrderSize); + *DisBootOption = AllocatePool (BootOrderSize); + *DisBootOptionCount = 0; + *EnBootOptionCount = 0; + Index = 0; + + ASSERT (BbsIndexArray != NULL); + ASSERT (DeviceTypeArray != NULL); + ASSERT (*EnBootOption != NULL); + ASSERT (*DisBootOption != NULL); + + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); + InitializeListHead (&List); + BootOption = BdsLibVariableToOption (&List, OptionName); + ASSERT (BootOption != NULL); + + if ((DevicePathType (BootOption->DevicePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (BootOption->DevicePath) == BBS_BBS_DP)) { + // + // Legacy Boot Option + // + ASSERT (BootOption->LoadOptionsSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); + + DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType; + BbsIndexArray [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption->LoadOptions)->BbsIndex; + } else { + DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN; + BbsIndexArray [Index] = 0xFFFF; + } + FreePool (BootOption->DevicePath); + FreePool (BootOption->Description); + FreePool (BootOption->LoadOptions); + FreePool (BootOption); + } + + // + // Record the corresponding Boot Option Numbers according to the DevOrder + // Record the EnBootOption and DisBootOption according to the DevOrder + // + StartPosition = BootOrderSize / sizeof (UINT16); + NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16)); + ASSERT (NewBootOption != NULL); + while (DevOrderCount-- != 0) { + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) { + StartPosition = MIN (StartPosition, Index); + NewBootOption[DevOrderCount] = BootOrder[Index]; + + if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) { + (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index]; + (*DisBootOptionCount)++; + } else { + (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index]; + (*EnBootOptionCount)++; + } + break; + } + } + } + + // + // Overwrite the old BootOption + // + CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16)); + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + // + // Changing content without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + FreePool (NewBootOption); + FreePool (DeviceTypeArray); + FreePool (BbsIndexArray); + FreePool (BootOrder); +} + +/** + Group the legacy boot options in the BootOption. + + The routine assumes the boot options in the beginning that covers all the device + types are ordered properly and re-position the following boot options just after + the corresponding boot options with the same device type. + For example: + 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0] + Assuming [Harddisk1 CdRom2 Efi1] is ordered properly + Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0] + + 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2] + Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly + Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2] + +**/ +VOID +GroupMultipleLegacyBootOption4SameType ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN DeviceIndex; + UINTN DeviceTypeIndex[7]; + UINTN *NextIndex; + UINT16 OptionNumber; + UINT16 *BootOrder; + UINTN BootOrderSize; + CHAR16 OptionName[sizeof ("Boot####")]; + BDS_COMMON_OPTION *BootOption; + LIST_ENTRY List; + + SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xff); + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); + InitializeListHead (&List); + BootOption = BdsLibVariableToOption (&List, OptionName); + ASSERT (BootOption != NULL); + + if ((DevicePathType (BootOption->DevicePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (BootOption->DevicePath) == BBS_BBS_DP)) { + // + // Legacy Boot Option + // + ASSERT ((((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType & 0xF) < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0])); + NextIndex = &DeviceTypeIndex[((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType & 0xF]; + + if (*NextIndex == (UINTN) -1) { + // + // *NextIndex is the Index in BootOrder to put the next Option Number for the same type + // + *NextIndex = Index + 1; + } else { + // + // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position + // + OptionNumber = BootOrder[Index]; + CopyMem (&BootOrder[*NextIndex + 1], &BootOrder[*NextIndex], (Index - *NextIndex) * sizeof (UINT16)); + BootOrder[*NextIndex] = OptionNumber; + + // + // Update the DeviceTypeIndex array to reflect the right shift operation + // + for (DeviceIndex = 0; DeviceIndex < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]); DeviceIndex++) { + if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) { + DeviceTypeIndex[DeviceIndex]++; + } + } + } + } + FreePool (BootOption->DevicePath); + FreePool (BootOption->Description); + FreePool (BootOption->LoadOptions); + FreePool (BootOption); + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + // + // Changing content without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + FreePool (BootOrder); +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h new file mode 100644 index 0000000000..e73dc85995 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h @@ -0,0 +1,82 @@ +/** @file + declares interface functions + +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. + +**/ + +#ifndef _EFI_BDS_BBS_SUPPORT_H_ +#define _EFI_BDS_BBS_SUPPORT_H_ + +#include "BootMaint.h" + +/** + Build Legacy Device Name String according. + + @param CurBBSEntry BBS Table. + @param Index Index. + @param BufSize The buffer size. + @param BootString The output string. + + @return VOID No output. + +**/ +VOID +BdsBuildLegacyDevNameString ( + IN BBS_TABLE *CurBBSEntry, + IN UINTN Index, + IN UINTN BufSize, + OUT CHAR16 *BootString + ); + +/** + Group the legacy boot options in the BootOption. + + The routine assumes the boot options in the beginning that covers all the device + types are ordered properly and re-position the following boot options just after + the corresponding boot options with the same device type. + For example: + 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0] + Assuming [Harddisk1 CdRom2 Efi1] is ordered properly + Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0] + + 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2] + Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly + Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2] +**/ +VOID +GroupMultipleLegacyBootOption4SameType ( + VOID + ); + +/** + Re-order the Boot Option according to the DevOrder. + + The routine re-orders the Boot Option in BootOption array according to + the order specified by DevOrder. + + @param DevOrder Pointer to buffer containing the BBS Index, + high 8-bit value 0xFF indicating a disabled boot option + @param DevOrderCount Count of the BBS Index + @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers + @param EnBootOptionCount Count of the enabled Boot Option Numbers + @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers + @param DisBootOptionCount Count of the disabled Boot Option Numbers +**/ +VOID +OrderLegacyBootOption4SameType ( + UINT16 *DevOrder, + UINTN DevOrderCount, + UINT16 **EnBootOption, + UINTN *EnBootOptionCount, + UINT16 **DisBootOption, + UINTN *DisBootOptionCount + ); +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr new file mode 100644 index 0000000000..0d35c2c37e --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr @@ -0,0 +1,365 @@ +///** @file +// +// Boot Maintenance Utility Formset +// +// Copyright (c) 2004 - 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 "FormGuid.h" + +formset + guid = BOOT_MAINT_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_MAIN_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = BOOT_MAINT_FORMSET_GUID, + + varstore BMM_FAKE_NV_DATA, + varid = VARSTORE_ID_BOOT_MAINT, + name = BmmData, + guid = BOOT_MAINT_FORMSET_GUID; + + form formid = FORM_MAIN_ID, + title = STRING_TOKEN(STR_FORM_MAIN_TITLE); + + goto FORM_BOOT_SETUP_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_SETUP_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_DRIVER_SETUP_ID, + prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE), + help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP), + flags = INTERACTIVE, + key = FORM_DRIVER_SETUP_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_CON_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE), + help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP), + flags = INTERACTIVE, + key = FORM_CON_MAIN_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_BOOT_FROM_FILE_ID, + prompt = STRING_TOKEN(STR_BOOT_FROM_FILE), + help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP), + flags = INTERACTIVE, + key = KEY_VALUE_BOOT_FROM_FILE; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + +// label FORM_MAIN_ID; + + goto FORM_BOOT_NEXT_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_NEXT_ID; + + goto FORM_TIME_OUT_ID, + prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE), + help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP), + flags = INTERACTIVE, + key = FORM_TIME_OUT_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + text + help = STRING_TOKEN(STR_RESET), + text = STRING_TOKEN(STR_RESET), + flags = INTERACTIVE, + key = FORM_RESET; + + endform; + + form formid = FORM_BOOT_SETUP_ID, + title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN); + //flags = INTERACTIVE, + //key = FORM_MAIN_ID; + + goto FORM_BOOT_ADD_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_ADD_ID; + + goto FORM_BOOT_DEL_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_DEL_ID; + + goto FORM_BOOT_CHG_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_CHG_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + // + // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive" + // here dynamically + // + label FORM_BOOT_LEGACY_DEVICE_ID; + label LABEL_END; + + endform; + + form formid = FORM_DRIVER_SETUP_ID, + title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN); + //help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + //flags = INTERACTIVE, + //key = FORM_MAIN_ID; + + goto FORM_DRV_ADD_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP), + flags = INTERACTIVE, + key = FORM_DRV_ADD_ID; + + goto FORM_DRV_DEL_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_DRV_DEL_ID; + + goto FORM_DRV_CHG_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_DRV_CHG_ID; + endform; + + form formid = FORM_BOOT_DEL_ID, + title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE); + + label FORM_BOOT_DEL_ID; + label LABEL_END; + endform; + + form formid = FORM_BOOT_CHG_ID, + title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE); + + label FORM_BOOT_CHG_ID; + label LABEL_END; + + endform; + + form formid = FORM_BOOT_NEXT_ID, + title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE); + + label FORM_BOOT_NEXT_ID; + label LABEL_END; + endform; + + form formid = FORM_TIME_OUT_ID, + title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE); + + label FORM_TIME_OUT_ID; + label LABEL_END; + endform; + + form formid = FORM_DRV_ADD_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN); + //flags = INTERACTIVE, + //key = FORM_MAIN_ID; + + goto FORM_DRV_ADD_FILE_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), + flags = INTERACTIVE, + key = FORM_DRV_ADD_FILE_ID; + + endform; + + form formid = FORM_DRV_DEL_ID, + title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE); + + label FORM_DRV_DEL_ID; + label LABEL_END; + + endform; + + form formid = FORM_DRV_CHG_ID, + title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE); + + label FORM_DRV_CHG_ID; + label LABEL_END; + + endform; + + form formid = FORM_CON_MAIN_ID, + title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN); + //flags = INTERACTIVE, + //key = FORM_MAIN_ID; + + goto FORM_CON_IN_ID, + prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE), + help = STRING_TOKEN(STR_FORM_CON_IN_HELP), + flags = INTERACTIVE, + key = FORM_CON_IN_ID; + + goto FORM_CON_OUT_ID, + prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE), + help = STRING_TOKEN(STR_FORM_CON_OUT_HELP), + flags = INTERACTIVE, + key = FORM_CON_OUT_ID; + + goto FORM_CON_ERR_ID, + prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE), + help = STRING_TOKEN(STR_FORM_STD_ERR_HELP), + flags = INTERACTIVE, + key = FORM_CON_ERR_ID; + + goto FORM_CON_MODE_ID, + prompt = STRING_TOKEN(STR_FORM_MODE_TITLE), + help = STRING_TOKEN(STR_FORM_MODE_HELP), + flags = INTERACTIVE, + key = FORM_CON_MODE_ID; + + goto FORM_CON_COM_ID, + prompt = STRING_TOKEN(STR_FORM_COM_TITLE), + help = STRING_TOKEN(STR_FORM_COM_HELP), + flags = INTERACTIVE, + key = FORM_CON_COM_ID; + endform; + + form formid = FORM_CON_MODE_ID, + title = STRING_TOKEN(STR_FORM_MODE_TITLE); + + label FORM_CON_MODE_ID; + label LABEL_END; + endform; + + form formid = FORM_CON_COM_ID, + title = STRING_TOKEN(STR_FORM_COM_TITLE); + + label FORM_CON_COM_ID; + label LABEL_END; + endform; + + form formid = FORM_CON_COM_SETUP_ID, + title = STRING_TOKEN(STR_CON_COM_SETUP); + + label FORM_CON_COM_SETUP_ID; + label LABEL_END; + endform; + + form formid = FORM_FILE_SEEK_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_FILE_SEEK_ID; + label LABEL_END; + endform; + + form formid = FORM_FILE_NEW_SEEK_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_FILE_NEW_SEEK_ID; + label LABEL_END; + endform; + + form formid = FORM_DRV_ADD_HANDLE_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE); + + label FORM_DRV_ADD_HANDLE_ID; + label LABEL_END; + endform; + + form formid = FORM_DRV_ADD_HANDLE_DESC_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); + + label FORM_DRV_ADD_HANDLE_DESC_ID; + label LABEL_END; + + endform; + + form formid = FORM_CON_IN_ID, + title = STRING_TOKEN(STR_FORM_CON_IN_TITLE); + + label FORM_CON_IN_ID; + label LABEL_END; + + endform; + + form formid = FORM_CON_OUT_ID, + title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE); + + label FORM_CON_OUT_ID; + label LABEL_END; + + endform; + + form formid = FORM_CON_ERR_ID, + title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE); + + label FORM_CON_ERR_ID; + label LABEL_END; + + endform; + + form formid = FORM_SET_FD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE); + + label FORM_SET_FD_ORDER_ID; + label LABEL_END; + endform; + + form formid = FORM_SET_HD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE); + + label FORM_SET_HD_ORDER_ID; + label LABEL_END; + endform; + + form formid = FORM_SET_CD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE); + + label FORM_SET_CD_ORDER_ID; + label LABEL_END; + endform; + + form formid = FORM_SET_NET_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE); + + label FORM_SET_NET_ORDER_ID; + label LABEL_END; + endform; + + form formid = FORM_SET_BEV_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE); + + label FORM_SET_BEV_ORDER_ID; + label LABEL_END; + endform; + +endformset; diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c new file mode 100644 index 0000000000..4424831859 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c @@ -0,0 +1,411 @@ +/** @file + Utility routines used by boot maintenance modules. + +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 +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 "BootMaint.h" + +/** + + Function opens and returns a file handle to the root directory of a volume. + + @param DeviceHandle A handle for a device + + @return A valid file handle or NULL is returned + +**/ +EFI_FILE_HANDLE +EfiLibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_FILE_HANDLE File; + + File = NULL; + + // + // File the file system interface to the device + // + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID *) &Volume + ); + + // + // Open the root directory of the volume + // + if (!EFI_ERROR (Status)) { + Status = Volume->OpenVolume ( + Volume, + &File + ); + } + // + // Done + // + return EFI_ERROR (Status) ? NULL : File; +} + +/** + + Helper function called as part of the code needed + to allocate the proper sized buffer for various + EFI interfaces. + + + @param Status Current status + @param Buffer Current allocated buffer, or NULL + @param BufferSize Current buffer size needed + + @retval TRUE if the buffer was reallocated and the caller + should try the API again. + @retval FALSE The caller should not call this function again. + +**/ +BOOLEAN +EfiGrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +{ + BOOLEAN TryAgain; + + // + // If this is an initial request, buffer will be null with a new buffer size + // + if ((*Buffer == NULL) && (BufferSize != 0)) { + *Status = EFI_BUFFER_TOO_SMALL; + } + // + // If the status code is "buffer too small", resize the buffer + // + TryAgain = FALSE; + if (*Status == EFI_BUFFER_TOO_SMALL) { + + if (*Buffer != NULL) { + FreePool (*Buffer); + } + + *Buffer = AllocateZeroPool (BufferSize); + + if (*Buffer != NULL) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + // + // If there's an error, free the buffer + // + if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) { + FreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + +/** + Function returns the value of the specified variable. + + + @param Name A Null-terminated Unicode string that is + the name of the vendor's variable. + @param VendorGuid A unique identifier for the vendor. + + @return The payload of the variable. + @retval NULL If the variable can't be read. + +**/ +VOID * +EfiLibGetVariable ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid + ) +{ + UINTN VarSize; + + return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize); +} + +/** + Function deletes the variable specified by VarName and VarGuid. + + @param VarName A Null-terminated Unicode string that is + the name of the vendor's variable. + + @param VarGuid A unique identifier for the vendor. + + @retval EFI_SUCCESS The variable was found and removed + @retval EFI_UNSUPPORTED The variable store was inaccessible + @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available + @retval EFI_NOT_FOUND The variable was not found + +**/ +EFI_STATUS +EfiLibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ) +{ + VOID *VarBuf; + EFI_STATUS Status; + + VarBuf = EfiLibGetVariable (VarName, VarGuid); + Status = EFI_NOT_FOUND; + + if (VarBuf != NULL) { + // + // Delete variable from Storage + // + Status = gRT->SetVariable ( + VarName, + VarGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + FreePool (VarBuf); + } + + return Status; +} + +/** + + Function gets the file system information from an open file descriptor, + and stores it in a buffer allocated from pool. + + + @param FHand The file handle. + + @return A pointer to a buffer with file information. + @retval NULL is returned if failed to get Vaolume Label Info. + +**/ +EFI_FILE_SYSTEM_VOLUME_LABEL * +EfiLibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_VOLUME_LABEL *Buffer; + UINTN BufferSize; + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200; + + // + // Call the real function + // + while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileSystemVolumeLabelInfoIdGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +/** + Duplicate a string. + + @param Src The source. + + @return A new string which is duplicated copy of the source. + @retval NULL If there is not enough memory. + +**/ +CHAR16 * +EfiStrDuplicate ( + IN CHAR16 *Src + ) +{ + CHAR16 *Dest; + UINTN Size; + + Size = StrSize (Src); + Dest = AllocateZeroPool (Size); + ASSERT (Dest != NULL); + if (Dest != NULL) { + CopyMem (Dest, Src, Size); + } + + return Dest; +} + +/** + + Function gets the file information from an open file descriptor, and stores it + in a buffer allocated from pool. + + @param FHand File Handle. + + @return A pointer to a buffer with file information or NULL is returned + +**/ +EFI_FILE_INFO * +EfiLibFileInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + + // + // Call the real function + // + while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileInfoGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +/** + Function is used to determine the number of device path instances + that exist in a device path. + + + @param DevicePath A pointer to a device path data structure. + + @return This function counts and returns the number of device path instances + in DevicePath. + +**/ +UINTN +EfiDevicePathInstanceCount ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + UINTN Count; + UINTN Size; + + Count = 0; + while (GetNextDevicePathInstance (&DevicePath, &Size) != NULL) { + Count += 1; + } + + return Count; +} + +/** + Adjusts the size of a previously allocated buffer. + + + @param OldPool - A pointer to the buffer whose size is being adjusted. + @param OldSize - The size of the current buffer. + @param NewSize - The size of the new buffer. + + @return The newly allocated buffer. + @retval NULL Allocation failed. + +**/ +VOID * +EfiReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ) +{ + VOID *NewPool; + + NewPool = NULL; + if (NewSize != 0) { + NewPool = AllocateZeroPool (NewSize); + } + + if (OldPool != NULL) { + if (NewPool != NULL) { + CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); + } + + FreePool (OldPool); + } + + return NewPool; +} + +/** + Get a string from the Data Hub record based on + a device path. + + @param DevPath The device Path. + + @return A string located from the Data Hub records based on + the device path. + @retval NULL If failed to get the String from Data Hub. + +**/ +UINT16 * +EfiLibStrFromDatahub ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + return NULL; +} + +/** + + Find the first instance of this Protocol + in the system and return it's interface. + + + @param ProtocolGuid Provides the protocol to search for + @param Interface On return, a pointer to the first interface + that matches ProtocolGuid + + @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found + @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid + +**/ +EFI_STATUS +EfiLibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + ProtocolGuid, + NULL, + (VOID **) Interface + ); + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni new file mode 100644 index 0000000000..b0aabc3b11 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c new file mode 100644 index 0000000000..d4b4475f09 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c @@ -0,0 +1,1690 @@ +/** @file + The functions for Boot Maintainence Main menu. + +Copyright (c) 2004 - 2015, Intel 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 "BootMaint.h" +#include "FormGuid.h" +#include "Bds.h" +#include "FrontPage.h" + +EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = { + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + BOOT_MAINT_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +HII_VENDOR_DEVICE_PATH mFeHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + FILE_EXPLORE_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +CHAR16 mBootMaintStorageName[] = L"BmmData"; +CHAR16 mFileExplorerStorageName[] = L"FeData"; +BMM_CALLBACK_DATA *mBmmCallbackInfo = NULL; + +/** + Init all memu. + + @param CallbackData The BMM context data. + +**/ +VOID +InitAllMenu ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Free up all Menu Option list. + +**/ +VOID +FreeAllMenu ( + VOID + ); + +/** + Initialize all of BMM configuration data in BmmFakeNvData and BmmOldFakeNVData member + in BMM context data and create all of dynamic OP code for BMM. + + @param CallbackData The BMM context data. + +**/ +VOID +InitializeBmmConfig ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + + ASSERT (CallbackData != NULL); + + // + // Initialize data which located in BMM main page + // + CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber); + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewLoadContext->IsBootNext) { + CallbackData->BmmFakeNvData.BootNext = Index; + break; + } + } + + CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); + + // + // Initialize data which located in Boot Options Menu + // + GetBootOrder (CallbackData); + GetLegacyDeviceOrder (CallbackData); + + // + // Initialize data which located in Driver Options Menu + // + GetDriverOrder (CallbackData); + + // + // Initialize data which located in Console Options Menu + // + GetConsoleOutMode (CallbackData); + GetConsoleInCheck (CallbackData); + GetConsoleOutCheck (CallbackData); + GetConsoleErrCheck (CallbackData); + GetTerminalAttribute (CallbackData); + + // + // Backup Initialize BMM configuartion data to BmmOldFakeNVData + // + CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA)); +} + +/** + Create string tokens for a menu from its help strings and display strings + + @param CallbackData The BMM context data. + @param HiiHandle Hii Handle of the package to be updated. + @param MenuOption The Menu whose string tokens need to be created + + @retval EFI_SUCCESS String tokens created successfully + @retval others contain some errors +**/ +EFI_STATUS +CreateMenuStringToken ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN BM_MENU_OPTION *MenuOption + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); + + NewMenuEntry->DisplayStringToken = HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->DisplayString, + NULL + ); + + if (NULL == NewMenuEntry->HelpString) { + NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; + } else { + NewMenuEntry->HelpStringToken = HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->HelpString, + NULL + ); + } + } + + return EFI_SUCCESS; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +BootMaintExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + BMM_CALLBACK_DATA *Private; + EFI_STRING ConfigRequestHdr; + EFI_STRING ConfigRequest; + BOOLEAN AllocatedRequest; + UINTN Size; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Request; + if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gBootMaintFormSetGuid, mBootMaintStorageName)) { + return EFI_NOT_FOUND; + } + + ConfigRequestHdr = NULL; + ConfigRequest = NULL; + AllocatedRequest = FALSE; + Size = 0; + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + // + // Convert buffer data to by helper function BlockToConfig() + // + BufferSize = sizeof (BMM_FAKE_NV_DATA); + 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 (&gBootMaintFormSetGuid, mBootMaintStorageName, Private->BmmDriverHandle); + Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); + ConfigRequest = AllocateZeroPool (Size); + ASSERT (ConfigRequest != NULL); + AllocatedRequest = TRUE; + UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); + FreePool (ConfigRequestHdr); + } + + Status = gHiiConfigRouting->BlockToConfig ( + gHiiConfigRouting, + ConfigRequest, + (UINT8 *) &Private->BmmFakeNvData, + BufferSize, + 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 applies changes in a driver's configuration. + Input is a Configuration, which has the routing data for this + driver followed by name / value configuration pairs. The driver + must apply those pairs to its configurable storage. If the + driver's configuration is stored in a linear block of data + and the driver's name / value pairs are in + format, it may use the ConfigToBlock helper function (above) to + simplify the job. Currently not implemented. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Configuration A null-terminated Unicode string in + format. + @param[out] Progress A pointer to a string filled in with the + offset of the most recent '&' before the + first failing name / value pair (or the + beginn ing 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 have been distributed or are + awaiting distribution. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + @retval EFI_INVALID_PARAMETERS Passing in a NULL for the + Results parameter would result + in this type of error. + @retval EFI_NOT_FOUND Target for the specified routing data + was not found. +**/ +EFI_STATUS +EFIAPI +BootMaintRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; + BMM_FAKE_NV_DATA *NewBmmData; + BMM_FAKE_NV_DATA *OldBmmData; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + BOOLEAN TerminalAttChange; + BMM_CALLBACK_DATA *Private; + + if (Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Configuration; + + if (Configuration == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check routing data in . + // Note: there is no name for Name/Value storage, only GUID will be checked + // + if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName)) { + return EFI_NOT_FOUND; + } + + Status = gBS->LocateProtocol ( + &gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID**) &ConfigRouting + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + // + // Get Buffer Storage data from EFI variable + // + BufferSize = sizeof (BMM_FAKE_NV_DATA); + OldBmmData = &Private->BmmOldFakeNVData; + NewBmmData = &Private->BmmFakeNvData; + // + // Convert to buffer data by helper function ConfigToBlock() + // + Status = ConfigRouting->ConfigToBlock ( + ConfigRouting, + Configuration, + (UINT8 *) NewBmmData, + &BufferSize, + Progress + ); + ASSERT_EFI_ERROR (Status); + // + // Compare new and old BMM configuration data and only do action for modified item to + // avoid setting unnecessary non-volatile variable + // + + // + // Check data which located in BMM main page and save the settings if need + // + if (CompareMem (NewBmmData->LegacyFD, OldBmmData->LegacyFD, sizeof (NewBmmData->LegacyFD)) != 0) { + Var_UpdateBBSOption (Private, FORM_SET_FD_ORDER_ID); + } + + if (CompareMem (NewBmmData->LegacyHD, OldBmmData->LegacyHD, sizeof (NewBmmData->LegacyHD)) != 0) { + Var_UpdateBBSOption (Private, FORM_SET_HD_ORDER_ID); + } + + if (CompareMem (NewBmmData->LegacyCD, OldBmmData->LegacyCD, sizeof (NewBmmData->LegacyCD)) != 0) { + Var_UpdateBBSOption (Private, FORM_SET_CD_ORDER_ID); + } + + if (CompareMem (NewBmmData->LegacyNET, OldBmmData->LegacyNET, sizeof (NewBmmData->LegacyNET)) != 0) { + Var_UpdateBBSOption (Private, FORM_SET_NET_ORDER_ID); + } + + if (CompareMem (NewBmmData->LegacyBEV, OldBmmData->LegacyBEV, sizeof (NewBmmData->LegacyBEV)) != 0) { + Var_UpdateBBSOption (Private, FORM_SET_BEV_ORDER_ID); + } + + // + // Change for "delete boot option" page need update NewBmmData->BootOptionOrder, so process + // NewBmmData->BootOptionOrder before NewBmmData->BootOptionDel + // + if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) { + Status = Var_UpdateBootOrder (Private); + } + + // + // Change for "delete driver option" page need update NewBmmData->DriverOptionOrder, so process + // NewBmmData->DriverOptionOrder before NewBmmData->DriverOptionDel + // + if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) { + Status = Var_UpdateDriverOrder (Private); + } + + // + // Check data which located in Boot Options Menu and save the settings if need + // + if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) { + for (Index = 0; + ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); + Index ++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index]; + NewBmmData->BootOptionDel[Index] = FALSE; + NewBmmData->BootOptionDelMark[Index] = FALSE; + } + + Var_DelBootOption (); + } + + // + // Check data which located in Driver Options Menu and save the settings if need + // + if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) { + for (Index = 0; + ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); + Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index]; + NewBmmData->DriverOptionDel[Index] = FALSE; + NewBmmData->DriverOptionDelMark[Index] = FALSE; + } + Var_DelDriverOption (); + } + + if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0) { + Status = gRT->SetVariable ( + L"Timeout", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &(NewBmmData->BootTimeOut) + ); + ASSERT_EFI_ERROR(Status); + + // + // Bugbug: code not exit in UiApp but in IntelFrameworkModulePkg, need do more check. + // + Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut; + } + + if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) { + Status = Var_UpdateBootNext (Private); + } + + if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0) { + Var_UpdateConMode (Private); + } + + TerminalAttChange = FALSE; + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + + // + // only need update modified items + // + if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 && + CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 && + CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 && + CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 && + CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 && + CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) { + continue; + } + + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + ASSERT (NewMenuEntry != NULL); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index]; + ASSERT (NewBmmData->COMBaudRate[Index] < (sizeof (BaudRateList) / sizeof (BaudRateList[0]))); + NewTerminalContext->BaudRate = BaudRateList[NewBmmData->COMBaudRate[Index]].Value; + NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index]; + ASSERT (NewBmmData->COMDataRate[Index] < (sizeof (DataBitsList) / sizeof (DataBitsList[0]))); + NewTerminalContext->DataBits = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value; + NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index]; + ASSERT (NewBmmData->COMStopBits[Index] < (sizeof (StopBitsList) / sizeof (StopBitsList[0]))); + NewTerminalContext->StopBits = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value; + NewTerminalContext->ParityIndex = NewBmmData->COMParity[Index]; + ASSERT (NewBmmData->COMParity[Index] < (sizeof (ParityList) / sizeof (ParityList[0]))); + NewTerminalContext->Parity = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value; + NewTerminalContext->TerminalType = NewBmmData->COMTerminalType[Index]; + NewTerminalContext->FlowControl = NewBmmData->COMFlowControl[Index]; + ChangeTerminalDevicePath ( + &(NewTerminalContext->DevicePath), + FALSE + ); + TerminalAttChange = TRUE; + } + if (TerminalAttChange) { + Var_UpdateConsoleInpOption (); + Var_UpdateConsoleOutOption (); + Var_UpdateErrorOutOption (); + } + + // + // Check data which located in Console Options Menu and save the settings if need + // + if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0) { + for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index < MAX_MENU_NUMBER); + NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index]; + } + + Var_UpdateConsoleInpOption (); + } + + if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0) { + for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index < MAX_MENU_NUMBER); + NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index]; + } + + Var_UpdateConsoleOutOption (); + } + + if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0) { + for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index < MAX_MENU_NUMBER); + NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index]; + } + + Var_UpdateErrorOutOption (); + } + + // + // After user do the save action, need to update OldBmmData. + // + CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA)); + + return EFI_SUCCESS; +} + +/** + Create GoTo OP code into FORM_BOOT_LEGACY_DEVICE label for legacy boot option. + +**/ +EFI_STATUS +InitializeLegacyBootOption ( + VOID + ) +{ + RefreshUpdateData (); + mStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID; + + // + // If LegacyBios Protocol is installed, add 3 tags about legacy boot option + // in BootOption form: legacy FD/HD/CD/NET/BEV + // + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_SET_FD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), + EFI_IFR_FLAG_CALLBACK, + FORM_SET_FD_ORDER_ID + ); + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_SET_HD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), + EFI_IFR_FLAG_CALLBACK, + FORM_SET_HD_ORDER_ID + ); + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_SET_CD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), + EFI_IFR_FLAG_CALLBACK, + FORM_SET_CD_ORDER_ID + ); + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_SET_NET_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), + EFI_IFR_FLAG_CALLBACK, + FORM_SET_NET_ORDER_ID + ); + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_SET_BEV_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), + EFI_IFR_FLAG_CALLBACK, + FORM_SET_BEV_ORDER_ID + ); + + HiiUpdateForm ( + mBmmCallbackInfo->BmmHiiHandle, + &gBootMaintFormSetGuid, + FORM_BOOT_SETUP_ID, + mStartOpCodeHandle, // Label FORM_BOOT_LEGACY_DEVICE_ID + mEndOpCodeHandle // LABEL_END + ); + + return EFI_SUCCESS; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. +**/ +EFI_STATUS +EFIAPI +BootMaintCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + BMM_CALLBACK_DATA *Private; + BM_MENU_ENTRY *NewMenuEntry; + BMM_FAKE_NV_DATA *CurrentFakeNVMap; + EFI_STATUS Status; + UINTN OldValue; + UINTN NewValue; + UINTN Number; + UINTN Pos; + UINTN Bit; + UINT16 NewValuePos; + UINT16 Index3; + UINT16 Index2; + UINT16 Index; + UINT8 *OldLegacyDev; + UINT8 *NewLegacyDev; + UINT8 *DisMap; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + if (Action == EFI_BROWSER_ACTION_FORM_OPEN && QuestionId == FORM_BOOT_SETUP_ID) { + // + // Initilize Form for legacy boot option. + // + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios); + if (!EFI_ERROR (Status)) { + InitializeLegacyBootOption (); + } + + return EFI_SUCCESS; + } + + if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { + // + // All other action return unsupported. + // + return EFI_UNSUPPORTED; + } + + Status = EFI_SUCCESS; + OldValue = 0; + NewValue = 0; + Number = 0; + OldLegacyDev = NULL; + NewLegacyDev = NULL; + NewValuePos = 0; + DisMap = NULL; + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + // + // Retrive uncommitted data from Form Browser + // + CurrentFakeNVMap = &Private->BmmFakeNvData; + HiiGetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); + if (Action == EFI_BROWSER_ACTION_CHANGING) { + if (Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + UpdatePageId (Private, QuestionId); + + if (QuestionId < FILE_OPTION_OFFSET) { + if (QuestionId < CONFIG_OPTION_OFFSET) { + switch (QuestionId) { + case KEY_VALUE_BOOT_FROM_FILE: + Private->FeCurrentState = FileExplorerStateBootFromFile; + break; + + case FORM_BOOT_ADD_ID: + Private->FeCurrentState = FileExplorerStateAddBootOption; + break; + + case FORM_DRV_ADD_FILE_ID: + Private->FeCurrentState = FileExplorerStateAddDriverOptionState; + break; + + case FORM_DRV_ADD_HANDLE_ID: + CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); + UpdateDrvAddHandlePage (Private); + break; + + case FORM_BOOT_DEL_ID: + CleanUpPage (FORM_BOOT_DEL_ID, Private); + UpdateBootDelPage (Private); + break; + + case FORM_BOOT_CHG_ID: + case FORM_DRV_CHG_ID: + UpdatePageBody (QuestionId, Private); + break; + + case FORM_DRV_DEL_ID: + CleanUpPage (FORM_DRV_DEL_ID, Private); + UpdateDrvDelPage (Private); + break; + + case FORM_BOOT_NEXT_ID: + CleanUpPage (FORM_BOOT_NEXT_ID, Private); + UpdateBootNextPage (Private); + break; + + case FORM_TIME_OUT_ID: + CleanUpPage (FORM_TIME_OUT_ID, Private); + UpdateTimeOutPage (Private); + break; + + case FORM_CON_IN_ID: + case FORM_CON_OUT_ID: + case FORM_CON_ERR_ID: + UpdatePageBody (QuestionId, Private); + break; + + case FORM_CON_MODE_ID: + CleanUpPage (FORM_CON_MODE_ID, Private); + UpdateConModePage (Private); + break; + + case FORM_CON_COM_ID: + CleanUpPage (FORM_CON_COM_ID, Private); + UpdateConCOMPage (Private); + break; + + case FORM_SET_FD_ORDER_ID: + case FORM_SET_HD_ORDER_ID: + case FORM_SET_CD_ORDER_ID: + case FORM_SET_NET_ORDER_ID: + case FORM_SET_BEV_ORDER_ID: + CleanUpPage (QuestionId, Private); + UpdateSetLegacyDeviceOrderPage (QuestionId, Private); + break; + + default: + break; + } + } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { + Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); + Private->CurrentTerminal = Index2; + + CleanUpPage (FORM_CON_COM_SETUP_ID, Private); + UpdateTerminalPage (Private); + + } else if (QuestionId >= HANDLE_OPTION_OFFSET) { + Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); + + NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2); + ASSERT (NewMenuEntry != NULL); + Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; + + CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); + + Private->MenuEntry = NewMenuEntry; + Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; + + UpdateDriverAddHandleDescPage (Private); + } + } + } else if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { + if (Value->b){ + // + // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu. + // + CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE; + } else { + // + // Means user remove the old check status. + // + CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE; + } + } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { + if (Value->b){ + CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE; + } else { + CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE; + } + } else if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) { + // + // Update Select FD/HD/CD/NET/BEV Order Form + // + + DisMap = Private->BmmOldFakeNVData.DisableMap; + + if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyFDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD; + NewLegacyDev = CurrentFakeNVMap->LegacyFD; + } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyHDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD; + NewLegacyDev = CurrentFakeNVMap->LegacyHD; + } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyCDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD; + NewLegacyDev = CurrentFakeNVMap->LegacyCD; + } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyNETMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET; + NewLegacyDev = CurrentFakeNVMap->LegacyNET; + } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { + Number = (UINT16) LegacyBEVMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV; + NewLegacyDev = CurrentFakeNVMap->LegacyBEV; + } + // + // First, find the different position + // if there is change, it should be only one + // + for (Index = 0; Index < Number; Index++) { + if (OldLegacyDev[Index] != NewLegacyDev[Index]) { + OldValue = OldLegacyDev[Index]; + NewValue = NewLegacyDev[Index]; + break; + } + } + + if (Index != Number) { + // + // there is change, now process + // + if (0xFF == NewValue) { + // + // This item will be disable + // Just move the items behind this forward to overlap it + // + Pos = OldValue / 8; + Bit = 7 - (OldValue % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + for (Index2 = Index; Index2 < Number - 1; Index2++) { + NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1]; + } + + NewLegacyDev[Index2] = 0xFF; + } else { + for (Index2 = 0; Index2 < Number; Index2++) { + if (Index2 == Index) { + continue; + } + + if (OldLegacyDev[Index2] == NewValue) { + // + // If NewValue is in OldLegacyDev array + // remember its old position + // + NewValuePos = Index2; + break; + } + } + + if (Index2 != Number) { + // + // We will change current item to an existing item + // (It's hard to describe here, please read code, it's like a cycle-moving) + // + for (Index2 = NewValuePos; Index2 != Index;) { + if (NewValuePos < Index) { + NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1]; + Index2++; + } else { + NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1]; + Index2--; + } + } + } else { + // + // If NewValue is not in OldlegacyDev array, we are changing to a disabled item + // so we should modify DisMap to reflect the change + // + Pos = NewValue / 8; + Bit = 7 - (NewValue % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); + if (0xFF != OldValue) { + // + // Because NewValue is a item that was disabled before + // so after changing the OldValue should be disabled + // actually we are doing a swap of enable-disable states of two items + // + Pos = OldValue / 8; + Bit = 7 - (OldValue % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + } + } + } + // + // To prevent DISABLE appears in the middle of the list + // we should perform a re-ordering + // + Index3 = Index; + Index = 0; + while (Index < Number) { + if (0xFF != NewLegacyDev[Index]) { + Index++; + continue; + } + + Index2 = Index; + Index2++; + while (Index2 < Number) { + if (0xFF != NewLegacyDev[Index2]) { + break; + } + + Index2++; + } + + if (Index2 < Number) { + NewLegacyDev[Index] = NewLegacyDev[Index2]; + NewLegacyDev[Index2] = 0xFF; + } + + Index++; + } + + // + // Return correct question value. + // + Value->u8 = NewLegacyDev[Index3]; + } + } else { + switch (QuestionId) { + case KEY_VALUE_SAVE_AND_EXIT: + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; + break; + + case KEY_VALUE_NO_SAVE_AND_EXIT: + // + // Restore local maintain data. + // + DiscardChangeHandler (Private, CurrentFakeNVMap); + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; + break; + + case FORM_RESET: + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + return EFI_UNSUPPORTED; + + default: + break; + } + } + } + + // + // Pass changed uncommitted data back to Form Browser + // + HiiSetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); + return EFI_SUCCESS; +} + +/** + Discard all changes done to the BMM pages such as Boot Order change, + Driver order change. + + @param Private The BMM context data. + @param CurrentFakeNVMap The current Fack NV Map. + +**/ +VOID +DiscardChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap + ) +{ + UINT16 Index; + + switch (Private->BmmPreviousPageId) { + case FORM_BOOT_CHG_ID: + CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder)); + break; + + case FORM_DRV_CHG_ID: + CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder)); + break; + + case FORM_BOOT_DEL_ID: + ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0]))); + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + CurrentFakeNVMap->BootOptionDel[Index] = FALSE; + CurrentFakeNVMap->BootOptionDelMark[Index] = FALSE; + } + break; + + case FORM_DRV_DEL_ID: + ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0]))); + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + CurrentFakeNVMap->DriverOptionDel[Index] = FALSE; + CurrentFakeNVMap->DriverOptionDelMark[Index] = FALSE; + } + break; + + case FORM_BOOT_NEXT_ID: + CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext; + break; + + case FORM_TIME_OUT_ID: + CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut; + break; + + case FORM_DRV_ADD_HANDLE_DESC_ID: + case FORM_DRV_ADD_FILE_ID: + case FORM_DRV_ADD_HANDLE_ID: + CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000; + CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000; + break; + + default: + break; + } +} + +/** + Initialize the Boot Maintenance Utitliy. + + + @retval EFI_SUCCESS utility ended successfully + @retval others contain some errors + +**/ +EFI_STATUS +InitializeBM ( + VOID + ) +{ + BMM_CALLBACK_DATA *BmmCallbackInfo; + EFI_STATUS Status; + EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; + UINT32 Length; + UINT8 *Data; + + Status = EFI_SUCCESS; + BmmCallbackInfo = mBmmCallbackInfo; + + BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; + BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; + BmmCallbackInfo->FeCurrentState = FileExplorerStateInActive; + BmmCallbackInfo->FeDisplayContext = FileExplorerDisplayUnknown; + + // + // Reinstall String packages to include more new strings. + // + + // + // String package size + // + Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32); + + // + // Add the length of the Package List Header and the terminating Package Header + // + Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER); + + // + // Allocate the storage for the entire Package List + // + PackageListHeader = AllocateZeroPool (Length); + + // + // If the Package List can not be allocated, then return a NULL HII Handle + // + if (PackageListHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Fill in the GUID and Length of the Package List Header + // + PackageListHeader->PackageLength = Length; + + // + // Copy String Data into Package list. + // + Data = (UINT8 *)(PackageListHeader + 1); + Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32); + CopyMem (Data, (UINT8 *) BdsDxeStrings + sizeof (UINT32), Length); + + // + // Add End type HII package. + // + Data += Length; + ((EFI_HII_PACKAGE_HEADER *) Data)->Type = EFI_HII_PACKAGE_END; + ((EFI_HII_PACKAGE_HEADER *) Data)->Length = sizeof (EFI_HII_PACKAGE_HEADER); + + // + // Update String package for BM + // + CopyGuid (&PackageListHeader->PackageListGuid, &gBootMaintFormSetGuid); + Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle, PackageListHeader); + + // + // Update String package for FE. + // + CopyGuid (&PackageListHeader->PackageListGuid, &gFileExploreFormSetGuid); + Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle, PackageListHeader); + + FreePool (PackageListHeader); + + // + // Init OpCode Handle and Allocate space for creation of Buffer + // + mStartOpCodeHandle = HiiAllocateOpCodeHandle (); + if (mStartOpCodeHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + mEndOpCodeHandle = HiiAllocateOpCodeHandle (); + if (mEndOpCodeHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + // + // Create Hii Extend Label OpCode as the start opcode + // + mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + + // + // Create Hii Extend Label OpCode as the end opcode + // + mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + mEndLabel->Number = LABEL_END; + + InitializeStringDepository (); + + InitAllMenu (BmmCallbackInfo); + + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu); + + InitializeBmmConfig (BmmCallbackInfo); + + // + // Dispatch BMM main formset and File Explorer formset. + // + FormSetDispatcher (BmmCallbackInfo); + + // + // Clean up. + // + CleanUpStringDepository (); + + FreeAllMenu (); + +Exit: + if (mStartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mStartOpCodeHandle); + } + + if (mEndOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mEndOpCodeHandle); + } + + return Status; +} + + +/** + Initialized all Menu Option List. + + @param CallbackData The BMM context data. + +**/ +VOID +InitAllMenu ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + InitializeListHead (&BootOptionMenu.Head); + InitializeListHead (&DriverOptionMenu.Head); + BOpt_GetBootOptions (CallbackData); + BOpt_GetDriverOptions (CallbackData); + BOpt_GetLegacyOptions (); + InitializeListHead (&FsOptionMenu.Head); + BOpt_FindDrivers (); + InitializeListHead (&DirectoryMenu.Head); + InitializeListHead (&ConsoleInpMenu.Head); + InitializeListHead (&ConsoleOutMenu.Head); + InitializeListHead (&ConsoleErrMenu.Head); + InitializeListHead (&TerminalMenu.Head); + LocateSerialIo (); + GetAllConsoles (); +} + +/** + Free up all Menu Option list. + +**/ +VOID +FreeAllMenu ( + VOID + ) +{ + BOpt_FreeMenu (&DirectoryMenu); + BOpt_FreeMenu (&FsOptionMenu); + BOpt_FreeMenu (&BootOptionMenu); + BOpt_FreeMenu (&DriverOptionMenu); + BOpt_FreeMenu (&DriverMenu); + BOpt_FreeLegacyOptions (); + FreeAllConsoles (); +} + +/** + Initialize all the string depositories. + +**/ +VOID +InitializeStringDepository ( + VOID + ) +{ + STRING_DEPOSITORY *StringDepository; + StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER); + FileOptionStrDepository = StringDepository++; + ConsoleOptionStrDepository = StringDepository++; + BootOptionStrDepository = StringDepository++; + BootOptionHelpStrDepository = StringDepository++; + DriverOptionStrDepository = StringDepository++; + DriverOptionHelpStrDepository = StringDepository++; + TerminalStrDepository = StringDepository; +} + +/** + Fetch a usable string node from the string depository and return the string token. + + @param CallbackData The BMM context data. + @param StringDepository The string repository. + + @retval EFI_STRING_ID String token. + +**/ +EFI_STRING_ID +GetStringTokenFromDepository ( + IN BMM_CALLBACK_DATA *CallbackData, + IN STRING_DEPOSITORY *StringDepository + ) +{ + STRING_LIST_NODE *CurrentListNode; + STRING_LIST_NODE *NextListNode; + + CurrentListNode = StringDepository->CurrentNode; + + if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) { + // + // Fetch one reclaimed node from the list. + // + NextListNode = StringDepository->CurrentNode->Next; + } else { + // + // If there is no usable node in the list, update the list. + // + NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE)); + ASSERT (NextListNode != NULL); + NextListNode->StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, L" ", NULL); + ASSERT (NextListNode->StringToken != 0); + + StringDepository->TotalNodeNumber++; + + if (NULL == CurrentListNode) { + StringDepository->ListHead = NextListNode; + } else { + CurrentListNode->Next = NextListNode; + } + } + + StringDepository->CurrentNode = NextListNode; + + return StringDepository->CurrentNode->StringToken; +} + +/** + Reclaim string depositories by moving the current node pointer to list head.. + +**/ +VOID +ReclaimStringDepository ( + VOID + ) +{ + UINTN DepositoryIndex; + STRING_DEPOSITORY *StringDepository; + + StringDepository = FileOptionStrDepository; + for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { + StringDepository->CurrentNode = StringDepository->ListHead; + StringDepository++; + } +} + +/** + Release resource for all the string depositories. + +**/ +VOID +CleanUpStringDepository ( + VOID + ) +{ + UINTN NodeIndex; + UINTN DepositoryIndex; + STRING_LIST_NODE *CurrentListNode; + STRING_LIST_NODE *NextListNode; + STRING_DEPOSITORY *StringDepository; + + // + // Release string list nodes. + // + StringDepository = FileOptionStrDepository; + for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { + CurrentListNode = StringDepository->ListHead; + for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) { + NextListNode = CurrentListNode->Next; + FreePool (CurrentListNode); + CurrentListNode = NextListNode; + } + + StringDepository++; + } + // + // Release string depository. + // + FreePool (FileOptionStrDepository); +} + +/** + Start boot maintenance manager + + @retval EFI_SUCCESS If BMM is invoked successfully. + @return Other value if BMM return unsuccessfully. + +**/ +EFI_STATUS +BdsStartBootMaint ( + VOID + ) +{ + EFI_STATUS Status; + LIST_ENTRY BdsBootOptionList; + + InitializeListHead (&BdsBootOptionList); + + // + // Connect all prior to entering the platform setup menu. + // + if (!gConnectAllHappened) { + BdsLibConnectAllDriversToAllControllers (); + gConnectAllHappened = TRUE; + } + // + // Have chance to enumerate boot device + // + BdsLibEnumerateAllBootOption (&BdsBootOptionList); + + // + // Group the legacy boot options for the same device type + // + GroupMultipleLegacyBootOption4SameType (); + + // + // Init the BMM + // + Status = InitializeBM (); + + return Status; +} + +/** + Dispatch BMM formset and FileExplorer formset. + + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS If function complete successfully. + @return Other value if the Setup Browser process BMM's pages and + return unsuccessfully. + +**/ +EFI_STATUS +FormSetDispatcher ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + EFI_BROWSER_ACTION_REQUEST ActionRequest; + + while (TRUE) { + UpdatePageId (CallbackData, FORM_MAIN_ID); + + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &CallbackData->BmmHiiHandle, + 1, + &gBootMaintFormSetGuid, + 0, + NULL, + &ActionRequest + ); + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + ReclaimStringDepository (); + + // + // When this Formset returns, check if we are going to explore files. + // + if (FileExplorerStateInActive != CallbackData->FeCurrentState) { + UpdateFileExplorer (CallbackData, 0); + + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &CallbackData->FeHiiHandle, + 1, + &gFileExploreFormSetGuid, + 0, + NULL, + &ActionRequest + ); + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + CallbackData->FeCurrentState = FileExplorerStateInActive; + CallbackData->FeDisplayContext = FileExplorerDisplayUnknown; + ReclaimStringDepository (); + } else { + break; + } + } + + return Status; +} + +/** + Intall BootMaint and FileExplorer HiiPackages. + +**/ +EFI_STATUS +InitBMPackage ( + VOID + ) +{ + BMM_CALLBACK_DATA *BmmCallbackInfo; + EFI_STATUS Status; + UINT8 *Ptr; + + // + // Create CallbackData structures for Driver Callback + // + BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA)); + if (BmmCallbackInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Create LoadOption in BmmCallbackInfo for Driver Callback + // + Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY)); + if (Ptr == NULL) { + FreePool (BmmCallbackInfo); + BmmCallbackInfo = NULL; + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize Bmm callback data. + // + BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr; + Ptr += sizeof (BM_LOAD_CONTEXT); + + BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr; + Ptr += sizeof (BM_FILE_CONTEXT); + + BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr; + Ptr += sizeof (BM_HANDLE_CONTEXT); + + BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr; + + BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE; + BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig; + BmmCallbackInfo->BmmConfigAccess.RouteConfig = BootMaintRouteConfig; + BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback; + BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig; + BmmCallbackInfo->FeConfigAccess.RouteConfig = FileExplorerRouteConfig; + BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback; + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BmmCallbackInfo->BmmDriverHandle, + &gEfiDevicePathProtocolGuid, + &mBmmHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &BmmCallbackInfo->BmmConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BmmCallbackInfo->FeDriverHandle, + &gEfiDevicePathProtocolGuid, + &mFeHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &BmmCallbackInfo->FeConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Post our Boot Maint VFR binary to the HII database. + // + BmmCallbackInfo->BmmHiiHandle = HiiAddPackages ( + &gBootMaintFormSetGuid, + BmmCallbackInfo->BmmDriverHandle, + BmBin, + BdsDxeStrings, + NULL + ); + ASSERT (BmmCallbackInfo->BmmHiiHandle != NULL); + + // + // Post our File Explorer VFR binary to the HII database. + // + BmmCallbackInfo->FeHiiHandle = HiiAddPackages ( + &gFileExploreFormSetGuid, + BmmCallbackInfo->FeDriverHandle, + FEBin, + BdsDxeStrings, + NULL + ); + ASSERT (BmmCallbackInfo->FeHiiHandle != NULL); + + mBmmCallbackInfo = BmmCallbackInfo; + + return EFI_SUCCESS; +} + +/** + Remvoe the intalled BootMaint and FileExplorer HiiPackages. + +**/ +VOID +FreeBMPackage ( + VOID + ) +{ + BMM_CALLBACK_DATA *BmmCallbackInfo; + + BmmCallbackInfo = mBmmCallbackInfo; + + // + // Remove our IFR data from HII database + // + HiiRemovePackages (BmmCallbackInfo->BmmHiiHandle); + HiiRemovePackages (BmmCallbackInfo->FeHiiHandle); + + if (BmmCallbackInfo->FeDriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + BmmCallbackInfo->FeDriverHandle, + &gEfiDevicePathProtocolGuid, + &mFeHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &BmmCallbackInfo->FeConfigAccess, + NULL + ); + } + + if (BmmCallbackInfo->BmmDriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + BmmCallbackInfo->BmmDriverHandle, + &gEfiDevicePathProtocolGuid, + &mBmmHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &BmmCallbackInfo->BmmConfigAccess, + NULL + ); + } + + FreePool (BmmCallbackInfo->LoadContext); + FreePool (BmmCallbackInfo); + + mBmmCallbackInfo = NULL; + + return; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h new file mode 100644 index 0000000000..098692fa53 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h @@ -0,0 +1,1679 @@ +/** @file + Header file for boot maintenance module. + +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 +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 _BOOT_MAINT_H_ +#define _BOOT_MAINT_H_ + +#include "Bds.h" +#include "BBSsupport.h" +#include "FormGuid.h" +#include "FrontPage.h" + +// +// Constants which are variable names used to access variables +// +#define VAR_CON_OUT_MODE L"ConOutMode" + +// +// String Contant +// +#define STR_FLOPPY L"Floppy Drive #%02x" +#define STR_HARDDISK L"HardDisk Drive #%02x" +#define STR_CDROM L"ATAPI CDROM Drive #%02x" +#define STR_NET L"NET Drive #%02x" +#define STR_BEV L"BEV Drive #%02x" +#define STR_FLOPPY_HELP L"Select Floppy Drive #%02x" +#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x" +#define STR_CDROM_HELP L"Select ATAPI CDROM Drive #%02x" +#define STR_NET_HELP L"NET Drive #%02x" +#define STR_BEV_HELP L"BEV Drive #%02x" + +extern CHAR16 mFileExplorerStorageName[]; +extern CHAR16 mBootMaintStorageName[]; +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 BmBin[]; +extern UINT8 FEBin[]; + +// +// Below are the number of options in Baudrate, Databits, +// Parity and Stopbits selection for serial ports. +// +#define BM_COM_ATTR_BUADRATE 19 +#define BM_COM_ATTR_DATABITS 4 +#define BM_COM_ATTR_PARITY 5 +#define BM_COM_ATTR_STOPBITS 3 + +// +// Callback function helper +// +#define BMM_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('C', 'b', 'c', 'k') +#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE) + +#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE) + +// +// Enumeration type definition +// +typedef enum _TYPE_OF_TERMINAL { + TerminalTypePcAnsi = 0, + TerminalTypeVt100, + TerminalTypeVt100Plus, + TerminalTypeVtUtf8 +} TYPE_OF_TERMINAL; + +typedef enum _FILE_EXPLORER_STATE { + FileExplorerStateInActive = 0, + FileExplorerStateBootFromFile, + FileExplorerStateAddBootOption, + FileExplorerStateAddDriverOptionState, + FileExplorerStateUnknown +} FILE_EXPLORER_STATE; + +typedef enum _FILE_EXPLORER_DISPLAY_CONTEXT { + FileExplorerDisplayFileSystem, + FileExplorerDisplayDirectory, + FileExplorerDisplayUnknown +} FILE_EXPLORER_DISPLAY_CONTEXT; + +// +// All of the signatures that will be used in list structure +// +#define BM_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u') +#define BM_LOAD_OPTION_SIGNATURE SIGNATURE_32 ('l', 'o', 'a', 'd') +#define BM_CONSOLE_OPTION_SIGNATURE SIGNATURE_32 ('c', 'n', 's', 'l') +#define BM_FILE_OPTION_SIGNATURE SIGNATURE_32 ('f', 'i', 'l', 'e') +#define BM_HANDLE_OPTION_SIGNATURE SIGNATURE_32 ('h', 'n', 'd', 'l') +#define BM_TERMINAL_OPTION_SIGNATURE SIGNATURE_32 ('t', 'r', 'm', 'l') +#define BM_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r') + +#define BM_LOAD_CONTEXT_SELECT 0x0 +#define BM_CONSOLE_CONTEXT_SELECT 0x1 +#define BM_FILE_CONTEXT_SELECT 0x2 +#define BM_HANDLE_CONTEXT_SELECT 0x3 +#define BM_TERMINAL_CONTEXT_SELECT 0x5 + +#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6 +#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7 +#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8 +#define BM_LEGACY_DEV_CONTEXT_SELECT 0x9 + +// +// Buffer size for update data +// +#define UPDATE_DATA_SIZE 0x100000 + +// +// Namespace of callback keys used in display and file system navigation +// +#define MAX_BBS_OFFSET 0xE000 +#define NET_OPTION_OFFSET 0xD800 +#define BEV_OPTION_OFFSET 0xD000 +#define FD_OPTION_OFFSET 0xC000 +#define HD_OPTION_OFFSET 0xB000 +#define CD_OPTION_OFFSET 0xA000 +#define FILE_OPTION_GOTO_OFFSET 0xC000 +#define FILE_OPTION_OFFSET 0x8000 +#define FILE_OPTION_MASK 0x3FFF +#define HANDLE_OPTION_OFFSET 0x7000 +#define CONSOLE_OPTION_OFFSET 0x6000 +#define TERMINAL_OPTION_OFFSET 0x5000 +#define CONFIG_OPTION_OFFSET 0x1200 +#define KEY_VALUE_OFFSET 0x1100 +#define FORM_ID_OFFSET 0x1000 + +// +// VarOffset that will be used to create question +// all these values are computed from the structure +// defined below +// +#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field))) + +// +// Question Id of Zero is invalid, so add an offset to it +// +#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET) + +#define BOOT_TIME_OUT_VAR_OFFSET VAR_OFFSET (BootTimeOut) +#define BOOT_NEXT_VAR_OFFSET VAR_OFFSET (BootNext) +#define COM1_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM1BaudRate) +#define COM1_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM1DataRate) +#define COM1_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM1StopBits) +#define COM1_PARITY_VAR_OFFSET VAR_OFFSET (COM1Parity) +#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType) +#define COM2_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM2BaudRate) +#define COM2_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM2DataRate) +#define COM2_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM2StopBits) +#define COM2_PARITY_VAR_OFFSET VAR_OFFSET (COM2Parity) +#define COM2_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType) +#define DRV_ADD_HANDLE_DESC_VAR_OFFSET VAR_OFFSET (DriverAddHandleDesc) +#define DRV_ADD_ACTIVE_VAR_OFFSET VAR_OFFSET (DriverAddActive) +#define DRV_ADD_RECON_VAR_OFFSET VAR_OFFSET (DriverAddForceReconnect) +#define CON_IN_COM1_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM1) +#define CON_IN_COM2_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM2) +#define CON_OUT_COM1_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM1) +#define CON_OUT_COM2_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM2) +#define CON_ERR_COM1_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM1) +#define CON_ERR_COM2_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM2) +#define CON_MODE_VAR_OFFSET VAR_OFFSET (ConsoleOutMode) +#define CON_IN_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleInCheck) +#define CON_OUT_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleOutCheck) +#define CON_ERR_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleErrCheck) +#define BOOT_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (BootOptionOrder) +#define DRIVER_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (DriverOptionOrder) +#define BOOT_OPTION_DEL_VAR_OFFSET VAR_OFFSET (BootOptionDel) +#define DRIVER_OPTION_DEL_VAR_OFFSET VAR_OFFSET (DriverOptionDel) +#define DRIVER_ADD_OPTION_VAR_OFFSET VAR_OFFSET (DriverAddHandleOptionalData) +#define COM_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COMBaudRate) +#define COM_DATA_RATE_VAR_OFFSET VAR_OFFSET (COMDataRate) +#define COM_STOP_BITS_VAR_OFFSET VAR_OFFSET (COMStopBits) +#define COM_PARITY_VAR_OFFSET VAR_OFFSET (COMParity) +#define COM_TERMINAL_VAR_OFFSET VAR_OFFSET (COMTerminalType) +#define COM_FLOWCONTROL_VAR_OFFSET VAR_OFFSET (COMFlowControl) +#define LEGACY_FD_VAR_OFFSET VAR_OFFSET (LegacyFD) +#define LEGACY_HD_VAR_OFFSET VAR_OFFSET (LegacyHD) +#define LEGACY_CD_VAR_OFFSET VAR_OFFSET (LegacyCD) +#define LEGACY_NET_VAR_OFFSET VAR_OFFSET (LegacyNET) +#define LEGACY_BEV_VAR_OFFSET VAR_OFFSET (LegacyBEV) + +#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut) +#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext) +#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate) +#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate) +#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits) +#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity) +#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) +#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate) +#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate) +#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits) +#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity) +#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) +#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc) +#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive) +#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect) +#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1) +#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2) +#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1) +#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2) +#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1) +#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2) +#define CON_MODE_QUESTION_ID QUESTION_ID (ConsoleOutMode) +#define CON_IN_DEVICE_QUESTION_ID QUESTION_ID (ConsoleInCheck) +#define CON_OUT_DEVICE_QUESTION_ID QUESTION_ID (ConsoleOutCheck) +#define CON_ERR_DEVICE_QUESTION_ID QUESTION_ID (ConsoleErrCheck) +#define BOOT_OPTION_ORDER_QUESTION_ID QUESTION_ID (BootOptionOrder) +#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionOrder) +#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel) +#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel) +#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData) +#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate) +#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate) +#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits) +#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity) +#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType) +#define COM_FLOWCONTROL_QUESTION_ID QUESTION_ID (COMFlowControl) +#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD) +#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD) +#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD) +#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET) +#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV) + +#define STRING_DEPOSITORY_NUMBER 8 + +/// +/// Serial Ports attributes, first one is the value for +/// return from callback function, stringtoken is used to +/// display the value properly +/// +typedef struct { + UINTN Value; + UINT16 StringToken; +} COM_ATTR; + +typedef struct { + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; + + UINT8 BaudRateIndex; + UINT8 DataBitsIndex; + UINT8 ParityIndex; + UINT8 StopBitsIndex; + + UINT8 FlowControl; + + UINT8 IsConIn; + UINT8 IsConOut; + UINT8 IsStdErr; + UINT8 TerminalType; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_TERMINAL_CONTEXT; + +typedef struct { + BOOLEAN IsBootNext; + BOOLEAN LoadOptionModified; + BOOLEAN Deleted; + + BOOLEAN IsLegacy; + BOOLEAN IsActive; + BOOLEAN ForceReconnect; + UINTN OptionalDataSize; + + UINTN LoadOptionSize; + UINT8 *LoadOption; + + UINT32 Attributes; + UINT16 FilePathListLength; + UINT16 *Description; + EFI_DEVICE_PATH_PROTOCOL *FilePathList; + UINT8 *OptionalData; + + UINT16 BbsIndex; +} BM_LOAD_CONTEXT; + +typedef struct { + BBS_TABLE *BbsEntry; + UINT16 BbsIndex; + UINT16 BbsCount; + CHAR16 *Description; +} BM_LEGACY_DEVICE_CONTEXT; + +typedef struct { + + BOOLEAN IsActive; + + BOOLEAN IsTerminal; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_CONSOLE_CONTEXT; + +typedef struct { + UINTN Column; + UINTN Row; +} CONSOLE_OUT_MODE; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FILE_HANDLE FHandle; + UINT16 *FileName; + EFI_FILE_SYSTEM_VOLUME_LABEL *Info; + + BOOLEAN IsRoot; + BOOLEAN IsDir; + BOOLEAN IsRemovableMedia; + BOOLEAN IsLoadFile; + BOOLEAN IsBootLegacy; +} BM_FILE_CONTEXT; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_HANDLE_CONTEXT; + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} BM_MENU_OPTION; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINTN OptionNumber; + UINT16 *DisplayString; + UINT16 *HelpString; + EFI_STRING_ID DisplayStringToken; + EFI_STRING_ID HelpStringToken; + UINTN ContextSelection; + VOID *VariableContext; +} BM_MENU_ENTRY; + +typedef struct { + // + // Shared callback data. + // + UINTN Signature; + + BM_MENU_ENTRY *MenuEntry; + BM_HANDLE_CONTEXT *HandleContext; + BM_FILE_CONTEXT *FileContext; + BM_LOAD_CONTEXT *LoadContext; + BM_TERMINAL_CONTEXT *TerminalContext; + UINTN CurrentTerminal; + BBS_TYPE BbsType; + + // + // BMM main formset callback data. + // + EFI_HII_HANDLE BmmHiiHandle; + EFI_HANDLE BmmDriverHandle; + EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess; + EFI_FORM_ID BmmCurrentPageId; + EFI_FORM_ID BmmPreviousPageId; + BOOLEAN BmmAskSaveOrNot; + BMM_FAKE_NV_DATA BmmFakeNvData; + BMM_FAKE_NV_DATA BmmOldFakeNVData; + + // + // File explorer formset callback data. + // + EFI_HII_HANDLE FeHiiHandle; + EFI_HANDLE FeDriverHandle; + EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess; + FILE_EXPLORER_STATE FeCurrentState; + FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext; + FILE_EXPLORER_NV_DATA FeFakeNvData; +} BMM_CALLBACK_DATA; + +typedef struct _STRING_LIST_NODE STRING_LIST_NODE; + +struct _STRING_LIST_NODE { + EFI_STRING_ID StringToken; + STRING_LIST_NODE *Next; +}; + +typedef struct _STRING_DEPOSITORY { + UINTN TotalNodeNumber; + STRING_LIST_NODE *CurrentNode; + STRING_LIST_NODE *ListHead; +} STRING_DEPOSITORY; + +// +// #pragma pack() +// +// For initializing File System menu +// + +/** + This function build the FsOptionMenu list which records all + available file system in the system. They includes all instances + of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM + and all type of legacy boot device. + + @param CallbackData BMM context data + + @retval EFI_SUCCESS Success find the file system + @retval EFI_OUT_OF_RESOURCES Can not create menu entry + +**/ +EFI_STATUS +BOpt_FindFileSystem ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Find files under current directory + All files and sub-directories in current directory + will be stored in DirectoryMenu for future use. + + @param CallbackData The BMM context data. + @param MenuEntry The Menu Entry. + + @retval EFI_SUCCESS Get files from current dir successfully. + @return Other value if can't get files from current dir. + +**/ +EFI_STATUS +BOpt_FindFiles ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_ENTRY *MenuEntry + ); + +/** + + Find drivers that will be added as Driver#### variables from handles + in current system environment + All valid handles in the system except those consume SimpleFs, LoadFile + are stored in DriverMenu for future use. + + @retval EFI_SUCCESS The function complets successfully. + @return Other value if failed to build the DriverMenu. + +**/ +EFI_STATUS +BOpt_FindDrivers ( + VOID + ); + +/** + + Build the BootOptionMenu according to BootOrder Variable. + This Routine will access the Boot#### to get EFI_LOAD_OPTION. + + @param CallbackData The BMM context data. + + @return The number of the Var Boot####. + +**/ +EFI_STATUS +BOpt_GetBootOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + + Build up all DriverOptionMenu + + @param CallbackData The BMM context data. + + @return EFI_SUCESS The functin completes successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation. + + +**/ +EFI_STATUS +BOpt_GetDriverOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ); + + +/** + Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function. + +**/ +EFI_STATUS +BOpt_GetLegacyOptions ( + VOID + ); + +/** + Free out resouce allocated from Legacy Boot Options. + +**/ +VOID +BOpt_FreeLegacyOptions ( + VOID + ); + +/** + Free resources allocated in Allocate Rountine. + + @param FreeMenu Menu to be freed + +**/ +VOID +BOpt_FreeMenu ( + BM_MENU_OPTION *FreeMenu + ); + + +/** + + Append file name to existing file name. + + @param Str1 The existing file name + @param Str2 The file name to be appended + + @return Allocate a new string to hold the appended result. + Caller is responsible to free the returned string. + +**/ +CHAR16* +BOpt_AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ); + +/** + + Check whether current FileName point to a valid + Efi Image File. + + @param FileName File need to be checked. + + @retval TRUE Is Efi Image + @retval FALSE Not a valid Efi Image + +**/ +BOOLEAN +BOpt_IsEfiImageName ( + IN UINT16 *FileName + ); + +/** + + Check whether current FileName point to a valid Efi Application + + @param Dir Pointer to current Directory + @param FileName Pointer to current File name. + + @retval TRUE Is a valid Efi Application + @retval FALSE not a valid Efi Application + +**/ +BOOLEAN +BOpt_IsEfiApp ( + IN EFI_FILE_HANDLE Dir, + IN UINT16 *FileName + ); + +/** + + Get the Option Number that has not been allocated for use. + + @param Type The type of Option. + + @return The available Option Number. + +**/ +UINT16 +BOpt_GetOptionNumber ( + CHAR16 *Type + ); + +/** + + Get the Option Number for Boot#### that does not used. + + @return The available Option Number. + +**/ +UINT16 +BOpt_GetBootOptionNumber ( + VOID + ); + +/** + +Get the Option Number for Driver#### that does not used. + +@return The unused Option Number. + +**/ +UINT16 +BOpt_GetDriverOptionNumber ( + VOID + ); + +/** + Create a menu entry give a Menu type. + + @param MenuType The Menu type to be created. + + + @retval NULL If failed to create the menu. + @return The menu. + +**/ +BM_MENU_ENTRY * +BOpt_CreateMenuEntry ( + UINTN MenuType + ); + +/** + Free up all resource allocated for a BM_MENU_ENTRY. + + @param MenuEntry A pointer to BM_MENU_ENTRY. + +**/ +VOID +BOpt_DestroyMenuEntry ( + BM_MENU_ENTRY *MenuEntry + ); + +/** + Get the Menu Entry from the list in Menu Entry List. + + If MenuNumber is great or equal to the number of Menu + Entry in the list, then ASSERT. + + @param MenuOption The Menu Entry List to read the menu entry. + @param MenuNumber The index of Menu Entry. + + @return The Menu Entry. + +**/ +BM_MENU_ENTRY * +BOpt_GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ); + +// +// Locate all serial io devices for console +// +/** + Build a list containing all serial devices. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_UNSUPPORTED No serial ports present. + +**/ +EFI_STATUS +LocateSerialIo ( + VOID + ); + +// +// Initializing Console menu +// +/** + Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + + @retval EFI_SUCCESS The function always complete successfully. + +**/ +EFI_STATUS +GetAllConsoles( + VOID + ); + +// +// Get current mode information +// +/** + Get mode number according to column and row + + @param CallbackData The BMM context data. +**/ +VOID +GetConsoleOutMode ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// Cleaning up console menu +// +/** + Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + + @retval EFI_SUCCESS The function always complete successfully. +**/ +EFI_STATUS +FreeAllConsoles ( + VOID + ); + +/** + Update the device path that describing a terminal device + based on the new BaudRate, Data Bits, parity and Stop Bits + set. + + @param DevicePath The devicepath protocol instance wanted to be updated. + +**/ +VOID +ChangeVariableDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Update the multi-instance device path of Terminal Device based on + the global TerminalMenu. If ChangeTernimal is TRUE, the terminal + device path in the Terminal Device in TerminalMenu is also updated. + + @param DevicePath The multi-instance device path. + @param ChangeTerminal TRUE, then device path in the Terminal Device + in TerminalMenu is also updated; FALSE, no update. + + @return EFI_SUCCESS The function completes successfully. + +**/ +EFI_STATUS +ChangeTerminalDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + IN BOOLEAN ChangeTerminal + ); + +// +// Variable operation by menu selection +// +/** + This function create a currently loaded Boot Option from + the BMM. It then appends this Boot Option to the end of + the "BootOrder" list. It also append this Boot Opotion to the end + of BootOptionMenu. + + @param CallbackData The BMM context data. + @param NvRamMap The file explorer formset internal state. + + @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. + @retval EFI_SUCCESS If function completes successfully. + +**/ +EFI_STATUS +Var_UpdateBootOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN FILE_EXPLORER_NV_DATA *NvRamMap + ); + +/** + Delete Boot Option that represent a Deleted state in BootOptionMenu. + After deleting this boot option, call Var_ChangeBootOrder to + make sure BootOrder is in valid state. + + @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to + BM_LOAD_CONTEXT marked for deletion is deleted + @return Others If failed to update the "BootOrder" variable after deletion. + +**/ +EFI_STATUS +Var_DelBootOption ( + VOID + ); + +/** + After any operation on Boot####, there will be a discrepancy in BootOrder. + Since some are missing but in BootOrder, while some are present but are + not reflected by BootOrder. Then a function rebuild BootOrder from + scratch by content from BootOptionMenu is needed. + + @retval EFI_SUCCESS The boot order is updated successfully. + @return other than EFI_SUCCESS if failed to change the "BootOrder" EFI Variable. + +**/ +EFI_STATUS +Var_ChangeBootOrder ( + VOID + ); + +/** + This function create a currently loaded Drive Option from + the BMM. It then appends this Driver Option to the end of + the "DriverOrder" list. It append this Driver Opotion to the end + of DriverOptionMenu. + + @param CallbackData The BMM context data. + @param HiiHandle The HII handle associated with the BMM formset. + @param DescriptionData The description of this driver option. + @param OptionalData The optional load option. + @param ForceReconnect If to force reconnect. + + @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. + @retval EFI_SUCCESS If function completes successfully. + +**/ +EFI_STATUS +Var_UpdateDriverOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 *DescriptionData, + IN UINT16 *OptionalData, + IN UINT8 ForceReconnect + ); + +/** + Delete Load Option that represent a Deleted state in BootOptionMenu. + After deleting this Driver option, call Var_ChangeDriverOrder to + make sure DriverOrder is in valid state. + + @retval EFI_SUCCESS Load Option is successfully updated. + @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI + Variable. + +**/ +EFI_STATUS +Var_DelDriverOption ( + VOID + ); + +/** + After any operation on Driver####, there will be a discrepancy in + DriverOrder. Since some are missing but in DriverOrder, while some + are present but are not reflected by DriverOrder. Then a function + rebuild DriverOrder from scratch by content from DriverOptionMenu is + needed. + + @retval EFI_SUCCESS The driver order is updated successfully. + @return other than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable. + +**/ +EFI_STATUS +Var_ChangeDriverOrder ( + VOID + ); + +/** + This function delete and build multi-instance device path ConIn + console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateConsoleInpOption ( + VOID + ); + +/** + This function delete and build multi-instance device path ConOut console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateConsoleOutOption ( + VOID + ); + +/** + This function delete and build multi-instance device path ErrOut console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateErrorOutOption ( + VOID + ); + +/** + Update the device path of "ConOut", "ConIn" and "ErrOut" based on the new BaudRate, Data Bits, + parity and stop Bits set. + +**/ +VOID +Var_UpdateAllConsoleOption ( + VOID + ); + +/** + This function update the "BootNext" EFI Variable. If there is no "BootNex" specified in BMM, + this EFI Variable is deleted. + It also update the BMM context data specified the "BootNext" value. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateBootNext ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + This function update the "BootOrder" EFI Variable based on BMM Formset's NV map. It then refresh + BootOptionMenu with the new "BootOrder" list. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. + @return not The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + This function update the "DriverOrder" EFI Variable based on + BMM Formset's NV map. It then refresh DriverOptionMenu + with the new "DriverOrder" list. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable + is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid + is also updated. + + @param CallbackData The context data for BMM. + @param FormId The form id. + + @return EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can not be found. + +**/ +EFI_STATUS +Var_UpdateBBSOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_FORM_ID FormId + ); + +/** + Update the Text Mode of Console. + + @param CallbackData The context data for BMM. + + @retval EFI_SUCCSS If the Text Mode of Console is updated. + @return Other value if the Text Mode of Console is not updated. + +**/ +EFI_STATUS +Var_UpdateConMode ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// Following are page create and refresh functions +// +/** + Refresh the global UpdateData structure. + +**/ +VOID +RefreshUpdateData ( + VOID + ); + +/** + Clean up the dynamic opcode at label and form specified by + both LabelId. + + @param LabelId It is both the Form ID and Label ID for + opcode deletion. + @param CallbackData The BMM context data. + +**/ +VOID +CleanUpPage ( + IN UINT16 LabelId, + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a lit of boot option from global BootOptionMenu. It + allow user to delete the boot option. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateBootDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a lit of driver option from global DriverMenu. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateDrvAddHandlePage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a lit of driver option from global DriverOptionMenu. It + allow user to delete the driver option. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateDrvDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Prepare the page to allow user to add description for a Driver Option. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateDriverAddHandleDescPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Dispatch the correct update page function to call based on the UpdatePageId. + + @param UpdatePageId The form ID. + @param CallbackData The BMM context data. +**/ +VOID +UpdatePageBody ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create the dynamic page to allow user to set the "BootNext" vaule. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateBootNextPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create the dynamic page to allow user to set the "TimeOut" vaule. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateTimeOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits, + Parity, Stop Bits, Terminal Type. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateTerminalPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Refresh the text mode page + + @param CallbackData The BMM context data. +**/ +VOID +UpdateConModePage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a list of Goto Opcode for all terminal devices logged + by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateConCOMPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a dynamic page so that Legacy Device boot order + can be set for specified device type. + + @param UpdatePageId The form ID. It also spefies the legacy device type. + @param CallbackData The BMM context data. +**/ +VOID +UpdateSetLegacyDeviceOrderPage ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ); + + +/** + Function opens and returns a file handle to the root directory of a volume. + + @param DeviceHandle A handle for a device + @return A valid file handle or NULL is returned +**/ +EFI_FILE_HANDLE +EfiLibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ); + +/** + Function gets the file system information from an open file descriptor, + and stores it in a buffer allocated from pool. + + @param FHand The file handle. + + @return A pointer to a buffer with file information. + NULL is returned if failed to get Vaolume Label Info. +**/ +EFI_FILE_SYSTEM_VOLUME_LABEL * +EfiLibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ); + +/** + + Function gets the file information from an open file descriptor, and stores it + in a buffer allocated from pool. + + @param FHand File Handle. + + @return A pointer to a buffer with file information or NULL is returned + +**/ +EFI_FILE_INFO * +EfiLibFileInfo ( + IN EFI_FILE_HANDLE FHand + ); + +/** + Adjusts the size of a previously allocated buffer. + + @param OldPool A pointer to the buffer whose size is being adjusted. + @param OldSize The size of the current buffer. + @param NewSize The size of the new buffer. + + @return The newly allocated buffer. if NULL, allocation failed. + +**/ +VOID* +EfiReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ); + +/** + Function deletes the variable specified by VarName and VarGuid. + + + @param VarName A Null-terminated Unicode string that is + the name of the vendor's variable. + + @param VarGuid A unique identifier for the vendor. + + @retval EFI_SUCCESS The variable was found and removed + @retval EFI_UNSUPPORTED The variable store was inaccessible + @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available + @retval EFI_NOT_FOUND The variable was not found + +**/ +EFI_STATUS +EfiLibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ); + +/** + Duplicate a string. + + @param Src The source. + + @return A new string which is duplicated copy of the source. + @retval NULL If there is not enough memory. + +**/ +CHAR16 * +EfiStrDuplicate ( + IN CHAR16 *Src + ); + +/** + Function is used to determine the number of device path instances + that exist in a device path. + + + @param DevicePath A pointer to a device path data structure. + + @return This function counts and returns the number of device path instances + in DevicePath. + +**/ +UINTN +EfiDevicePathInstanceCount ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Create string tokens for a menu from its help strings and display strings + + + @param CallbackData The BMM context data. + @param HiiHandle Hii Handle of the package to be updated. + @param MenuOption The Menu whose string tokens need to be created + + @retval EFI_SUCCESS string tokens created successfully + @retval others contain some errors + +**/ +EFI_STATUS +CreateMenuStringToken ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN BM_MENU_OPTION *MenuOption + ); + +/** + Get a string from the Data Hub record based on + a device path. + + @param DevPath The device Path. + + @return A string located from the Data Hub records based on + the device path. + @retval NULL If failed to get the String from Data Hub. + +**/ +UINT16 * +EfiLibStrFromDatahub ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +/** + Initialize the Boot Maintenance Utitliy. + + @retval EFI_SUCCESS utility ended successfully. + @retval others contain some errors. + +**/ +EFI_STATUS +InitializeBM ( + VOID + ); + +/** + Start boot maintenance manager + + @retval EFI_SUCCESS If BMM is invoked successfully. + @return Other value if BMM return unsuccessfully. + +**/ +EFI_STATUS +BdsStartBootMaint ( + VOID + ); + +/** + Intialize all the string depositories. + +**/ +VOID +InitializeStringDepository ( + VOID + ); + +/** + Fetch a usable string node from the string depository and return the string token. + + + @param CallbackData The BMM context data. + @param StringDepository Pointer of the string depository. + + @retval EFI_STRING_ID String token. + +**/ +EFI_STRING_ID +GetStringTokenFromDepository ( + IN BMM_CALLBACK_DATA *CallbackData, + IN STRING_DEPOSITORY *StringDepository + ); + +/** + Reclaim string depositories by moving the current node pointer to list head.. +**/ +VOID +ReclaimStringDepository ( + VOID + ); + +/** + Release resource for all the string depositories. + +**/ +VOID +CleanUpStringDepository ( + VOID + ); + +/** + Function handling request to apply changes for BMM pages. + + @param Private Pointer to callback data buffer. + @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM + @param FormId ID of the form which has sent the request to apply change. + + @retval EFI_SUCCESS Change successfully applied. + @retval Other Error occurs while trying to apply changes. + +**/ +EFI_STATUS +ApplyChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, + IN EFI_FORM_ID FormId + ); + +/** + Discard all changes done to the BMM pages such as Boot Order change, + Driver order change. + + @param Private The BMM context data. + @param CurrentFakeNVMap The current Fack NV Map. + +**/ +VOID +DiscardChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap + ); + +/** + Dispatch the display to the next page based on NewPageId. + + @param Private The BMM context data. + @param NewPageId The original page ID. + +**/ +VOID +UpdatePageId ( + BMM_CALLBACK_DATA *Private, + UINT16 NewPageId + ); + +/** + Boot a file selected by user at File Expoloer of BMM. + + @param FileContext The file context data, which contains the device path + of the file to be boot from. + + @retval EFI_SUCCESS The function completed successfull. + @return Other value if the boot from the file fails. + +**/ +EFI_STATUS +BootThisFile ( + IN BM_FILE_CONTEXT *FileContext + ); + +/** + Update the file explower page with the refershed file system. + + + @param CallbackData BMM context data + @param KeyValue Key value to identify the type of data to expect. + + @retval TRUE Inform the caller to create a callback packet to exit file explorer. + @retval FALSE Indicate that there is no need to exit file explorer. + +**/ +BOOLEAN +UpdateFileExplorer ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT16 KeyValue + ); + +/** + This function processes the results of changes in configuration. + When user select a interactive opcode, this callback will be triggered. + Based on the Question(QuestionId) that triggers the callback, the corresponding + actions is performed. It handles: + + 1) the addition of boot option. + 2) the addition of driver option. + 3) exit from file browser + 4) update of file content if a dir is selected. + 5) boot the file if a file is selected in "boot from file" + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + +**/ +EFI_STATUS +EFIAPI +FileExplorerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + This function applies changes in a driver's configuration. + Input is a Configuration, which has the routing data for this + driver followed by name / value configuration pairs. The driver + must apply those pairs to its configurable storage. If the + driver's configuration is stored in a linear block of data + and the driver's name / value pairs are in + format, it may use the ConfigToBlock helper function (above) to + simplify the job. Currently not implemented. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Configuration A null-terminated Unicode string in + format. + @param[out] Progress A pointer to a string filled in with the + offset of the most recent '&' before the + first failing name / value pair (or the + beginn ing 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 have been distributed or are + awaiting distribution. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + @retval EFI_INVALID_PARAMETERS Passing in a NULL for the + Results parameter would result + in this type of error. + @retval EFI_NOT_FOUND Target for the specified routing data + was not found. +**/ +EFI_STATUS +EFIAPI +FileExplorerRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +/** + Dispatch BMM formset and FileExplorer formset. + + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS If function complete successfully. + @return Other value if the Setup Browser process BMM's pages and + return unsuccessfully. + +**/ +EFI_STATUS +FormSetDispatcher ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Function returns the value of the specified variable. + + @param Name A Null-terminated Unicode string that is + the name of the vendor's variable. + @param VendorGuid A unique identifier for the vendor. + + @return The payload of the variable. + @retval NULL If the variable can't be read. + +**/ +VOID * +EfiLibGetVariable ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid + ); + +/** + Get option number according to Boot#### and BootOrder variable. + The value is saved as #### + 1. + + @param CallbackData The BMM context data. +**/ +VOID +GetBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Get driver option order from globalc DriverOptionMenu. + + @param CallbackData The BMM context data. + +**/ +VOID +GetDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Intall BootMaint and FileExplorer HiiPackages. + +**/ +EFI_STATUS +InitBMPackage ( + VOID + ); + +/** + Remvoe the intalled BootMaint and FileExplorer HiiPackages. + +**/ +VOID +FreeBMPackage ( + VOID + ); + +/** + According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV + devices list . + + @param CallbackData The BMM context data. +**/ +VOID +GetLegacyDeviceOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + + Initialize console input device check box to ConsoleInCheck[MAX_MENU_NUMBER] + in BMM_FAKE_NV_DATA structure. + + @param CallbackData The BMM context data. + +**/ +VOID +GetConsoleInCheck ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + + Initialize console output device check box to ConsoleOutCheck[MAX_MENU_NUMBER] + in BMM_FAKE_NV_DATA structure. + + @param CallbackData The BMM context data. + +**/ +VOID +GetConsoleOutCheck ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + + Initialize standard error output device check box to ConsoleErrCheck[MAX_MENU_NUMBER] + in BMM_FAKE_NV_DATA structure. + + @param CallbackData The BMM context data. + +**/ +VOID +GetConsoleErrCheck ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + + Initialize terminal attributes (baudrate, data rate, stop bits, parity and terminal type) + to BMM_FAKE_NV_DATA structure. + + @param CallbackData The BMM context data. + +**/ +VOID +GetTerminalAttribute ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + + Find the first instance of this Protocol + in the system and return it's interface. + + + @param ProtocolGuid Provides the protocol to search for + @param Interface On return, a pointer to the first interface + that matches ProtocolGuid + + @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found + @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid + +**/ +EFI_STATUS +EfiLibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ); + +// +// Global variable in this program (defined in data.c) +// +extern BM_MENU_OPTION BootOptionMenu; +extern BM_MENU_OPTION DriverOptionMenu; +extern BM_MENU_OPTION FsOptionMenu; +extern BM_MENU_OPTION ConsoleInpMenu; +extern BM_MENU_OPTION ConsoleOutMenu; +extern BM_MENU_OPTION ConsoleErrMenu; +extern BM_MENU_OPTION DirectoryMenu; +extern BM_MENU_OPTION DriverMenu; +extern BM_MENU_OPTION TerminalMenu; +extern BM_MENU_OPTION LegacyFDMenu; +extern BM_MENU_OPTION LegacyHDMenu; +extern BM_MENU_OPTION LegacyCDMenu; +extern BM_MENU_OPTION LegacyNETMenu; +extern BM_MENU_OPTION LegacyBEVMenu; +extern UINT16 TerminalType[]; +extern COM_ATTR BaudRateList[19]; +extern COM_ATTR DataBitsList[4]; +extern COM_ATTR ParityList[5]; +extern COM_ATTR StopBitsList[3]; +extern EFI_GUID TerminalTypeGuid[4]; +extern STRING_DEPOSITORY *FileOptionStrDepository; +extern STRING_DEPOSITORY *ConsoleOptionStrDepository; +extern STRING_DEPOSITORY *BootOptionStrDepository; +extern STRING_DEPOSITORY *BootOptionHelpStrDepository; +extern STRING_DEPOSITORY *DriverOptionStrDepository; +extern STRING_DEPOSITORY *DriverOptionHelpStrDepository; +extern STRING_DEPOSITORY *TerminalStrDepository; +extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[]; +extern UINT16 mFlowControlType[2]; +extern UINT32 mFlowControlValue[2]; +// +// Shared IFR form update data +// +extern VOID *mStartOpCodeHandle; +extern VOID *mEndOpCodeHandle; +extern EFI_IFR_GUID_LABEL *mStartLabel; +extern EFI_IFR_GUID_LABEL *mEndLabel; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c new file mode 100644 index 0000000000..56bcfab23f --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c @@ -0,0 +1,1823 @@ +/** @file + Provide boot option support for Application "BootMaint" + + Include file system navigation, system handle selection + + Boot option manipulation + +Copyright (c) 2004 - 2015, Intel 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 "BootMaint.h" +#include "BBSsupport.h" + +/** + Create a menu entry by given menu type. + + @param MenuType The Menu type to be created. + + @retval NULL If failed to create the menu. + @return the new menu entry. + +**/ +BM_MENU_ENTRY * +BOpt_CreateMenuEntry ( + UINTN MenuType + ) +{ + BM_MENU_ENTRY *MenuEntry; + UINTN ContextSize; + + // + // Get context size according to menu type + // + switch (MenuType) { + case BM_LOAD_CONTEXT_SELECT: + ContextSize = sizeof (BM_LOAD_CONTEXT); + break; + + case BM_FILE_CONTEXT_SELECT: + ContextSize = sizeof (BM_FILE_CONTEXT); + break; + + case BM_CONSOLE_CONTEXT_SELECT: + ContextSize = sizeof (BM_CONSOLE_CONTEXT); + break; + + case BM_TERMINAL_CONTEXT_SELECT: + ContextSize = sizeof (BM_TERMINAL_CONTEXT); + break; + + case BM_HANDLE_CONTEXT_SELECT: + ContextSize = sizeof (BM_HANDLE_CONTEXT); + break; + + case BM_LEGACY_DEV_CONTEXT_SELECT: + ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT); + break; + + default: + ContextSize = 0; + break; + } + + if (ContextSize == 0) { + return NULL; + } + + // + // Create new menu entry + // + MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY)); + if (MenuEntry == NULL) { + return NULL; + } + + MenuEntry->VariableContext = AllocateZeroPool (ContextSize); + if (MenuEntry->VariableContext == NULL) { + FreePool (MenuEntry); + return NULL; + } + + MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE; + MenuEntry->ContextSelection = MenuType; + return MenuEntry; +} + +/** + Free up all resource allocated for a BM_MENU_ENTRY. + + @param MenuEntry A pointer to BM_MENU_ENTRY. + +**/ +VOID +BOpt_DestroyMenuEntry ( + BM_MENU_ENTRY *MenuEntry + ) +{ + BM_LOAD_CONTEXT *LoadContext; + BM_FILE_CONTEXT *FileContext; + BM_CONSOLE_CONTEXT *ConsoleContext; + BM_TERMINAL_CONTEXT *TerminalContext; + BM_HANDLE_CONTEXT *HandleContext; + BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext; + + // + // Select by the type in Menu entry for current context type + // + switch (MenuEntry->ContextSelection) { + case BM_LOAD_CONTEXT_SELECT: + LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext; + FreePool (LoadContext->FilePathList); + FreePool (LoadContext->LoadOption); + if (LoadContext->OptionalData != NULL) { + FreePool (LoadContext->OptionalData); + } + FreePool (LoadContext); + break; + + case BM_FILE_CONTEXT_SELECT: + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + if (!FileContext->IsRoot) { + FreePool (FileContext->DevicePath); + } else { + if (FileContext->FHandle != NULL) { + FileContext->FHandle->Close (FileContext->FHandle); + } + } + + if (FileContext->FileName != NULL) { + FreePool (FileContext->FileName); + } + if (FileContext->Info != NULL) { + FreePool (FileContext->Info); + } + FreePool (FileContext); + break; + + case BM_CONSOLE_CONTEXT_SELECT: + ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext; + FreePool (ConsoleContext->DevicePath); + FreePool (ConsoleContext); + break; + + case BM_TERMINAL_CONTEXT_SELECT: + TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext; + FreePool (TerminalContext->DevicePath); + FreePool (TerminalContext); + break; + + case BM_HANDLE_CONTEXT_SELECT: + HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext; + FreePool (HandleContext); + break; + + case BM_LEGACY_DEV_CONTEXT_SELECT: + LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext; + FreePool (LegacyDevContext); + + default: + break; + } + + FreePool (MenuEntry->DisplayString); + if (MenuEntry->HelpString != NULL) { + FreePool (MenuEntry->HelpString); + } + + FreePool (MenuEntry); +} + +/** + Get the Menu Entry from the list in Menu Entry List. + + If MenuNumber is great or equal to the number of Menu + Entry in the list, then ASSERT. + + @param MenuOption The Menu Entry List to read the menu entry. + @param MenuNumber The index of Menu Entry. + + @return The Menu Entry. + +**/ +BM_MENU_ENTRY * +BOpt_GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + LIST_ENTRY *List; + + ASSERT (MenuNumber < MenuOption->MenuNumber); + + List = MenuOption->Head.ForwardLink; + for (Index = 0; Index < MenuNumber; Index++) { + List = List->ForwardLink; + } + + NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE); + + return NewMenuEntry; +} + +/** + This function build the FsOptionMenu list which records all + available file system in the system. They includes all instances + of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM + and all type of legacy boot device. + + @param CallbackData BMM context data + + @retval EFI_SUCCESS Success find the file system + @retval EFI_OUT_OF_RESOURCES Can not create menu entry + +**/ +EFI_STATUS +BOpt_FindFileSystem ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN NoBlkIoHandles; + UINTN NoSimpleFsHandles; + UINTN NoLoadFileHandles; + EFI_HANDLE *BlkIoHandle; + EFI_HANDLE *SimpleFsHandle; + EFI_HANDLE *LoadFileHandle; + UINT16 *VolumeLabel; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + UINTN Index; + EFI_STATUS Status; + BM_MENU_ENTRY *MenuEntry; + BM_FILE_CONTEXT *FileContext; + UINT16 *TempStr; + UINTN OptionNumber; + VOID *Buffer; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 DeviceType; + BBS_BBS_DEVICE_PATH BbsDevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN RemovableMedia; + + + NoSimpleFsHandles = 0; + NoLoadFileHandles = 0; + OptionNumber = 0; + InitializeListHead (&FsOptionMenu.Head); + + // + // Locate Handles that support BlockIo protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NoBlkIoHandles, + &BlkIoHandle + ); + if (!EFI_ERROR (Status)) { + + for (Index = 0; Index < NoBlkIoHandles; Index++) { + Status = gBS->HandleProtocol ( + BlkIoHandle[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + + if (EFI_ERROR (Status)) { + continue; + } + + // + // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media + // + if (BlkIo->Media->RemovableMedia) { + Buffer = AllocateZeroPool (BlkIo->Media->BlockSize); + if (NULL == Buffer) { + FreePool (BlkIoHandle); + return EFI_OUT_OF_RESOURCES; + } + + BlkIo->ReadBlocks ( + BlkIo, + BlkIo->Media->MediaId, + 0, + BlkIo->Media->BlockSize, + Buffer + ); + FreePool (Buffer); + } + } + FreePool (BlkIoHandle); + } + + // + // Locate Handles that support Simple File System protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NoSimpleFsHandles, + &SimpleFsHandle + ); + if (!EFI_ERROR (Status)) { + // + // Find all the instances of the File System prototocol + // + for (Index = 0; Index < NoSimpleFsHandles; Index++) { + Status = gBS->HandleProtocol ( + SimpleFsHandle[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (EFI_ERROR (Status)) { + // + // If no block IO exists assume it's NOT a removable media + // + RemovableMedia = FALSE; + } else { + // + // If block IO exists check to see if it's remobable media + // + RemovableMedia = BlkIo->Media->RemovableMedia; + } + + // + // Allocate pool for this load option + // + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + FreePool (SimpleFsHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + FileContext->Handle = SimpleFsHandle[Index]; + MenuEntry->OptionNumber = Index; + FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle); + if (FileContext->FHandle == NULL) { + BOpt_DestroyMenuEntry (MenuEntry); + continue; + } + + MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle)); + FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle); + FileContext->FileName = EfiStrDuplicate (L"\\"); + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + FileContext->IsDir = TRUE; + FileContext->IsRoot = TRUE; + FileContext->IsRemovableMedia = RemovableMedia; + FileContext->IsLoadFile = FALSE; + + // + // Get current file system's Volume Label + // + if (FileContext->Info == NULL) { + VolumeLabel = L"NO FILE SYSTEM INFO"; + } else { + VolumeLabel = FileContext->Info->VolumeLabel; + if (*VolumeLabel == 0x0000) { + VolumeLabel = L"NO VOLUME LABEL"; + } + } + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"%s, [%s]", + VolumeLabel, + TempStr + ); + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoSimpleFsHandles != 0) { + FreePool (SimpleFsHandle); + } + // + // Searching for handles that support Load File protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadFileProtocolGuid, + NULL, + &NoLoadFileHandles, + &LoadFileHandle + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NoLoadFileHandles; Index++) { + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + FreePool (LoadFileHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = TRUE; + FileContext->Handle = LoadFileHandle[Index]; + FileContext->IsRoot = TRUE; + + FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle); + FileContext->FileName = DevicePathToStr (FileContext->DevicePath); + + MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"Load File [%s]", + TempStr + ); + + MenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoLoadFileHandles != 0) { + FreePool (LoadFileHandle); + } + + // + // Add Legacy Boot Option Support Here + // + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID **) &LegacyBios + ); + if (!EFI_ERROR (Status)) { + + for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) { + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = TRUE; + FileContext->IsBootLegacy = TRUE; + DeviceType = (UINT16) Index; + BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH; + BbsDevicePathNode.Header.SubType = BBS_BBS_DP; + SetDevicePathNodeLength ( + &BbsDevicePathNode.Header, + sizeof (BBS_BBS_DEVICE_PATH) + ); + BbsDevicePathNode.DeviceType = DeviceType; + BbsDevicePathNode.StatusFlag = 0; + BbsDevicePathNode.String[0] = 0; + DevicePath = AppendDevicePathNode ( + EndDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode + ); + + FileContext->DevicePath = DevicePath; + MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"Boot Legacy [%s]", + TempStr + ); + MenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + // + // Remember how many file system options are here + // + FsOptionMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + +/** + Free resources allocated in Allocate Rountine. + + @param FreeMenu Menu to be freed +**/ +VOID +BOpt_FreeMenu ( + BM_MENU_OPTION *FreeMenu + ) +{ + BM_MENU_ENTRY *MenuEntry; + while (!IsListEmpty (&FreeMenu->Head)) { + MenuEntry = CR ( + FreeMenu->Head.ForwardLink, + BM_MENU_ENTRY, + Link, + BM_MENU_ENTRY_SIGNATURE + ); + RemoveEntryList (&MenuEntry->Link); + BOpt_DestroyMenuEntry (MenuEntry); + } + FreeMenu->MenuNumber = 0; +} + +/** + Find files under current directory + All files and sub-directories in current directory + will be stored in DirectoryMenu for future use. + + @param CallbackData The BMM context data. + @param MenuEntry The Menu Entry. + + @retval EFI_SUCCESS Get files from current dir successfully. + @return Other value if can't get files from current dir. + +**/ +EFI_STATUS +BOpt_FindFiles ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_ENTRY *MenuEntry + ) +{ + EFI_FILE_HANDLE NewDir; + EFI_FILE_HANDLE Dir; + EFI_FILE_INFO *DirInfo; + UINTN BufferSize; + UINTN DirBufferSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *FileContext; + BM_FILE_CONTEXT *NewFileContext; + UINTN Pass; + EFI_STATUS Status; + UINTN OptionNumber; + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + Dir = FileContext->FHandle; + OptionNumber = 0; + // + // Open current directory to get files from it + // + Status = Dir->Open ( + Dir, + &NewDir, + FileContext->FileName, + EFI_FILE_READ_ONLY, + 0 + ); + if (!FileContext->IsRoot) { + Dir->Close (Dir); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + DirInfo = EfiLibFileInfo (NewDir); + if (DirInfo == NULL) { + return EFI_NOT_FOUND; + } + + if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { + return EFI_INVALID_PARAMETER; + } + + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + + DirBufferSize = sizeof (EFI_FILE_INFO) + 1024; + DirInfo = AllocateZeroPool (DirBufferSize); + if (DirInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Get all files in current directory + // Pass 1 to get Directories + // Pass 2 to get files that are EFI images + // + for (Pass = 1; Pass <= 2; Pass++) { + NewDir->SetPosition (NewDir, 0); + for (;;) { + BufferSize = DirBufferSize; + Status = NewDir->Read (NewDir, &BufferSize, DirInfo); + if (EFI_ERROR (Status) || BufferSize == 0) { + break; + } + + if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) || + ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1) + ) { + // + // Pass 1 is for Directories + // Pass 2 is for file names + // + continue; + } + + if (!(BOpt_IsEfiImageName (DirInfo->FileName) || (DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0)) { + // + // Slip file unless it is a directory entry or a .EFI file + // + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + NewFileContext->Handle = FileContext->Handle; + NewFileContext->FileName = BOpt_AppendFileName ( + FileContext->FileName, + DirInfo->FileName + ); + NewFileContext->FHandle = NewDir; + NewFileContext->DevicePath = FileDevicePath ( + NewFileContext->Handle, + NewFileContext->FileName + ); + NewMenuEntry->HelpString = NULL; + + MenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + FileOptionStrDepository + ); + + NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY); + + if (NewFileContext->IsDir) { + BufferSize = StrLen (DirInfo->FileName) * 2 + 6; + NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize); + + UnicodeSPrint ( + NewMenuEntry->DisplayString, + BufferSize, + L"<%s>", + DirInfo->FileName + ); + + } else { + NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName); + } + + NewFileContext->IsRoot = FALSE; + NewFileContext->IsLoadFile = FALSE; + NewFileContext->IsRemovableMedia = FALSE; + + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link); + } + } + + DirectoryMenu.MenuNumber = OptionNumber; + FreePool (DirInfo); + return EFI_SUCCESS; +} + +/** + Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function. + +**/ +EFI_STATUS +BOpt_GetLegacyOptions ( + VOID + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 HddCount; + HDD_INFO *HddInfo; + UINT16 BbsCount; + BBS_TABLE *BbsTable; + UINT16 Index; + CHAR16 DescString[100]; + UINTN FDNum; + UINTN HDNum; + UINTN CDNum; + UINTN NETNum; + UINTN BEVNum; + + NewMenuEntry = NULL; + HddInfo = NULL; + BbsTable = NULL; + BbsCount = 0; + + // + // Initialize Bbs Table Context from BBS info data + // + InitializeListHead (&LegacyFDMenu.Head); + InitializeListHead (&LegacyHDMenu.Head); + InitializeListHead (&LegacyCDMenu.Head); + InitializeListHead (&LegacyNETMenu.Head); + InitializeListHead (&LegacyBEVMenu.Head); + + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID **) &LegacyBios + ); + if (!EFI_ERROR (Status)) { + Status = LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &HddInfo, + &BbsCount, + &BbsTable + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + FDNum = 0; + HDNum = 0; + CDNum = 0; + NETNum = 0; + BEVNum = 0; + + for (Index = 0; Index < BbsCount; Index++) { + if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) || + (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority) + ) { + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + break; + } + + NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; + NewLegacyDevContext->BbsEntry = &BbsTable[Index]; + NewLegacyDevContext->BbsIndex = Index; + NewLegacyDevContext->BbsCount = BbsCount; + BdsBuildLegacyDevNameString ( + &BbsTable[Index], + Index, + sizeof (DescString), + DescString + ); + NewLegacyDevContext->Description = AllocateCopyPool (StrSize (DescString), DescString); + if (NULL == NewLegacyDevContext->Description) { + break; + } + + NewMenuEntry->DisplayString = NewLegacyDevContext->Description; + NewMenuEntry->HelpString = NULL; + + switch (BbsTable[Index].DeviceType) { + case BBS_FLOPPY: + InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); + FDNum++; + break; + + case BBS_HARDDISK: + InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); + HDNum++; + break; + + case BBS_CDROM: + InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); + CDNum++; + break; + + case BBS_EMBED_NETWORK: + InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); + NETNum++; + break; + + case BBS_BEV_DEVICE: + InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); + BEVNum++; + break; + } + } + + if (Index != BbsCount) { + BOpt_FreeLegacyOptions (); + return EFI_OUT_OF_RESOURCES; + } + + LegacyFDMenu.MenuNumber = FDNum; + LegacyHDMenu.MenuNumber = HDNum; + LegacyCDMenu.MenuNumber = CDNum; + LegacyNETMenu.MenuNumber = NETNum; + LegacyBEVMenu.MenuNumber = BEVNum; + return EFI_SUCCESS; +} + +/** + Free out resouce allocated from Legacy Boot Options. + +**/ +VOID +BOpt_FreeLegacyOptions ( + VOID + ) +{ + BOpt_FreeMenu (&LegacyFDMenu); + BOpt_FreeMenu (&LegacyHDMenu); + BOpt_FreeMenu (&LegacyCDMenu); + BOpt_FreeMenu (&LegacyNETMenu); + BOpt_FreeMenu (&LegacyBEVMenu); +} + +/** + + Build the BootOptionMenu according to BootOrder Variable. + This Routine will access the Boot#### to get EFI_LOAD_OPTION. + + @param CallbackData The BMM context data. + + @return EFI_NOT_FOUND Fail to find "BootOrder" variable. + @return EFI_SUCESS Success build boot option menu. + +**/ +EFI_STATUS +BOpt_GetBootOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Index; + UINT16 BootString[10]; + UINT8 *LoadOptionFromVar; + UINT8 *LoadOption; + UINTN BootOptionSize; + BOOLEAN BootNextFlag; + UINT16 *BootOrderList; + UINTN BootOrderListSize; + UINT16 *BootNext; + UINTN BootNextSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT8 *LoadOptionPtr; + UINTN StringSize; + UINTN OptionalDataSize; + UINT8 *LoadOptionEnd; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN MenuCount; + UINT8 *Ptr; + + MenuCount = 0; + BootOrderListSize = 0; + BootNextSize = 0; + BootOrderList = NULL; + BootNext = NULL; + LoadOptionFromVar = NULL; + BOpt_FreeMenu (&BootOptionMenu); + InitializeListHead (&BootOptionMenu.Head); + + // + // Get the BootOrder from the Var + // + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + if (BootOrderList == NULL) { + return EFI_NOT_FOUND; + } + + // + // Get the BootNext from the Var + // + BootNext = BdsLibGetVariableAndSize ( + L"BootNext", + &gEfiGlobalVariableGuid, + &BootNextSize + ); + + if (BootNext != NULL) { + if (BootNextSize != sizeof (UINT16)) { + FreePool (BootNext); + BootNext = NULL; + } + } + + for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { + UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]); + // + // Get all loadoptions from the VAR + // + LoadOptionFromVar = BdsLibGetVariableAndSize ( + BootString, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (LoadOptionFromVar == NULL) { + continue; + } + + LoadOption = AllocateZeroPool (BootOptionSize); + if (LoadOption == NULL) { + continue; + } + + CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize); + FreePool (LoadOptionFromVar); + + if (BootNext != NULL) { + BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]); + } else { + BootNextFlag = FALSE; + } + + if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) { + FreePool (LoadOption); + continue; + } + // + // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly. + // the buffer allocated already should be freed before returning. + // + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + LoadOptionPtr = LoadOption; + LoadOptionEnd = LoadOption + BootOptionSize; + + NewMenuEntry->OptionNumber = BootOrderList[Index]; + NewLoadContext->LoadOptionModified = FALSE; + NewLoadContext->Deleted = FALSE; + NewLoadContext->IsBootNext = BootNextFlag; + + // + // Is a Legacy Device? + // + Ptr = (UINT8 *) LoadOption; + + // + // Attribute = *(UINT32 *)Ptr; + // + Ptr += sizeof (UINT32); + + // + // FilePathSize = *(UINT16 *)Ptr; + // + Ptr += sizeof (UINT16); + + // + // Description = (CHAR16 *)Ptr; + // + Ptr += StrSize ((CHAR16 *) Ptr); + + // + // Now Ptr point to Device Path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { + NewLoadContext->IsLegacy = TRUE; + } else { + NewLoadContext->IsLegacy = FALSE; + } + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + NewLoadContext->LoadOption = LoadOption; + NewLoadContext->LoadOptionSize = BootOptionSize; + + NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; + NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); + + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize((UINT16*)LoadOptionPtr); + + NewLoadContext->Description = AllocateCopyPool (StrSize((UINT16*)LoadOptionPtr), LoadOptionPtr); + ASSERT (NewLoadContext->Description != NULL); + + NewMenuEntry->DisplayString = NewLoadContext->Description; + + LoadOptionPtr += StringSize; + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionStrDepository + ); + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionHelpStrDepository + ); + LoadOptionPtr += NewLoadContext->FilePathListLength; + + if (LoadOptionPtr < LoadOptionEnd) { + OptionalDataSize = BootOptionSize - + sizeof (UINT32) - + sizeof (UINT16) - + StringSize - + NewLoadContext->FilePathListLength; + + NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); + ASSERT (NewLoadContext->OptionalData != NULL); + CopyMem ( + NewLoadContext->OptionalData, + LoadOptionPtr, + OptionalDataSize + ); + + NewLoadContext->OptionalDataSize = OptionalDataSize; + } + + InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + MenuCount++; + } + + if (BootNext != NULL) { + FreePool (BootNext); + } + if (BootOrderList != NULL) { + FreePool (BootOrderList); + } + BootOptionMenu.MenuNumber = MenuCount; + return EFI_SUCCESS; +} + +/** + + Append file name to existing file name. + + @param Str1 The existing file name + @param Str2 The file name to be appended + + @return Allocate a new string to hold the appended result. + Caller is responsible to free the returned string. + +**/ +CHAR16 * +BOpt_AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ) +{ + UINTN Size1; + UINTN Size2; + UINTN MaxLen; + CHAR16 *Str; + CHAR16 *TmpStr; + CHAR16 *Ptr; + CHAR16 *LastSlash; + + Size1 = StrSize (Str1); + Size2 = StrSize (Str2); + MaxLen = (Size1 + Size2 + sizeof (CHAR16)) / sizeof (CHAR16); + Str = AllocateZeroPool (MaxLen * sizeof (CHAR16)); + ASSERT (Str != NULL); + + TmpStr = AllocateZeroPool (MaxLen * sizeof (CHAR16)); + ASSERT (TmpStr != NULL); + + StrCatS (Str, MaxLen, Str1); + if (!((*Str == '\\') && (*(Str + 1) == 0))) { + StrCatS (Str, MaxLen, L"\\"); + } + + StrCatS (Str, MaxLen, Str2); + + Ptr = Str; + LastSlash = Str; + while (*Ptr != 0) { + if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') { + // + // Convert "\Name\..\" to "\" + // DO NOT convert the .. if it is at the end of the string. This will + // break the .. behavior in changing directories. + // + + // + // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings + // that overlap. + // + StrCpyS (TmpStr, MaxLen, Ptr + 3); + StrCpyS (LastSlash, MaxLen - (UINTN) (LastSlash - Str), TmpStr); + Ptr = LastSlash; + } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') { + // + // Convert a "\.\" to a "\" + // + + // + // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings + // that overlap. + // + StrCpyS (TmpStr, MaxLen, Ptr + 2); + StrCpyS (Ptr, MaxLen - (UINTN) (Ptr - Str), TmpStr); + Ptr = LastSlash; + } else if (*Ptr == '\\') { + LastSlash = Ptr; + } + + Ptr++; + } + + FreePool (TmpStr); + + return Str; +} + +/** + + Check whether current FileName point to a valid + Efi Image File. + + @param FileName File need to be checked. + + @retval TRUE Is Efi Image + @retval FALSE Not a valid Efi Image + +**/ +BOOLEAN +BOpt_IsEfiImageName ( + IN UINT16 *FileName + ) +{ + // + // Search for ".efi" extension + // + while (*FileName != L'\0') { + if (FileName[0] == '.') { + if (FileName[1] == 'e' || FileName[1] == 'E') { + if (FileName[2] == 'f' || FileName[2] == 'F') { + if (FileName[3] == 'i' || FileName[3] == 'I') { + return TRUE; + } else if (FileName[3] == 0x0000) { + return FALSE; + } + } else if (FileName[2] == 0x0000) { + return FALSE; + } + } else if (FileName[1] == 0x0000) { + return FALSE; + } + } + + FileName += 1; + } + + return FALSE; +} + +/** + + Check whether current FileName point to a valid Efi Application + + @param Dir Pointer to current Directory + @param FileName Pointer to current File name. + + @retval TRUE Is a valid Efi Application + @retval FALSE not a valid Efi Application + +**/ +BOOLEAN +BOpt_IsEfiApp ( + IN EFI_FILE_HANDLE Dir, + IN UINT16 *FileName + ) +{ + UINTN BufferSize; + EFI_IMAGE_DOS_HEADER DosHdr; + UINT16 Subsystem; + EFI_FILE_HANDLE File; + EFI_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr; + + Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + BufferSize = sizeof (EFI_IMAGE_DOS_HEADER); + File->Read (File, &BufferSize, &DosHdr); + if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + File->Close (File); + return FALSE; + } + + File->SetPosition (File, DosHdr.e_lfanew); + BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); + File->Read (File, &BufferSize, &PeHdr); + if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + File->Close (File); + return FALSE; + } + // + // Determine PE type and read subsytem + // + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Subsystem = PeHdr.Pe32.OptionalHeader.Subsystem; + } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Subsystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem; + } else { + return FALSE; + } + + if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + File->Close (File); + return TRUE; + } else { + File->Close (File); + return FALSE; + } +} + +/** + + Find drivers that will be added as Driver#### variables from handles + in current system environment + All valid handles in the system except those consume SimpleFs, LoadFile + are stored in DriverMenu for future use. + + @retval EFI_SUCCESS The function complets successfully. + @return Other value if failed to build the DriverMenu. + +**/ +EFI_STATUS +BOpt_FindDrivers ( + VOID + ) +{ + UINTN NoDevicePathHandles; + EFI_HANDLE *DevicePathHandle; + UINTN Index; + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + BM_HANDLE_CONTEXT *NewHandleContext; + EFI_HANDLE CurHandle; + UINTN OptionNumber; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs; + EFI_LOAD_FILE_PROTOCOL *LoadFile; + + SimpleFs = NULL; + LoadFile = NULL; + + InitializeListHead (&DriverMenu.Head); + + // + // At first, get all handles that support Device Path + // protocol which is the basic requirement for + // Driver#### + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &NoDevicePathHandles, + &DevicePathHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OptionNumber = 0; + for (Index = 0; Index < NoDevicePathHandles; Index++) { + CurHandle = DevicePathHandle[Index]; + + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **) &SimpleFs + ); + if (Status == EFI_SUCCESS) { + continue; + } + + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiLoadFileProtocolGuid, + (VOID **) &LoadFile + ); + if (Status == EFI_SUCCESS) { + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + FreePool (DevicePathHandle); + return EFI_OUT_OF_RESOURCES; + } + + NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; + NewHandleContext->Handle = CurHandle; + NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle); + NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath); + NewMenuEntry->HelpString = NULL; + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link); + + } + + if (DevicePathHandle != NULL) { + FreePool (DevicePathHandle); + } + + DriverMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + +/** + + Get the Option Number that has not been allocated for use. + + @param Type The type of Option. + + @return The available Option Number. + +**/ +UINT16 +BOpt_GetOptionNumber ( + CHAR16 *Type + ) +{ + UINT16 *OrderList; + UINTN OrderListSize; + UINTN Index; + CHAR16 StrTemp[20]; + UINT16 *OptionBuffer; + UINT16 OptionNumber; + UINTN OptionSize; + + OrderListSize = 0; + OrderList = NULL; + OptionNumber = 0; + Index = 0; + + UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type); + + OrderList = BdsLibGetVariableAndSize ( + StrTemp, + &gEfiGlobalVariableGuid, + &OrderListSize + ); + + for (OptionNumber = 0; ; OptionNumber++) { + if (OrderList != NULL) { + for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) { + if (OptionNumber == OrderList[Index]) { + break; + } + } + } + + if (Index < OrderListSize / sizeof (UINT16)) { + // + // The OptionNumber occurs in the OrderList, continue to use next one + // + continue; + } + UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber); + DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp)); + OptionBuffer = BdsLibGetVariableAndSize ( + StrTemp, + &gEfiGlobalVariableGuid, + &OptionSize + ); + if (NULL == OptionBuffer) { + // + // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it + // + break; + } + } + + return OptionNumber; +} + +/** + + Get the Option Number for Boot#### that does not used. + + @return The available Option Number. + +**/ +UINT16 +BOpt_GetBootOptionNumber ( + VOID + ) +{ + return BOpt_GetOptionNumber (L"Boot"); +} + +/** + + Get the Option Number for Driver#### that does not used. + + @return The unused Option Number. + +**/ +UINT16 +BOpt_GetDriverOptionNumber ( + VOID + ) +{ + return BOpt_GetOptionNumber (L"Driver"); +} + +/** + + Build up all DriverOptionMenu + + @param CallbackData The BMM context data. + + @retval EFI_SUCESS The functin completes successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation. + @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable. + +**/ +EFI_STATUS +BOpt_GetDriverOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Index; + UINT16 DriverString[12]; + UINT8 *LoadOptionFromVar; + UINT8 *LoadOption; + UINTN DriverOptionSize; + + UINT16 *DriverOrderList; + UINTN DriverOrderListSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT8 *LoadOptionPtr; + UINTN StringSize; + UINTN OptionalDataSize; + UINT8 *LoadOptionEnd; + + DriverOrderListSize = 0; + DriverOrderList = NULL; + DriverOptionSize = 0; + LoadOptionFromVar = NULL; + BOpt_FreeMenu (&DriverOptionMenu); + InitializeListHead (&DriverOptionMenu.Head); + // + // Get the DriverOrder from the Var + // + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + if (DriverOrderList == NULL) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + DriverOrderList[Index] + ); + // + // Get all loadoptions from the VAR + // + LoadOptionFromVar = BdsLibGetVariableAndSize ( + DriverString, + &gEfiGlobalVariableGuid, + &DriverOptionSize + ); + if (LoadOptionFromVar == NULL) { + continue; + } + + LoadOption = AllocateZeroPool (DriverOptionSize); + if (LoadOption == NULL) { + continue; + } + + CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize); + FreePool (LoadOptionFromVar); + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + LoadOptionPtr = LoadOption; + LoadOptionEnd = LoadOption + DriverOptionSize; + NewMenuEntry->OptionNumber = DriverOrderList[Index]; + NewLoadContext->LoadOptionModified = FALSE; + NewLoadContext->Deleted = FALSE; + NewLoadContext->IsLegacy = FALSE; + + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + NewLoadContext->LoadOption = LoadOption; + NewLoadContext->LoadOptionSize = DriverOptionSize; + + NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; + NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); + + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize ((UINT16 *) LoadOptionPtr); + NewLoadContext->Description = AllocateZeroPool (StringSize); + ASSERT (NewLoadContext->Description != NULL); + CopyMem ( + NewLoadContext->Description, + (UINT16 *) LoadOptionPtr, + StringSize + ); + NewMenuEntry->DisplayString = NewLoadContext->Description; + + LoadOptionPtr += StringSize; + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionStrDepository + ); + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionHelpStrDepository + ); + LoadOptionPtr += NewLoadContext->FilePathListLength; + + if (LoadOptionPtr < LoadOptionEnd) { + OptionalDataSize = DriverOptionSize - + sizeof (UINT32) - + sizeof (UINT16) - + StringSize - + NewLoadContext->FilePathListLength; + + NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); + ASSERT (NewLoadContext->OptionalData != NULL); + CopyMem ( + NewLoadContext->OptionalData, + LoadOptionPtr, + OptionalDataSize + ); + + NewLoadContext->OptionalDataSize = OptionalDataSize; + } + + InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); + + } + + if (DriverOrderList != NULL) { + FreePool (DriverOrderList); + } + DriverOptionMenu.MenuNumber = Index; + return EFI_SUCCESS; + +} + +/** + Get option number according to Boot#### and BootOrder variable. + The value is saved as #### + 1. + + @param CallbackData The BMM context data. +**/ +VOID +GetBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BMM_FAKE_NV_DATA *BmmConfig; + UINT16 Index; + UINT16 OptionOrderIndex; + UINTN DeviceType; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + + ASSERT (CallbackData != NULL); + + DeviceType = (UINTN) -1; + BmmConfig = &CallbackData->BmmFakeNvData; + ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder)); + + for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) && + (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0])))); + Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewLoadContext->IsLegacy) { + if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) { + DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType; + } else { + // + // Only show one legacy boot option for the same device type + // assuming the boot options are grouped by the device type + // + continue; + } + } + BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1); + } +} + +/** + According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV + devices list . + + @param CallbackData The BMM context data. +**/ +VOID +GetLegacyDeviceOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Index; + UINTN OptionIndex; + UINT16 PageIdList[5]; + UINTN PageNum; + UINTN VarSize; + UINT8 *VarData; + UINT8 *WorkingVarData; + LEGACY_DEV_ORDER_ENTRY *DevOrder; + UINT16 VarDevOrder; + UINT8 *DisMap; + BM_MENU_OPTION *OptionMenu; + BBS_TYPE BbsType; + UINT8 *LegacyOrder; + UINT8 *OldData; + UINTN Pos; + UINTN Bit; + + ASSERT (CallbackData != NULL); + + PageIdList[0] = FORM_SET_FD_ORDER_ID; + PageIdList[1] = FORM_SET_HD_ORDER_ID; + PageIdList[2] = FORM_SET_CD_ORDER_ID; + PageIdList[3] = FORM_SET_NET_ORDER_ID; + PageIdList[4] = FORM_SET_BEV_ORDER_ID; + OptionMenu = NULL; + BbsType = 0; + LegacyOrder = NULL; + OldData = NULL; + DisMap = ZeroMem (CallbackData->BmmFakeNvData.DisableMap, sizeof (CallbackData->BmmFakeNvData.DisableMap)); + PageNum = sizeof (PageIdList) / sizeof (PageIdList[0]); + VarData = BdsLibGetVariableAndSize ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + &VarSize + ); + + for (Index = 0; Index < PageNum; Index++) { + switch (PageIdList[Index]) { + + case FORM_SET_FD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; + BbsType = BBS_FLOPPY; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD; + OldData = CallbackData->BmmOldFakeNVData.LegacyFD; + break; + + case FORM_SET_HD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; + BbsType = BBS_HARDDISK; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD; + OldData = CallbackData->BmmOldFakeNVData.LegacyHD; + break; + + case FORM_SET_CD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; + BbsType = BBS_CDROM; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD; + OldData = CallbackData->BmmOldFakeNVData.LegacyCD; + break; + + case FORM_SET_NET_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; + BbsType = BBS_EMBED_NETWORK; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET; + OldData = CallbackData->BmmOldFakeNVData.LegacyNET; + break; + + default: + ASSERT (PageIdList[Index] == FORM_SET_BEV_ORDER_ID); + OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; + BbsType = BBS_BEV_DEVICE; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV; + OldData = CallbackData->BmmOldFakeNVData.LegacyBEV; + break; + } + + if (NULL != VarData) { + WorkingVarData = VarData; + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData; + while (WorkingVarData < VarData + VarSize) { + if (DevOrder->BbsType == BbsType) { + break; + } + + WorkingVarData = (UINT8 *)((UINTN)WorkingVarData + sizeof (BBS_TYPE)); + WorkingVarData += *(UINT16 *) WorkingVarData; + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData; + } + for (OptionIndex = 0; OptionIndex < OptionMenu->MenuNumber; OptionIndex++) { + VarDevOrder = *(UINT16 *) ((UINTN) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + OptionIndex * sizeof (UINT16)); + if (0xFF00 == (VarDevOrder & 0xFF00)) { + LegacyOrder[OptionIndex] = 0xFF; + Pos = (VarDevOrder & 0xFF) / 8; + Bit = 7 - ((VarDevOrder & 0xFF) % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + } else { + LegacyOrder[OptionIndex] = (UINT8) (VarDevOrder & 0xFF); + } + } + CopyMem (OldData, LegacyOrder, 100); + } + } +} + +/** + Get driver option order from globalc DriverOptionMenu. + + @param CallbackData The BMM context data. + +**/ +VOID +GetDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BMM_FAKE_NV_DATA *BmmConfig; + UINT16 Index; + UINT16 OptionOrderIndex; + UINTN DeviceType; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + + ASSERT (CallbackData != NULL); + + DeviceType = (UINTN) -1; + BmmConfig = &CallbackData->BmmFakeNvData; + ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder)); + + for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) && + (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0])))); + Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewLoadContext->IsLegacy) { + if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) { + DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType; + } else { + // + // Only show one legacy boot option for the same device type + // assuming the boot options are grouped by the device type + // + continue; + } + } + BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1); + } +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c new file mode 100644 index 0000000000..1854b98c36 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c @@ -0,0 +1,1198 @@ +/** @file + handles console redirection from boot manager + +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 +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 "BootMaint.h" + +UART_FLOW_CONTROL_DEVICE_PATH mFlowControlDevicePath = +{ + { + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + { + (UINT8)(sizeof(UART_FLOW_CONTROL_DEVICE_PATH)), + (UINT8)((sizeof(UART_FLOW_CONTROL_DEVICE_PATH)) >> 8) + } + }, + DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL, + UART_FLOW_CONTROL_HARDWARE +}; + +/** + Check the device path node whether it's the Flow Control node or not. + + @param[in] FlowControl The device path node to be checked. + + @retval TRUE It's the Flow Control node. + @retval FALSE It's not. + +**/ +BOOLEAN +IsUartFlowControlNode ( + IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl + ) +{ + return (BOOLEAN) ( + (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) && + (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid)) + ); +} + +/** + Check whether the device path node is ISA Serial Node. + + @param Acpi Device path node to be checked + + @retval TRUE It's ISA Serial Node. + @retval FALSE It's NOT ISA Serial Node. + +**/ +BOOLEAN +IsIsaSerialNode ( + IN ACPI_HID_DEVICE_PATH *Acpi + ) +{ + return (BOOLEAN) ( + (DevicePathType (Acpi) == ACPI_DEVICE_PATH) && + (DevicePathSubType (Acpi) == ACPI_DP) && + (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501)) + ); +} + +/** + Update Com Ports attributes from DevicePath + + @param DevicePath DevicePath that contains Com ports + + @retval EFI_SUCCESS The update is successful. + +**/ +EFI_STATUS +UpdateComAttributeFromVariable ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Update the multi-instance device path of Terminal Device based on + the global TerminalMenu. If ChangeTernimal is TRUE, the terminal + device path in the Terminal Device in TerminalMenu is also updated. + + @param DevicePath The multi-instance device path. + @param ChangeTerminal TRUE, then device path in the Terminal Device + in TerminalMenu is also updated; FALSE, no update. + + @return EFI_SUCCESS The function completes successfully. + +**/ +EFI_STATUS +ChangeTerminalDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + IN BOOLEAN ChangeTerminal + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *Node1; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UART_DEVICE_PATH *Uart1; + UINTN Com; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode; + + Node = *DevicePath; + Node = NextDevicePathNode (Node); + Com = 0; + while (!IsDevicePathEnd (Node)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (IsIsaSerialNode (Acpi)) { + CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); + } + + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com); + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + CopyMem ( + &Uart->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + + FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node); + if (IsUartFlowControlNode (FlowControlNode)) { + FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl; + } else { + // + // Append the Flow control device node when user enable flow control. + // + if (NewTerminalContext->FlowControl != 0) { + mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl; + *DevicePath = AppendDevicePathNode ( + *DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath) + ); + } + } + + // + // Change the device path in the ComPort + // + if (ChangeTerminal) { + Node1 = NewTerminalContext->DevicePath; + Node1 = NextDevicePathNode (Node1); + while (!IsDevicePathEnd (Node1)) { + if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) { + Uart1 = (UART_DEVICE_PATH *) Node1; + CopyMem ( + &Uart1->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart1->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart1->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart1->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + break; + } + // + // end if + // + Node1 = NextDevicePathNode (Node1); + } + // + // end while + // + break; + } + } + + Node = NextDevicePathNode (Node); + } + + return EFI_SUCCESS; + +} + +/** + Update the device path that describing a terminal device + based on the new BaudRate, Data Bits, parity and Stop Bits + set. + + @param DevicePath terminal device's path + +**/ +VOID +ChangeVariableDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UINTN Com; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + + Node = DevicePath; + Node = NextDevicePathNode (Node); + Com = 0; + while (!IsDevicePathEnd (Node)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (IsIsaSerialNode (Acpi)) { + CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); + } + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + NewMenuEntry = BOpt_GetMenuEntry ( + &TerminalMenu, + Com + ); + ASSERT (NewMenuEntry != NULL); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + Uart = (UART_DEVICE_PATH *) Node; + CopyMem ( + &Uart->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + } + + Node = NextDevicePathNode (Node); + } +} + +/** + Retrieve ACPI UID of UART from device path + + @param Handle The handle for the UART device. + @param AcpiUid The ACPI UID on output. + + @retval TRUE Find valid UID from device path + @retval FALSE Can't find + +**/ +BOOLEAN +RetrieveUartUid ( + IN EFI_HANDLE Handle, + IN OUT UINT32 *AcpiUid + ) +{ + EFI_STATUS Status; + ACPI_HID_DEVICE_PATH *Acpi; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + Acpi = NULL; + for (; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_UART_DP)) { + break; + } + // + // Acpi points to the node before the Uart node + // + Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath; + } + + if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { + if (AcpiUid != NULL) { + CopyMem (AcpiUid, &Acpi->UID, sizeof (UINT32)); + } + return TRUE; + } else { + return FALSE; + } +} + +/** + Sort Uart handles array with Acpi->UID from low to high. + + @param Handles EFI_SERIAL_IO_PROTOCOL handle buffer + @param NoHandles EFI_SERIAL_IO_PROTOCOL handle count +**/ +VOID +SortedUartHandle ( + IN EFI_HANDLE *Handles, + IN UINTN NoHandles + ) +{ + UINTN Index1; + UINTN Index2; + UINTN Position; + UINT32 AcpiUid1; + UINT32 AcpiUid2; + UINT32 TempAcpiUid; + EFI_HANDLE TempHandle; + + for (Index1 = 0; Index1 < NoHandles-1; Index1++) { + if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) { + continue; + } + TempHandle = Handles[Index1]; + Position = Index1; + TempAcpiUid = AcpiUid1; + + for (Index2 = Index1+1; Index2 < NoHandles; Index2++) { + if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) { + continue; + } + if (AcpiUid2 < TempAcpiUid) { + TempAcpiUid = AcpiUid2; + TempHandle = Handles[Index2]; + Position = Index2; + } + } + Handles[Position] = Handles[Index1]; + Handles[Index1] = TempHandle; + } +} + +/** + Test whether DevicePath is a valid Terminal + + + @param DevicePath DevicePath to be checked + @param Termi If DevicePath is valid Terminal, terminal type is returned. + @param Com If DevicePath is valid Terminal, Com Port type is returned. + + @retval TRUE If DevicePath point to a Terminal. + @retval FALSE If DevicePath does not point to a Terminal. + +**/ +BOOLEAN +IsTerminalDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT TYPE_OF_TERMINAL *Termi, + OUT UINTN *Com + ); + +/** + Build a list containing all serial devices. + + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_UNSUPPORTED No serial ports present. + +**/ +EFI_STATUS +LocateSerialIo ( + VOID + ) +{ + UINTN Index; + UINTN Index2; + UINTN NoHandles; + EFI_HANDLE *Handles; + EFI_STATUS Status; + ACPI_HID_DEVICE_PATH *Acpi; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; + EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + VENDOR_DEVICE_PATH Vendor; + UINT32 FlowControl; + // + // Get all handles that have SerialIo protocol installed + // + InitializeListHead (&TerminalMenu.Head); + TerminalMenu.MenuNumber = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSerialIoProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + // + // No serial ports present + // + return EFI_UNSUPPORTED; + } + + // + // Sort Uart handles array with Acpi->UID from low to high + // then Terminal menu can be built from low Acpi->UID to high Acpi->UID + // + SortedUartHandle (Handles, NoHandles); + + for (Index = 0; Index < NoHandles; Index++) { + // + // Check to see whether the handle has DevicePath Protocol installed + // + gBS->HandleProtocol ( + Handles[Index], + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + + Acpi = NULL; + for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + break; + } + // + // Acpi points to the node before Uart node + // + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + } + + if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { + NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT); + if (NewMenuEntry == NULL) { + FreePool (Handles); + return EFI_OUT_OF_RESOURCES; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32)); + NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath); + // + // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system! + // coz' the misc data for each platform is not correct, actually it's the device path stored in + // datahub which is not completed, so a searching for end of device path will enter a + // dead-loop. + // + NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath); + if (NULL == NewMenuEntry->DisplayString) { + NewMenuEntry->DisplayString = DevicePathToStr (DevicePath); + } + + NewMenuEntry->HelpString = NULL; + + gBS->HandleProtocol ( + Handles[Index], + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo + ); + + CopyMem ( + &NewTerminalContext->BaudRate, + &SerialIo->Mode->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &NewTerminalContext->DataBits, + &SerialIo->Mode->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->Parity, + &SerialIo->Mode->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->StopBits, + &SerialIo->Mode->StopBits, + sizeof (UINT8) + ); + + NewTerminalContext->FlowControl = 0; + SerialIo->GetControl(SerialIo, &FlowControl); + if ((FlowControl & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) != 0) { + NewTerminalContext->FlowControl = UART_FLOW_CONTROL_HARDWARE; + } + + InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link); + TerminalMenu.MenuNumber++; + } + } + if (Handles != NULL) { + FreePool (Handles); + } + + // + // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var + // + OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid); + InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid); + ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid); + if (OutDevicePath != NULL) { + UpdateComAttributeFromVariable (OutDevicePath); + } + + if (InpDevicePath != NULL) { + UpdateComAttributeFromVariable (InpDevicePath); + } + + if (ErrDevicePath != NULL) { + UpdateComAttributeFromVariable (ErrDevicePath); + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + NewTerminalContext->TerminalType = 0; + NewTerminalContext->IsConIn = FALSE; + NewTerminalContext->IsConOut = FALSE; + NewTerminalContext->IsStdErr = FALSE; + + Vendor.Header.Type = MESSAGING_DEVICE_PATH; + Vendor.Header.SubType = MSG_VENDOR_DP; + + for (Index2 = 0; Index2 < 4; Index2++) { + CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID)); + SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); + NewDevicePath = AppendDevicePathNode ( + NewTerminalContext->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Vendor + ); + if (NewMenuEntry->HelpString != NULL) { + FreePool (NewMenuEntry->HelpString); + } + // + // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath); + // NewMenuEntry->DisplayString = NewMenuEntry->HelpString; + // + NewMenuEntry->HelpString = NULL; + + if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) { + NewTerminalContext->IsConOut = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + + if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) { + NewTerminalContext->IsConIn = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + + if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) { + NewTerminalContext->IsStdErr = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + } + } + + return EFI_SUCCESS; +} + +/** + Update Com Ports attributes from DevicePath + + @param DevicePath DevicePath that contains Com ports + + @retval EFI_SUCCESS The update is successful. + @retval EFI_NOT_FOUND Can not find specific menu entry +**/ +EFI_STATUS +UpdateComAttributeFromVariable ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *SerialNode; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UART_DEVICE_PATH *Uart1; + UINTN TerminalNumber; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + UINTN Index; + UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode; + BOOLEAN HasFlowControlNode; + + HasFlowControlNode = FALSE; + Node = DevicePath; + Node = NextDevicePathNode (Node); + TerminalNumber = 0; + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + while (!IsDevicePathEnd (Node)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (IsIsaSerialNode (Acpi)) { + CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32)); + } + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + CopyMem ( + &NewTerminalContext->BaudRate, + &Uart->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &NewTerminalContext->DataBits, + &Uart->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->Parity, + &Uart->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->StopBits, + &Uart->StopBits, + sizeof (UINT8) + ); + + FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node); + if (IsUartFlowControlNode (FlowControlNode)) { + HasFlowControlNode = TRUE; + NewTerminalContext->FlowControl = (UINT8) ReadUnaligned32 (&FlowControlNode->FlowControlMap); + } else if (NewTerminalContext->FlowControl != 0) { + // + // No Flow Control device path node, assumption no Flow control + // + NewTerminalContext->FlowControl = 0; + } + + SerialNode = NewTerminalContext->DevicePath; + SerialNode = NextDevicePathNode (SerialNode); + while (!IsDevicePathEnd (SerialNode)) { + if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) { + // + // Update following device paths according to + // previous acquired uart attributes + // + Uart1 = (UART_DEVICE_PATH *) SerialNode; + CopyMem ( + &Uart1->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart1->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + CopyMem ( + &Uart1->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + CopyMem ( + &Uart1->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + + FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (SerialNode); + if (IsUartFlowControlNode (FlowControlNode)) { + FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl; + } else { + if (HasFlowControlNode) { + mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl; + NewTerminalContext->DevicePath = AppendDevicePathNode ( + NewTerminalContext->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath) + ); + } + } + break; + } + + SerialNode = NextDevicePathNode (SerialNode); + } + // + // end while + // + } + + Node = NextDevicePathNode (Node); + } + // + // end while + // + } + + return EFI_SUCCESS; +} + +/** + Build up Console Menu based on types passed in. The type can + be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT + and BM_CONSOLE_ERR_CONTEXT_SELECT. + + @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT + and BM_CONSOLE_ERR_CONTEXT_SELECT. + + @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined. + @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev", + "ConInDev" or "ConErrDev" doesn't exists. + @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations. + @retval EFI_SUCCESS Function completes successfully. + +**/ +EFI_STATUS +GetConsoleMenu ( + IN UINTN ConsoleMenuType + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *AllDevicePath; + EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + UINTN AllCount; + UINTN Index; + UINTN Index2; + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + TYPE_OF_TERMINAL Terminal; + UINTN Com; + BM_MENU_OPTION *ConsoleMenu; + + DevicePath = NULL; + AllDevicePath = NULL; + AllCount = 0; + switch (ConsoleMenuType) { + case BM_CONSOLE_IN_CONTEXT_SELECT: + ConsoleMenu = &ConsoleInpMenu; + DevicePath = EfiLibGetVariable ( + L"ConIn", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ConInDev", + &gEfiGlobalVariableGuid + ); + break; + + case BM_CONSOLE_OUT_CONTEXT_SELECT: + ConsoleMenu = &ConsoleOutMenu; + DevicePath = EfiLibGetVariable ( + L"ConOut", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ConOutDev", + &gEfiGlobalVariableGuid + ); + break; + + case BM_CONSOLE_ERR_CONTEXT_SELECT: + ConsoleMenu = &ConsoleErrMenu; + DevicePath = EfiLibGetVariable ( + L"ErrOut", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ErrOutDev", + &gEfiGlobalVariableGuid + ); + break; + + default: + return EFI_UNSUPPORTED; + } + + if (NULL == AllDevicePath) { + return EFI_NOT_FOUND; + } + + InitializeListHead (&ConsoleMenu->Head); + + AllCount = EfiDevicePathInstanceCount (AllDevicePath); + ConsoleMenu->MenuNumber = 0; + // + // Following is menu building up for Console Devices selected. + // + MultiDevicePath = AllDevicePath; + Index2 = 0; + for (Index = 0; Index < AllCount; Index++) { + DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size); + + NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewMenuEntry->OptionNumber = Index2; + + NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst); + ASSERT (NewConsoleContext->DevicePath != NULL); + NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath); + if (NULL == NewMenuEntry->DisplayString) { + NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath); + } + + NewConsoleContext->IsTerminal = IsTerminalDevicePath ( + NewConsoleContext->DevicePath, + &Terminal, + &Com + ); + + NewConsoleContext->IsActive = BdsLibMatchDevicePaths ( + DevicePath, + NewConsoleContext->DevicePath + ); + + if (NewConsoleContext->IsTerminal) { + BOpt_DestroyMenuEntry (NewMenuEntry); + } else { + Index2++; + ConsoleMenu->MenuNumber++; + InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); + } + } + + return EFI_SUCCESS; +} + +/** + Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + + @retval EFI_SUCCESS The function always complete successfully. + +**/ +EFI_STATUS +GetAllConsoles ( + VOID + ) +{ + GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT); + GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT); + GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT); + return EFI_SUCCESS; +} + +/** + Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + + @retval EFI_SUCCESS The function always complete successfully. +**/ +EFI_STATUS +FreeAllConsoles ( + VOID + ) +{ + BOpt_FreeMenu (&ConsoleOutMenu); + BOpt_FreeMenu (&ConsoleInpMenu); + BOpt_FreeMenu (&ConsoleErrMenu); + BOpt_FreeMenu (&TerminalMenu); + return EFI_SUCCESS; +} + +/** + Test whether DevicePath is a valid Terminal + + + @param DevicePath DevicePath to be checked + @param Termi If DevicePath is valid Terminal, terminal type is returned. + @param Com If DevicePath is valid Terminal, Com Port type is returned. + + @retval TRUE If DevicePath point to a Terminal. + @retval FALSE If DevicePath does not point to a Terminal. + +**/ +BOOLEAN +IsTerminalDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT TYPE_OF_TERMINAL *Termi, + OUT UINTN *Com + ) +{ + BOOLEAN IsTerminal; + EFI_DEVICE_PATH_PROTOCOL *Node; + VENDOR_DEVICE_PATH *Vendor; + UART_DEVICE_PATH *Uart; + ACPI_HID_DEVICE_PATH *Acpi; + + IsTerminal = FALSE; + + Uart = NULL; + Vendor = NULL; + Acpi = NULL; + for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { + // + // Vendor points to the node before the End node + // + Vendor = (VENDOR_DEVICE_PATH *) Node; + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + } + + if (Uart == NULL) { + // + // Acpi points to the node before the UART node + // + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + } + } + + if (Vendor == NULL || + DevicePathType (Vendor) != MESSAGING_DEVICE_PATH || + DevicePathSubType (Vendor) != MSG_VENDOR_DP || + Uart == NULL) { + return FALSE; + } + + // + // There are four kinds of Terminal types + // check to see whether this devicepath + // is one of that type + // + if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[0])) { + *Termi = TerminalTypePcAnsi; + IsTerminal = TRUE; + } else { + if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[1])) { + *Termi = TerminalTypeVt100; + IsTerminal = TRUE; + } else { + if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[2])) { + *Termi = TerminalTypeVt100Plus; + IsTerminal = TRUE; + } else { + if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[3])) { + *Termi = TerminalTypeVtUtf8; + IsTerminal = TRUE; + } else { + IsTerminal = FALSE; + } + } + } + } + + if (!IsTerminal) { + return FALSE; + } + + if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { + CopyMem (Com, &Acpi->UID, sizeof (UINT32)); + } else { + return FALSE; + } + + return TRUE; +} + +/** + Get mode number according to column and row + + @param CallbackData The BMM context data. +**/ +VOID +GetConsoleOutMode ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Col; + UINTN Row; + UINTN CurrentCol; + UINTN CurrentRow; + UINTN Mode; + UINTN MaxMode; + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + + ConOut = gST->ConOut; + MaxMode = (UINTN) (ConOut->Mode->MaxMode); + + CurrentCol = PcdGet32 (PcdSetupConOutColumn); + CurrentRow = PcdGet32 (PcdSetupConOutRow); + for (Mode = 0; Mode < MaxMode; Mode++) { + Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); + if (!EFI_ERROR(Status)) { + if (CurrentCol == Col && CurrentRow == Row) { + CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode; + break; + } + } + } +} + +/** + + Initialize console input device check box to ConsoleInCheck[MAX_MENU_NUMBER] + in BMM_FAKE_NV_DATA structure. + + @param CallbackData The BMM context data. + +**/ +VOID +GetConsoleInCheck ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT16 Index; + BM_MENU_ENTRY *NewMenuEntry; + UINT8 *ConInCheck; + BM_CONSOLE_CONTEXT *NewConsoleContext; + + ASSERT (CallbackData != NULL); + + ConInCheck = &CallbackData->BmmFakeNvData.ConsoleInCheck[0]; + for (Index = 0; ((Index < ConsoleInpMenu.MenuNumber) && \ + (Index < MAX_MENU_NUMBER)) ; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ConInCheck[Index] = NewConsoleContext->IsActive; + } +} + +/** + + Initialize console output device check box to ConsoleOutCheck[MAX_MENU_NUMBER] + in BMM_FAKE_NV_DATA structure. + + @param CallbackData The BMM context data. + +**/ +VOID +GetConsoleOutCheck ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT16 Index; + BM_MENU_ENTRY *NewMenuEntry; + UINT8 *ConOutCheck; + BM_CONSOLE_CONTEXT *NewConsoleContext; + + ASSERT (CallbackData != NULL); + ConOutCheck = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0]; + for (Index = 0; ((Index < ConsoleOutMenu.MenuNumber) && \ + (Index < MAX_MENU_NUMBER)) ; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ConOutCheck[Index] = NewConsoleContext->IsActive; + } +} + +/** + + Initialize standard error output device check box to ConsoleErrCheck[MAX_MENU_NUMBER] + in BMM_FAKE_NV_DATA structure. + + @param CallbackData The BMM context data. + +**/ +VOID +GetConsoleErrCheck ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT16 Index; + BM_MENU_ENTRY *NewMenuEntry; + UINT8 *ConErrCheck; + BM_CONSOLE_CONTEXT *NewConsoleContext; + + ASSERT (CallbackData != NULL); + ConErrCheck = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0]; + for (Index = 0; ((Index < ConsoleErrMenu.MenuNumber) && \ + (Index < MAX_MENU_NUMBER)) ; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ConErrCheck[Index] = NewConsoleContext->IsActive; + } +} + +/** + + Initialize terminal attributes (baudrate, data rate, stop bits, parity and terminal type) + to BMM_FAKE_NV_DATA structure. + + @param CallbackData The BMM context data. + +**/ +VOID +GetTerminalAttribute ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BMM_FAKE_NV_DATA *CurrentFakeNVMap; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + UINT16 TerminalIndex; + UINT8 AttributeIndex; + + ASSERT (CallbackData != NULL); + + CurrentFakeNVMap = &CallbackData->BmmFakeNvData; + for (TerminalIndex = 0; ((TerminalIndex < TerminalMenu.MenuNumber) && \ + (TerminalIndex < MAX_MENU_NUMBER)); TerminalIndex++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalIndex); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + for (AttributeIndex = 0; AttributeIndex < sizeof (BaudRateList) / sizeof (BaudRateList [0]); AttributeIndex++) { + if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[AttributeIndex].Value)) { + NewTerminalContext->BaudRateIndex = AttributeIndex; + break; + } + } + for (AttributeIndex = 0; AttributeIndex < sizeof (DataBitsList) / sizeof (DataBitsList[0]); AttributeIndex++) { + if (NewTerminalContext->DataBits == (UINT64) (DataBitsList[AttributeIndex].Value)) { + NewTerminalContext->DataBitsIndex = AttributeIndex; + break; + } + } + + for (AttributeIndex = 0; AttributeIndex < sizeof (ParityList) / sizeof (ParityList[0]); AttributeIndex++) { + if (NewTerminalContext->Parity == (UINT64) (ParityList[AttributeIndex].Value)) { + NewTerminalContext->ParityIndex = AttributeIndex; + break; + } + } + + for (AttributeIndex = 0; AttributeIndex < sizeof (StopBitsList) / sizeof (StopBitsList[0]); AttributeIndex++) { + if (NewTerminalContext->StopBits == (UINT64) (StopBitsList[AttributeIndex].Value)) { + NewTerminalContext->StopBitsIndex = AttributeIndex; + break; + } + } + CurrentFakeNVMap->COMBaudRate[TerminalIndex] = NewTerminalContext->BaudRateIndex; + CurrentFakeNVMap->COMDataRate[TerminalIndex] = NewTerminalContext->DataBitsIndex; + CurrentFakeNVMap->COMStopBits[TerminalIndex] = NewTerminalContext->StopBitsIndex; + CurrentFakeNVMap->COMParity[TerminalIndex] = NewTerminalContext->ParityIndex; + CurrentFakeNVMap->COMTerminalType[TerminalIndex] = NewTerminalContext->TerminalType; + CurrentFakeNVMap->COMFlowControl[TerminalIndex] = NewTerminalContext->FlowControl; + } +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c new file mode 100644 index 0000000000..0a3ffbcc30 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c @@ -0,0 +1,332 @@ +/** @file + Define some data used for Boot Maint + +Copyright (c) 2004 - 2008, Intel 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 "BootMaint.h" + +VOID *mStartOpCodeHandle = NULL; +VOID *mEndOpCodeHandle = NULL; +EFI_IFR_GUID_LABEL *mStartLabel = NULL; +EFI_IFR_GUID_LABEL *mEndLabel = NULL; + +STRING_DEPOSITORY *FileOptionStrDepository; +STRING_DEPOSITORY *ConsoleOptionStrDepository; +STRING_DEPOSITORY *BootOptionStrDepository; +STRING_DEPOSITORY *BootOptionHelpStrDepository; +STRING_DEPOSITORY *DriverOptionStrDepository; +STRING_DEPOSITORY *DriverOptionHelpStrDepository; +STRING_DEPOSITORY *TerminalStrDepository; + +/// +/// Terminal type string token storage +/// +UINT16 TerminalType[] = { + STRING_TOKEN(STR_COM_TYPE_0), + STRING_TOKEN(STR_COM_TYPE_1), + STRING_TOKEN(STR_COM_TYPE_2), + STRING_TOKEN(STR_COM_TYPE_3), +}; + +/// +/// Flow Control type string token storage +/// +UINT16 mFlowControlType[2] = { + STRING_TOKEN(STR_NONE_FLOW_CONTROL), + STRING_TOKEN(STR_HARDWARE_FLOW_CONTROL) +}; + +UINT32 mFlowControlValue[2] = { + 0, + UART_FLOW_CONTROL_HARDWARE +}; + +/// +/// File system selection menu +/// +BM_MENU_OPTION FsOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Console Input Device Selection Menu +/// +BM_MENU_OPTION ConsoleInpMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Console Output Device Selection Menu +/// +BM_MENU_OPTION ConsoleOutMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Error Output Device Selection Menu +/// +BM_MENU_OPTION ConsoleErrMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Boot Option from variable Menu +/// +BM_MENU_OPTION BootOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Driver Option from variable menu +/// +BM_MENU_OPTION DriverOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy FD Info from LegacyBios.GetBbsInfo() +/// +BM_MENU_OPTION LegacyFDMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy HD Info from LegacyBios.GetBbsInfo() +/// +BM_MENU_OPTION LegacyHDMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy CD Info from LegacyBios.GetBbsInfo() +/// +BM_MENU_OPTION LegacyCDMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy NET Info from LegacyBios.GetBbsInfo() +/// +BM_MENU_OPTION LegacyNETMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy NET Info from LegacyBios.GetBbsInfo() +/// +BM_MENU_OPTION LegacyBEVMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Files and sub-directories in current directory menu +/// +BM_MENU_OPTION DirectoryMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Handles in current system selection menu +/// +BM_MENU_OPTION DriverMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +BM_MENU_OPTION TerminalMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Value and string token correspondency for BaudRate +/// +COM_ATTR BaudRateList[19] = { + { + 115200, + STRING_TOKEN(STR_COM_BAUD_RATE_0) + }, + { + 57600, + STRING_TOKEN(STR_COM_BAUD_RATE_1) + }, + { + 38400, + STRING_TOKEN(STR_COM_BAUD_RATE_2) + }, + { + 19200, + STRING_TOKEN(STR_COM_BAUD_RATE_3) + }, + { + 9600, + STRING_TOKEN(STR_COM_BAUD_RATE_4) + }, + { + 7200, + STRING_TOKEN(STR_COM_BAUD_RATE_5) + }, + { + 4800, + STRING_TOKEN(STR_COM_BAUD_RATE_6) + }, + { + 3600, + STRING_TOKEN(STR_COM_BAUD_RATE_7) + }, + { + 2400, + STRING_TOKEN(STR_COM_BAUD_RATE_8) + }, + { + 2000, + STRING_TOKEN(STR_COM_BAUD_RATE_9) + }, + { + 1800, + STRING_TOKEN(STR_COM_BAUD_RATE_10) + }, + { + 1200, + STRING_TOKEN(STR_COM_BAUD_RATE_11) + }, + { + 600, + STRING_TOKEN(STR_COM_BAUD_RATE_12) + }, + { + 300, + STRING_TOKEN(STR_COM_BAUD_RATE_13) + }, + { + 150, + STRING_TOKEN(STR_COM_BAUD_RATE_14) + }, + { + 134, + STRING_TOKEN(STR_COM_BAUD_RATE_15) + }, + { + 110, + STRING_TOKEN(STR_COM_BAUD_RATE_16) + }, + { + 75, + STRING_TOKEN(STR_COM_BAUD_RATE_17) + }, + { + 50, + STRING_TOKEN(STR_COM_BAUD_RATE_18) + } +}; + +/// +/// Value and string token correspondency for DataBits +/// +COM_ATTR DataBitsList[4] = { + { + 5, + STRING_TOKEN(STR_COM_DATA_BITS_0) + }, + { + 6, + STRING_TOKEN(STR_COM_DATA_BITS_1) + }, + { + 7, + STRING_TOKEN(STR_COM_DATA_BITS_2) + }, + { + 8, + STRING_TOKEN(STR_COM_DATA_BITS_3) + } +}; + +/// +/// Value and string token correspondency for Parity +/// +COM_ATTR ParityList[5] = { + { + NoParity, + STRING_TOKEN(STR_COM_PAR_0) + }, + { + EvenParity, + STRING_TOKEN(STR_COM_PAR_1) + }, + { + OddParity, + STRING_TOKEN(STR_COM_PAR_2) + }, + { + MarkParity, + STRING_TOKEN(STR_COM_PAR_3) + }, + { + SpaceParity, + STRING_TOKEN(STR_COM_PAR_4) + } +}; + +/// +/// Value and string token correspondency for Baudreate +/// +COM_ATTR StopBitsList[3] = { + { + OneStopBit, + STRING_TOKEN(STR_COM_STOP_BITS_0) + }, + { + OneFiveStopBits, + STRING_TOKEN(STR_COM_STOP_BITS_1) + }, + { + TwoStopBits, + STRING_TOKEN(STR_COM_STOP_BITS_2) + } +}; + +/// +/// Guid for messaging path, used in Serial port setting. +/// +EFI_GUID TerminalTypeGuid[4] = { + DEVICE_PATH_MESSAGING_PC_ANSI, + DEVICE_PATH_MESSAGING_VT_100, + DEVICE_PATH_MESSAGING_VT_100_PLUS, + DEVICE_PATH_MESSAGING_VT_UTF8 +}; diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr new file mode 100644 index 0000000000..056694ebef --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr @@ -0,0 +1,127 @@ +///** @file +// +// File Explorer Formset +// +// 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 +// 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 "FormGuid.h" + +formset + guid = FILE_EXPLORE_FORMSET_GUID, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = FILE_EXPLORE_FORMSET_GUID, + + varstore FILE_EXPLORER_NV_DATA, + varid = VARSTORE_ID_BOOT_MAINT, + name = FeData, + guid = FILE_EXPLORE_FORMSET_GUID; + + form formid = FORM_FILE_EXPLORER_ID, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); + + label FORM_FILE_EXPLORER_ID; + label LABEL_END; + endform; + + form formid = FORM_BOOT_ADD_DESCRIPTION_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE); + + label FORM_BOOT_ADD_DESCRIPTION_ID; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + string varid = FeData.BootDescriptionData, + questionid = KEY_VALUE_BOOT_DESCRIPTION, + prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), + help = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + minsize = 6, + maxsize = 75, + endstring; + + string varid = FeData.BootOptionalData, + questionid = KEY_VALUE_BOOT_OPTION, + prompt = STRING_TOKEN(STR_OPTIONAL_DATA), + help = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + minsize = 0, + maxsize = 120, + endstring; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_SAVE_AND_EXIT_BOOT; + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT; + + endform; + + form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); + + label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + string varid = FeData.DriverDescriptionData, + questionid = KEY_VALUE_DRIVER_DESCRIPTION, + prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), + help = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + minsize = 6, + maxsize = 75, + endstring; + + string varid = FeData.DriverOptionalData, + questionid = KEY_VALUE_DRIVER_OPTION, + prompt = STRING_TOKEN(STR_OPTIONAL_DATA), + help = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + minsize = 0, + maxsize = 120, + endstring; + + checkbox varid = FeData.ForceReconnect, + prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), + help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), + flags = CHECKBOX_DEFAULT, + key = 0, + endcheckbox; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_SAVE_AND_EXIT_DRIVER; //BUGBUB: allow duplicate key in one formset??? + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER; + + endform; + +endformset; \ No newline at end of file diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c new file mode 100644 index 0000000000..f804984fa9 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c @@ -0,0 +1,469 @@ +/** @file + File explorer related functions. + +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 +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 "BootMaint.h" + +/** + Update the File Explore page. + + @param CallbackData The BMM context data. + @param MenuOption Pointer to menu options to display. + +**/ +VOID +UpdateFileExplorePage ( + IN BMM_CALLBACK_DATA *CallbackData, + BM_MENU_OPTION *MenuOption + ) +{ + UINTN Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + EFI_FORM_ID FormId; + + NewMenuEntry = NULL; + NewFileContext = NULL; + FormId = 0; + + RefreshUpdateData (); + mStartLabel->Number = FORM_FILE_EXPLORER_ID; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewFileContext->IsBootLegacy) { + continue; + } + + if ((NewFileContext->IsDir) || (FileExplorerStateBootFromFile == CallbackData->FeCurrentState)) { + // + // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile. + // + HiiCreateActionOpCode ( + mStartOpCodeHandle, + (UINT16) (FILE_OPTION_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + 0 + ); + } else { + // + // Create Goto opcode for file in FileExplorerStateAddBootOption or FileExplorerStateAddDriverOptionState. + // + if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { + FormId = FORM_BOOT_ADD_DESCRIPTION_ID; + } else if (FileExplorerStateAddDriverOptionState == CallbackData->FeCurrentState) { + FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + } + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FormId, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + (UINT16) (FILE_OPTION_GOTO_OFFSET + Index) + ); + } + } + + HiiUpdateForm ( + CallbackData->FeHiiHandle, + &gFileExploreFormSetGuid, + FORM_FILE_EXPLORER_ID, + mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID + mEndOpCodeHandle // LABEL_END + ); +} + +/** + Update the file explower page with the refershed file system. + + + @param CallbackData BMM context data + @param KeyValue Key value to identify the type of data to expect. + + @retval TRUE Inform the caller to create a callback packet to exit file explorer. + @retval FALSE Indicate that there is no need to exit file explorer. + +**/ +BOOLEAN +UpdateFileExplorer ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT16 KeyValue + ) +{ + UINT16 FileOptionMask; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + EFI_FORM_ID FormId; + BOOLEAN ExitFileExplorer; + EFI_STATUS Status; + + NewMenuEntry = NULL; + NewFileContext = NULL; + ExitFileExplorer = FALSE; + + FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue); + + if (FileExplorerDisplayUnknown == CallbackData->FeDisplayContext) { + // + // First in, display file system. + // + BOpt_FreeMenu (&FsOptionMenu); + BOpt_FindFileSystem (CallbackData); + CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu); + + UpdateFileExplorePage (CallbackData, &FsOptionMenu); + + CallbackData->FeDisplayContext = FileExplorerDisplayFileSystem; + } else { + if (FileExplorerDisplayFileSystem == CallbackData->FeDisplayContext) { + NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask); + } else if (FileExplorerDisplayDirectory == CallbackData->FeDisplayContext) { + NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask); + } + + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewFileContext->IsDir ) { + CallbackData->FeDisplayContext = FileExplorerDisplayDirectory; + + RemoveEntryList (&NewMenuEntry->Link); + BOpt_FreeMenu (&DirectoryMenu); + Status = BOpt_FindFiles (CallbackData, NewMenuEntry); + if (EFI_ERROR (Status)) { + ExitFileExplorer = TRUE; + goto exit; + } + CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu); + BOpt_DestroyMenuEntry (NewMenuEntry); + + UpdateFileExplorePage (CallbackData, &DirectoryMenu); + + } else { + switch (CallbackData->FeCurrentState) { + case FileExplorerStateBootFromFile: + // + // Restore to original mode before launching boot option. + // + BdsSetConsoleMode (FALSE); + + // + // Here boot from file + // + BootThisFile (NewFileContext); + // + // Set proper video resolution and text mode for setup. + // + BdsSetConsoleMode (TRUE); + ExitFileExplorer = TRUE; + break; + + case FileExplorerStateAddBootOption: + case FileExplorerStateAddDriverOptionState: + if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { + FormId = FORM_BOOT_ADD_DESCRIPTION_ID; + if (!CallbackData->FeFakeNvData.BootOptionChanged) { + ZeroMem (CallbackData->FeFakeNvData.BootOptionalData, sizeof (CallbackData->FeFakeNvData.BootOptionalData)); + ZeroMem (CallbackData->FeFakeNvData.BootDescriptionData, sizeof (CallbackData->FeFakeNvData.BootDescriptionData)); + } + } else { + FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + if (!CallbackData->FeFakeNvData.DriverOptionChanged) { + ZeroMem (CallbackData->FeFakeNvData.DriverOptionalData, sizeof (CallbackData->FeFakeNvData.DriverOptionalData)); + ZeroMem (CallbackData->FeFakeNvData.DriverDescriptionData, sizeof (CallbackData->FeFakeNvData.DriverDescriptionData)); + } + } + + CallbackData->MenuEntry = NewMenuEntry; + CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath; + + // + // Create Subtitle op-code for the display string of the option. + // + RefreshUpdateData (); + mStartLabel->Number = FormId; + + HiiCreateSubTitleOpCode ( + mStartOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + 0, + 0 + ); + + HiiUpdateForm ( + CallbackData->FeHiiHandle, + &gFileExploreFormSetGuid, + FormId, + mStartOpCodeHandle, // Label FormId + mEndOpCodeHandle // LABEL_END + ); + break; + + default: + break; + } + } + } + exit: + return ExitFileExplorer; +} + +/** + This function applies changes in a driver's configuration. + Input is a Configuration, which has the routing data for this + driver followed by name / value configuration pairs. The driver + must apply those pairs to its configurable storage. If the + driver's configuration is stored in a linear block of data + and the driver's name / value pairs are in + format, it may use the ConfigToBlock helper function (above) to + simplify the job. Currently not implemented. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Configuration A null-terminated Unicode string in + format. + @param[out] Progress A pointer to a string filled in with the + offset of the most recent '&' before the + first failing name / value pair (or the + beginn ing 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 have been distributed or are + awaiting distribution. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + @retval EFI_INVALID_PARAMETERS Passing in a NULL for the + Results parameter would result + in this type of error. + @retval EFI_NOT_FOUND Target for the specified routing data + was not found. +**/ +EFI_STATUS +EFIAPI +FileExplorerRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; + FILE_EXPLORER_NV_DATA *FeData; + BMM_CALLBACK_DATA *Private; + + if (Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Configuration; + + if (Configuration == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check routing data in . + // Note: there is no name for Name/Value storage, only GUID will be checked + // + if (!HiiIsConfigHdrMatch (Configuration, &gFileExploreFormSetGuid, mFileExplorerStorageName)) { + return EFI_NOT_FOUND; + } + + Status = gBS->LocateProtocol ( + &gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID**) &ConfigRouting + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Private = FE_CALLBACK_DATA_FROM_THIS (This); + // + // Get Buffer Storage data from EFI variable + // + BufferSize = sizeof (FILE_EXPLORER_NV_DATA ); + FeData = &Private->FeFakeNvData; + + // + // Convert to buffer data by helper function ConfigToBlock() + // + Status = ConfigRouting->ConfigToBlock ( + ConfigRouting, + Configuration, + (UINT8 *) FeData, + &BufferSize, + Progress + ); + ASSERT_EFI_ERROR (Status); + + if (FeData->BootDescriptionData[0] != 0x00 || FeData->BootOptionalData[0] != 0x00) { + Status = Var_UpdateBootOption (Private, FeData); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_GetBootOptions (Private); + CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); + } + + if (FeData->DriverDescriptionData[0] != 0x00 || FeData->DriverOptionalData[0] != 0x00) { + Status = Var_UpdateDriverOption ( + Private, + Private->FeHiiHandle, + FeData->DriverDescriptionData, + FeData->DriverOptionalData, + FeData->ForceReconnect + ); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_GetDriverOptions (Private); + CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); + } + + return EFI_SUCCESS; +} + +/** + This function processes the results of changes in configuration. + When user select a interactive opcode, this callback will be triggered. + Based on the Question(QuestionId) that triggers the callback, the corresponding + actions is performed. It handles: + + 1) the addition of boot option. + 2) the addition of driver option. + 3) exit from file browser + 4) update of file content if a dir is selected. + 5) boot the file if a file is selected in "boot from file" + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + @retval EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL. +**/ +EFI_STATUS +EFIAPI +FileExplorerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + BMM_CALLBACK_DATA *Private; + FILE_EXPLORER_NV_DATA *NvRamMap; + EFI_STATUS Status; + + if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { + // + // All other action return unsupported. + // + return EFI_UNSUPPORTED; + } + + Status = EFI_SUCCESS; + Private = FE_CALLBACK_DATA_FROM_THIS (This); + + // + // Retrieve uncommitted data from Form Browser + // + NvRamMap = &Private->FeFakeNvData; + HiiGetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap); + + if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) { + NvRamMap->BootOptionChanged = FALSE; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { + NvRamMap->DriverOptionChanged = FALSE; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { + // + // Discard changes and exit formset + // + NvRamMap->DriverOptionalData[0] = 0x0000; + NvRamMap->DriverDescriptionData[0] = 0x0000; + NvRamMap->DriverOptionChanged = FALSE; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) { + // + // Discard changes and exit formset + // + NvRamMap->BootOptionalData[0] = 0x0000; + NvRamMap->BootDescriptionData[0] = 0x0000; + NvRamMap->BootOptionChanged = FALSE; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) { + NvRamMap->BootOptionChanged = TRUE; + } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) { + NvRamMap->DriverOptionChanged = TRUE; + } else if (QuestionId < FILE_OPTION_OFFSET) { + // + // Exit File Explorer formset + // + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } else if (QuestionId >= FILE_OPTION_OFFSET && QuestionId < FILE_OPTION_GOTO_OFFSET) { + // + // Update forms may return TRUE or FALSE, need to check here. + // + if (UpdateFileExplorer (Private, QuestionId)) { + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } + } + } else if (Action == EFI_BROWSER_ACTION_CHANGING) { + if (Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (QuestionId >= FILE_OPTION_GOTO_OFFSET) { + // + // function will always return FALSE, no need to check here. + // + UpdateFileExplorer (Private, QuestionId); + } + } + + // + // Pass changed uncommitted data back to Form Browser + // + HiiSetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap, NULL); + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h new file mode 100644 index 0000000000..bf99999760 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h @@ -0,0 +1,243 @@ +/** @file + Formset guids, form id and VarStore data structure for Boot Maintenance Manager. + +Copyright (c) 2004 - 2015, Intel 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 _FORM_GUID_H_ +#define _FORM_GUID_H_ + +#include + +#define FORM_MAIN_ID 0x1001 +#define FORM_BOOT_ADD_ID 0x1002 +#define FORM_BOOT_DEL_ID 0x1003 +#define FORM_BOOT_CHG_ID 0x1004 +#define FORM_DRV_ADD_ID 0x1005 +#define FORM_DRV_DEL_ID 0x1006 +#define FORM_DRV_CHG_ID 0x1007 +#define FORM_CON_MAIN_ID 0x1008 +#define FORM_CON_IN_ID 0x1009 +#define FORM_CON_OUT_ID 0x100A +#define FORM_CON_ERR_ID 0x100B +#define FORM_FILE_SEEK_ID 0x100C +#define FORM_FILE_NEW_SEEK_ID 0x100D +#define FORM_DRV_ADD_FILE_ID 0x100E +#define FORM_DRV_ADD_HANDLE_ID 0x100F +#define FORM_DRV_ADD_HANDLE_DESC_ID 0x1010 +#define FORM_BOOT_NEXT_ID 0x1011 +#define FORM_TIME_OUT_ID 0x1012 +#define FORM_RESET 0x1013 +#define FORM_BOOT_SETUP_ID 0x1014 +#define FORM_DRIVER_SETUP_ID 0x1015 +#define FORM_BOOT_LEGACY_DEVICE_ID 0x1016 +#define FORM_CON_COM_ID 0x1017 +#define FORM_CON_COM_SETUP_ID 0x1018 +#define FORM_SET_FD_ORDER_ID 0x1019 +#define FORM_SET_HD_ORDER_ID 0x101A +#define FORM_SET_CD_ORDER_ID 0x101B +#define FORM_SET_NET_ORDER_ID 0x101C +#define FORM_SET_BEV_ORDER_ID 0x101D +#define FORM_FILE_EXPLORER_ID 0x101E +#define FORM_BOOT_ADD_DESCRIPTION_ID 0x101F +#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x1020 +#define FORM_CON_MODE_ID 0x1021 +#define FORM_BOOT_FROM_FILE_ID 0x1022 + +#define MAXIMUM_FORM_ID 0x10FF + +#define KEY_VALUE_COM_SET_BAUD_RATE 0x1101 +#define KEY_VALUE_COM_SET_DATA_BITS 0x1102 +#define KEY_VALUE_COM_SET_STOP_BITS 0x1103 +#define KEY_VALUE_COM_SET_PARITY 0x1104 +#define KEY_VALUE_COM_SET_TERMI_TYPE 0x1105 +#define KEY_VALUE_MAIN_BOOT_NEXT 0x1106 +#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x1107 +#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x1108 +#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x1109 +#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x110A +#define KEY_VALUE_SAVE_AND_EXIT 0x110B +#define KEY_VALUE_NO_SAVE_AND_EXIT 0x110C +#define KEY_VALUE_BOOT_FROM_FILE 0x110D +#define KEY_VALUE_BOOT_DESCRIPTION 0x110E +#define KEY_VALUE_BOOT_OPTION 0x110F +#define KEY_VALUE_DRIVER_DESCRIPTION 0x1110 +#define KEY_VALUE_DRIVER_OPTION 0x1111 + +#define MAXIMUM_NORMAL_KEY_VALUE 0x11FF + +// +// Varstore ID defined for Buffer Storage +// +#define VARSTORE_ID_BOOT_MAINT 0x1000 +#define VARSTORE_ID_FILE_EXPLORER 0x1001 + +// +// End Label +// +#define LABEL_END 0xffff +#define MAX_MENU_NUMBER 100 + +/// +/// This is the structure that will be used to store the +/// question's current value. Use it at initialize time to +/// set default value for each question. When using at run +/// time, this map is returned by the callback function, +/// so dynamically changing the question's value will be +/// possible through this mechanism +/// +typedef struct { + // + // Three questions displayed at the main page + // for Timeout, BootNext Variables respectively + // + UINT16 BootTimeOut; + UINT16 BootNext; + + // + // This is the COM1 Attributes value storage + // + UINT8 COM1BaudRate; + UINT8 COM1DataRate; + UINT8 COM1StopBits; + UINT8 COM1Parity; + UINT8 COM1TerminalType; + + // + // This is the COM2 Attributes value storage + // + UINT8 COM2BaudRate; + UINT8 COM2DataRate; + UINT8 COM2StopBits; + UINT8 COM2Parity; + UINT8 COM2TerminalType; + + // + // Driver Option Add Handle page storage + // + UINT16 DriverAddHandleDesc[MAX_MENU_NUMBER]; + UINT16 DriverAddHandleOptionalData[MAX_MENU_NUMBER]; + UINT8 DriverAddActive; + UINT8 DriverAddForceReconnect; + + // + // Console Input/Output/Errorout using COM port check storage + // + UINT8 ConsoleInputCOM1; + UINT8 ConsoleInputCOM2; + UINT8 ConsoleOutputCOM1; + UINT8 ConsoleOutputCOM2; + UINT8 ConsoleErrorCOM1; + UINT8 ConsoleErrorCOM2; + + // + // At most 100 input/output/errorout device for console storage + // + UINT8 ConsoleCheck[MAX_MENU_NUMBER]; + // + // At most 100 input/output/errorout device for console storage + // + UINT8 ConsoleInCheck[MAX_MENU_NUMBER]; + UINT8 ConsoleOutCheck[MAX_MENU_NUMBER]; + UINT8 ConsoleErrCheck[MAX_MENU_NUMBER]; + + // + // Boot Option Order storage + // The value is the OptionNumber+1 because the order list value cannot be 0 + // Use UINT32 to hold the potential value 0xFFFF+1=0x10000 + // + UINT32 BootOptionOrder[MAX_MENU_NUMBER]; + + // + // Driver Option Order storage + // The value is the OptionNumber+1 because the order list value cannot be 0 + // Use UINT32 to hold the potential value 0xFFFF+1=0x10000 + // + UINT32 DriverOptionOrder[MAX_MENU_NUMBER]; + + // + // Boot Option Delete storage + // + BOOLEAN BootOptionDel[MAX_MENU_NUMBER]; + BOOLEAN BootOptionDelMark[MAX_MENU_NUMBER]; + + // + // Driver Option Delete storage + // + BOOLEAN DriverOptionDel[MAX_MENU_NUMBER]; + BOOLEAN DriverOptionDelMark[MAX_MENU_NUMBER]; + + // + // This is the Terminal Attributes value storage + // + UINT8 COMBaudRate[MAX_MENU_NUMBER]; + UINT8 COMDataRate[MAX_MENU_NUMBER]; + UINT8 COMStopBits[MAX_MENU_NUMBER]; + UINT8 COMParity[MAX_MENU_NUMBER]; + UINT8 COMTerminalType[MAX_MENU_NUMBER]; + UINT8 COMFlowControl[MAX_MENU_NUMBER]; + + // + // Legacy Device Order Selection Storage + // + UINT8 LegacyFD[MAX_MENU_NUMBER]; + UINT8 LegacyHD[MAX_MENU_NUMBER]; + UINT8 LegacyCD[MAX_MENU_NUMBER]; + UINT8 LegacyNET[MAX_MENU_NUMBER]; + UINT8 LegacyBEV[MAX_MENU_NUMBER]; + + // + // We use DisableMap array to record the enable/disable state of each boot device + // It should be taken as a bit array, from left to right there are totally 256 bits + // the most left one stands for BBS table item 0, and the most right one stands for item 256 + // If the bit is 1, it means the boot device has been disabled. + // + UINT8 DisableMap[32]; + + // + // Console Output Text Mode + // + UINT16 ConsoleOutMode; + + // + // UINT16 PadArea[10]; + // +} BMM_FAKE_NV_DATA; + +// +// Key used by File Explorer forms +// +#define KEY_VALUE_SAVE_AND_EXIT_BOOT 0x1000 +#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT 0x1001 +#define KEY_VALUE_SAVE_AND_EXIT_DRIVER 0x1002 +#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER 0x1003 + +// +// Description data and optional data size +// +#define DESCRIPTION_DATA_SIZE 75 +#define OPTIONAL_DATA_SIZE 127 + +/// +/// This is the data structure used by File Explorer formset +/// +typedef struct { + UINT16 BootDescriptionData[DESCRIPTION_DATA_SIZE]; + UINT16 BootOptionalData[OPTIONAL_DATA_SIZE]; + UINT16 DriverDescriptionData[DESCRIPTION_DATA_SIZE]; + UINT16 DriverOptionalData[OPTIONAL_DATA_SIZE]; + BOOLEAN BootOptionChanged; + BOOLEAN DriverOptionChanged; + UINT8 Active; + UINT8 ForceReconnect; +} FILE_EXPLORER_NV_DATA; + +#endif + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c new file mode 100644 index 0000000000..b13ed11630 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c @@ -0,0 +1,1391 @@ +/** @file +Dynamically update the pages. + +Copyright (c) 2004 - 2015, Intel 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 "BootMaint.h" + +/** + Refresh the global UpdateData structure. + +**/ +VOID +RefreshUpdateData ( + VOID + ) +{ + // + // Free current updated date + // + if (mStartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mStartOpCodeHandle); + } + + // + // Create new OpCode Handle + // + mStartOpCodeHandle = HiiAllocateOpCodeHandle (); + + // + // Create Hii Extend Label OpCode as the start opcode + // + mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + +} + +/** + Add a "Go back to main page" tag in front of the form when there are no + "Apply changes" and "Discard changes" tags in the end of the form. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdatePageStart ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + RefreshUpdateData (); + mStartLabel->Number = CallbackData->BmmCurrentPageId; + + if (!(CallbackData->BmmAskSaveOrNot)) { + // + // Add a "Go back to main page" tag in front of the form when there are no + // "Apply changes" and "Discard changes" tags in the end of the form. + // + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_MAIN_ID, + STRING_TOKEN (STR_FORM_GOTO_MAIN), + STRING_TOKEN (STR_FORM_GOTO_MAIN), + 0, + FORM_MAIN_ID + ); + } + +} + +/** + Create the "Apply changes" and "Discard changes" tags. And + ensure user can return to the main page. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdatePageEnd ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + // + // Create the "Apply changes" and "Discard changes" tags. + // + if (CallbackData->BmmAskSaveOrNot) { + HiiCreateSubTitleOpCode ( + mStartOpCodeHandle, + STRING_TOKEN (STR_NULL_STRING), + 0, + 0, + 0 + ); + + HiiCreateActionOpCode ( + mStartOpCodeHandle, + KEY_VALUE_SAVE_AND_EXIT, + STRING_TOKEN (STR_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + 0 + ); + } + + // + // Ensure user can return to the main page. + // + HiiCreateActionOpCode ( + mStartOpCodeHandle, + KEY_VALUE_NO_SAVE_AND_EXIT, + STRING_TOKEN (STR_NO_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + 0 + ); + + HiiUpdateForm ( + CallbackData->BmmHiiHandle, + &gBootMaintFormSetGuid, + CallbackData->BmmCurrentPageId, + mStartOpCodeHandle, // Label CallbackData->BmmCurrentPageId + mEndOpCodeHandle // LABEL_END + ); +} + +/** + Clean up the dynamic opcode at label and form specified by both LabelId. + + @param LabelId It is both the Form ID and Label ID for opcode deletion. + @param CallbackData The BMM context data. + +**/ +VOID +CleanUpPage ( + IN UINT16 LabelId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + RefreshUpdateData (); + + // + // Remove all op-codes from dynamic page + // + mStartLabel->Number = LabelId; + HiiUpdateForm ( + CallbackData->BmmHiiHandle, + &gBootMaintFormSetGuid, + LabelId, + mStartOpCodeHandle, // Label LabelId + mEndOpCodeHandle // LABEL_END + ); +} + +/** + Boot a file selected by user at File Expoloer of BMM. + + @param FileContext The file context data, which contains the device path + of the file to be boot from. + + @retval EFI_SUCCESS The function completed successfull. + @return Other value if the boot from the file fails. + +**/ +EFI_STATUS +BootThisFile ( + IN BM_FILE_CONTEXT *FileContext + ) +{ + EFI_STATUS Status; + UINTN ExitDataSize; + CHAR16 *ExitData; + BDS_COMMON_OPTION *Option; + + Option = (BDS_COMMON_OPTION *) AllocatePool (sizeof (BDS_COMMON_OPTION)); + ASSERT (Option != NULL); + Option->Description = (CHAR16 *) AllocateCopyPool (StrSize (FileContext->FileName), FileContext->FileName); + Option->DevicePath = FileContext->DevicePath; + Option->LoadOptionsSize = 0; + Option->LoadOptions = NULL; + + // + // Since current no boot from removable media directly is allowed */ + // + gST->ConOut->ClearScreen (gST->ConOut); + + ExitDataSize = 0; + + Status = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData); + + return Status; + +} + +/** + Create a list of Goto Opcode for all terminal devices logged + by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateConCOMPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + + CallbackData->BmmAskSaveOrNot = FALSE; + + UpdatePageStart (CallbackData); + + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_CON_COM_SETUP_ID, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + (UINT16) (TERMINAL_OPTION_OFFSET + Index) + ); + } + + UpdatePageEnd (CallbackData); +} + +/** + Create a lit of boot option from global BootOptionMenu. It + allow user to delete the boot option. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateBootDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); + + ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0]))); + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (NewLoadContext->IsLegacy) { + continue; + } + + NewLoadContext->Deleted = FALSE; + + if (CallbackData->BmmFakeNvData.BootOptionDel[Index] && !CallbackData->BmmFakeNvData.BootOptionDelMark[Index]) { + // + // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected + // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has + // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser + // through HiiSetBrowserData function. + // + CallbackData->BmmFakeNvData.BootOptionDel[Index] = FALSE; + } + + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + EFI_IFR_FLAG_CALLBACK, + 0, + NULL + ); + } + + UpdatePageEnd (CallbackData); +} + +/** + Create a lit of driver option from global DriverMenu. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateDrvAddHandlePage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + + CallbackData->BmmAskSaveOrNot = FALSE; + + UpdatePageStart (CallbackData); + + for (Index = 0; Index < DriverMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_DRV_ADD_HANDLE_DESC_ID, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + (UINT16) (HANDLE_OPTION_OFFSET + Index) + ); + } + + UpdatePageEnd (CallbackData); +} + +/** + Create a lit of driver option from global DriverOptionMenu. It + allow user to delete the driver option. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateDrvDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu); + + ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0]))); + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + + if (CallbackData->BmmFakeNvData.DriverOptionDel[Index] && !CallbackData->BmmFakeNvData.DriverOptionDelMark[Index]) { + // + // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected + // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has + // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser + // through HiiSetBrowserData function. + // + CallbackData->BmmFakeNvData.DriverOptionDel[Index] = FALSE; + } + + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + EFI_IFR_FLAG_CALLBACK, + 0, + NULL + ); + } + + UpdatePageEnd (CallbackData); +} + +/** + Prepare the page to allow user to add description for + a Driver Option. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateDriverAddHandleDescPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + + CallbackData->BmmFakeNvData.DriverAddActive = 0x01; + CallbackData->BmmFakeNvData.DriverAddForceReconnect = 0x00; + CallbackData->BmmAskSaveOrNot = TRUE; + NewMenuEntry = CallbackData->MenuEntry; + + UpdatePageStart (CallbackData); + + HiiCreateSubTitleOpCode ( + mStartOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + 0, + 0 + ); + + HiiCreateStringOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + DRV_ADD_HANDLE_DESC_VAR_OFFSET, + STRING_TOKEN (STR_LOAD_OPTION_DESC), + STRING_TOKEN (STR_NULL_STRING), + 0, + 0, + 6, + 75, + NULL + ); + + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + DRV_ADD_RECON_VAR_OFFSET, + STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), + STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), + 0, + 0, + NULL + ); + + HiiCreateStringOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + DRIVER_ADD_OPTION_VAR_OFFSET, + STRING_TOKEN (STR_OPTIONAL_DATA), + STRING_TOKEN (STR_NULL_STRING), + 0, + 0, + 6, + 75, + NULL + ); + + UpdatePageEnd (CallbackData); +} + +/** + Update console page. + + @param UpdatePageId The form ID to be updated. + @param ConsoleMenu The console menu list. + @param CallbackData The BMM context data. + +**/ +VOID +UpdateConsolePage ( + IN UINT16 UpdatePageId, + IN BM_MENU_OPTION *ConsoleMenu, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT8 CheckFlags; + UINT8 *ConsoleCheck; + EFI_QUESTION_ID QuestionIdBase; + UINT16 VariableOffsetBase; + + UpdatePageStart (CallbackData); + + ConsoleCheck = NULL; + QuestionIdBase = 0; + VariableOffsetBase = 0; + + switch (UpdatePageId) { + case FORM_CON_IN_ID: + ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleInCheck[0]; + QuestionIdBase = CON_IN_DEVICE_QUESTION_ID; + VariableOffsetBase = CON_IN_DEVICE_VAR_OFFSET; + break; + + case FORM_CON_OUT_ID: + ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0]; + QuestionIdBase = CON_OUT_DEVICE_QUESTION_ID; + VariableOffsetBase = CON_OUT_DEVICE_VAR_OFFSET; + break; + + case FORM_CON_ERR_ID: + ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0]; + QuestionIdBase = CON_ERR_DEVICE_QUESTION_ID; + VariableOffsetBase = CON_ERR_DEVICE_VAR_OFFSET; + break; + } + ASSERT (ConsoleCheck != NULL); + + for (Index = 0; ((Index < ConsoleMenu->MenuNumber) && \ + (Index < MAX_MENU_NUMBER)) ; Index++) { + CheckFlags = 0; + if (UpdatePageId != FORM_CON_ERR_ID) { + CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT; + } + NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (QuestionIdBase + Index), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (VariableOffsetBase + Index), + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + 0, + CheckFlags, + NULL + ); + } + + UpdatePageEnd (CallbackData); +} + +/** + Update the page's NV Map if user has changed the order + a list. This list can be Boot Order or Driver Order. + + @param UpdatePageId The form ID to be updated. + @param OptionMenu The new list. + @param CallbackData The BMM context data. + +**/ +VOID +UpdateOrderPage ( + IN UINT16 UpdatePageId, + IN BM_MENU_OPTION *OptionMenu, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT16 OptionIndex; + VOID *OptionsOpCodeHandle; + BOOLEAN BootOptionFound; + UINT32 *OptionOrder; + EFI_QUESTION_ID QuestionId; + UINT16 VarOffset; + + + UpdatePageStart (CallbackData); + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); + + OptionOrder = NULL; + QuestionId = 0; + VarOffset = 0; + switch (UpdatePageId) { + + case FORM_BOOT_CHG_ID: + //GetBootOrder (CallbackData); + OptionOrder = CallbackData->BmmFakeNvData.BootOptionOrder; + QuestionId = BOOT_OPTION_ORDER_QUESTION_ID; + VarOffset = BOOT_OPTION_ORDER_VAR_OFFSET; + break; + + case FORM_DRV_CHG_ID: + //GetDriverOrder (CallbackData); + OptionOrder = CallbackData->BmmFakeNvData.DriverOptionOrder; + QuestionId = DRIVER_OPTION_ORDER_QUESTION_ID; + VarOffset = DRIVER_OPTION_ORDER_VAR_OFFSET; + break; + } + ASSERT (OptionOrder != NULL); + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + NewMenuEntry = NULL; + for (OptionIndex = 0; (OptionIndex < MAX_MENU_NUMBER && OptionOrder[OptionIndex] != 0); OptionIndex++) { + BootOptionFound = FALSE; + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); + if ((UINT32) (NewMenuEntry->OptionNumber + 1) == OptionOrder[OptionIndex]) { + BootOptionFound = TRUE; + break; + } + } + if (BootOptionFound) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + EFI_IFR_TYPE_NUM_SIZE_32, + OptionOrder[OptionIndex] + ); + } + } + + if (OptionMenu->MenuNumber > 0) { + HiiCreateOrderedListOpCode ( + mStartOpCodeHandle, // Container for dynamic created opcodes + QuestionId, // Question ID + VARSTORE_ID_BOOT_MAINT, // VarStore ID + VarOffset, // Offset in Buffer Storage + STRING_TOKEN (STR_CHANGE_ORDER), // Question prompt text + STRING_TOKEN (STR_CHANGE_ORDER), // Question help text + 0, // Question flag + 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET + EFI_IFR_TYPE_NUM_SIZE_32, // Data type of Question value + 100, // Maximum container + OptionsOpCodeHandle, // Option Opcode list + NULL // Default Opcode is NULL + ); + } + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + UpdatePageEnd (CallbackData); +} + +/** + Create the dynamic page to allow user to set + the "BootNext" value. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateBootNextPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINTN NumberOfOptions; + UINT16 Index; + VOID *OptionsOpCodeHandle; + + NumberOfOptions = BootOptionMenu.MenuNumber; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); + + if (NumberOfOptions > 0) { + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + //CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber); + + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewLoadContext->IsBootNext) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + EFI_IFR_OPTION_DEFAULT, + EFI_IFR_TYPE_NUM_SIZE_16, + Index + ); + //CallbackData->BmmFakeNvData.BootNext = Index; + } else { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + Index + ); + } + } + + if (CallbackData->BmmFakeNvData.BootNext == Index) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_NONE), + EFI_IFR_OPTION_DEFAULT, + EFI_IFR_TYPE_NUM_SIZE_16, + Index + ); + } else { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_NONE), + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + BOOT_NEXT_VAR_OFFSET, + STRING_TOKEN (STR_BOOT_NEXT), + STRING_TOKEN (STR_BOOT_NEXT_HELP), + 0, + EFI_IFR_NUMERIC_SIZE_2, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + } + + UpdatePageEnd (CallbackData); +} + +/** + Create the dynamic page to allow user to set the "TimeOut" value. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateTimeOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT16 BootTimeOut; + VOID *DefaultOpCodeHandle; + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + + BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); + + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + HiiCreateDefaultOpCode (DefaultOpCodeHandle, EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_NUM_SIZE_16, BootTimeOut); + + HiiCreateNumericOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + BOOT_TIME_OUT_VAR_OFFSET, + STRING_TOKEN (STR_NUM_AUTO_BOOT), + STRING_TOKEN (STR_HLP_AUTO_BOOT), + 0, + EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC, + 0, + 65535, + 0, + DefaultOpCodeHandle + ); + + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + + //CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut; + + UpdatePageEnd (CallbackData); +} + +/** + Refresh the text mode page. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateConModePage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Mode; + UINTN Index; + UINTN Col; + UINTN Row; + CHAR16 ModeString[50]; + CHAR16 *PStr; + UINTN MaxMode; + UINTN ValidMode; + EFI_STRING_ID *ModeToken; + EFI_STATUS Status; + VOID *OptionsOpCodeHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + + ConOut = gST->ConOut; + Index = 0; + ValidMode = 0; + MaxMode = (UINTN) (ConOut->Mode->MaxMode); + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + + // + // Check valid mode + // + for (Mode = 0; Mode < MaxMode; Mode++) { + Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); + if (EFI_ERROR (Status)) { + continue; + } + ValidMode++; + } + + if (ValidMode == 0) { + return; + } + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + ModeToken = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode); + ASSERT(ModeToken != NULL); + + // + // Determin which mode should be the first entry in menu + // + // GetConsoleOutMode (CallbackData); + + // + // Build text mode options + // + for (Mode = 0; Mode < MaxMode; Mode++) { + Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Build mode string Column x Row + // + UnicodeValueToString (ModeString, 0, Col, 0); + PStr = &ModeString[0]; + StrCatS (PStr, sizeof (ModeString) / sizeof (ModeString[0]), L" x "); + PStr = PStr + StrLen (PStr); + UnicodeValueToString (PStr , 0, Row, 0); + + ModeToken[Index] = HiiSetString (CallbackData->BmmHiiHandle, 0, ModeString, NULL); + + if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + ModeToken[Index], + EFI_IFR_OPTION_DEFAULT, + EFI_IFR_TYPE_NUM_SIZE_16, + (UINT16) Mode + ); + } else { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + ModeToken[Index], + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + (UINT16) Mode + ); + } + Index++; + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) CON_MODE_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + CON_MODE_VAR_OFFSET, + STRING_TOKEN (STR_CON_MODE_SETUP), + STRING_TOKEN (STR_CON_MODE_SETUP), + EFI_IFR_FLAG_RESET_REQUIRED, + EFI_IFR_NUMERIC_SIZE_2, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + FreePool (ModeToken); + + UpdatePageEnd (CallbackData); +} + +/** + Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits, + Parity, Stop Bits, Terminal Type. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateTerminalPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT8 Index; + UINT8 CheckFlags; + BM_MENU_ENTRY *NewMenuEntry; + VOID *OptionsOpCodeHandle; + UINTN CurrentTerminal; + + UpdatePageStart (CallbackData); + + CurrentTerminal = CallbackData->CurrentTerminal; + NewMenuEntry = BOpt_GetMenuEntry ( + &TerminalMenu, + CurrentTerminal + ); + + if (NewMenuEntry == NULL) { + return ; + } + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) { + CheckFlags = 0; + if (BaudRateList[Index].Value == 115200) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + } + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + BaudRateList[Index].StringToken, + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (COM_BAUD_RATE_QUESTION_ID + CurrentTerminal), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (COM_BAUD_RATE_VAR_OFFSET + CurrentTerminal), + STRING_TOKEN (STR_COM_BAUD_RATE), + STRING_TOKEN (STR_COM_BAUD_RATE), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (DataBitsList) / sizeof (DataBitsList[0]); Index++) { + CheckFlags = 0; + + if (DataBitsList[Index].Value == 8) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + DataBitsList[Index].StringToken, + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (COM_DATA_RATE_QUESTION_ID + CurrentTerminal), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (COM_DATA_RATE_VAR_OFFSET + CurrentTerminal), + STRING_TOKEN (STR_COM_DATA_BITS), + STRING_TOKEN (STR_COM_DATA_BITS), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (ParityList) / sizeof (ParityList[0]); Index++) { + CheckFlags = 0; + if (ParityList[Index].Value == NoParity) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + ParityList[Index].StringToken, + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (COM_PARITY_QUESTION_ID + CurrentTerminal), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (COM_PARITY_VAR_OFFSET + CurrentTerminal), + STRING_TOKEN (STR_COM_PARITY), + STRING_TOKEN (STR_COM_PARITY), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (StopBitsList) / sizeof (StopBitsList[0]); Index++) { + CheckFlags = 0; + if (StopBitsList[Index].Value == OneStopBit) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + StopBitsList[Index].StringToken, + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (COM_STOP_BITS_QUESTION_ID + CurrentTerminal), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (COM_STOP_BITS_VAR_OFFSET + CurrentTerminal), + STRING_TOKEN (STR_COM_STOP_BITS), + STRING_TOKEN (STR_COM_STOP_BITS), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < 4; Index++) { + CheckFlags = 0; + if (Index == 0) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + (EFI_STRING_ID) TerminalType[Index], + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (COM_TERMINAL_QUESTION_ID + CurrentTerminal), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (COM_TERMINAL_VAR_OFFSET + CurrentTerminal), + STRING_TOKEN (STR_COM_TERMI_TYPE), + STRING_TOKEN (STR_COM_TERMI_TYPE), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (mFlowControlType) / sizeof (mFlowControlType[0]); Index++) { + CheckFlags = 0; + if (Index == 0) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + } + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + (EFI_STRING_ID) mFlowControlType[Index], + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + mFlowControlValue[Index] + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (COM_FLOWCONTROL_QUESTION_ID + CurrentTerminal), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (COM_FLOWCONTROL_VAR_OFFSET + CurrentTerminal), + STRING_TOKEN (STR_COM_FLOW_CONTROL), + STRING_TOKEN (STR_COM_FLOW_CONTROL), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + UpdatePageEnd (CallbackData); +} + +/** + Dispatch the correct update page function to call based on + the UpdatePageId. + + @param UpdatePageId The form ID. + @param CallbackData The BMM context data. + +**/ +VOID +UpdatePageBody ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + CleanUpPage (UpdatePageId, CallbackData); + switch (UpdatePageId) { + case FORM_CON_IN_ID: + UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData); + break; + + case FORM_CON_OUT_ID: + UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData); + break; + + case FORM_CON_ERR_ID: + UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData); + break; + + case FORM_BOOT_CHG_ID: + UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData); + break; + + case FORM_DRV_CHG_ID: + UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData); + break; + + default: + break; + } +} + +/** + Create a dynamic page so that Legacy Device boot order + can be set for specified device type. + + @param UpdatePageId The form ID. It also spefies the legacy device type. + @param CallbackData The BMM context data. + + +**/ +VOID +UpdateSetLegacyDeviceOrderPage ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + LEGACY_DEV_ORDER_ENTRY *DevOrder; + BM_MENU_OPTION *OptionMenu; + BM_MENU_ENTRY *NewMenuEntry; + EFI_STRING_ID StrRef; + EFI_STRING_ID StrRefHelp; + BBS_TYPE BbsType; + UINTN VarSize; + UINTN Pos; + UINTN Bit; + UINT16 Index; + UINT16 Key; + CHAR16 String[100]; + CHAR16 *TypeStr; + CHAR16 *TypeStrHelp; + UINT16 VarDevOrder; + UINT8 *VarData; + UINT8 *LegacyOrder; + UINT8 *OldData; + UINT8 *DisMap; + VOID *OptionsOpCodeHandle; + + OptionMenu = NULL; + Key = 0; + StrRef = 0; + StrRefHelp = 0; + TypeStr = NULL; + TypeStrHelp = NULL; + BbsType = BBS_FLOPPY; + LegacyOrder = NULL; + OldData = NULL; + DisMap = NULL; + + CallbackData->BmmAskSaveOrNot = TRUE; + UpdatePageStart (CallbackData); + + DisMap = ZeroMem (CallbackData->BmmOldFakeNVData.DisableMap, sizeof (CallbackData->BmmOldFakeNVData.DisableMap)); + + // + // Create oneof option list + // + switch (UpdatePageId) { + case FORM_SET_FD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; + Key = (UINT16) LEGACY_FD_QUESTION_ID; + TypeStr = STR_FLOPPY; + TypeStrHelp = STR_FLOPPY_HELP; + BbsType = BBS_FLOPPY; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD; + OldData = CallbackData->BmmOldFakeNVData.LegacyFD; + break; + + case FORM_SET_HD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; + Key = (UINT16) LEGACY_HD_QUESTION_ID; + TypeStr = STR_HARDDISK; + TypeStrHelp = STR_HARDDISK_HELP; + BbsType = BBS_HARDDISK; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD; + OldData = CallbackData->BmmOldFakeNVData.LegacyHD; + break; + + case FORM_SET_CD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; + Key = (UINT16) LEGACY_CD_QUESTION_ID; + TypeStr = STR_CDROM; + TypeStrHelp = STR_CDROM_HELP; + BbsType = BBS_CDROM; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD; + OldData = CallbackData->BmmOldFakeNVData.LegacyCD; + break; + + case FORM_SET_NET_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; + Key = (UINT16) LEGACY_NET_QUESTION_ID; + TypeStr = STR_NET; + TypeStrHelp = STR_NET_HELP; + BbsType = BBS_EMBED_NETWORK; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET; + OldData = CallbackData->BmmOldFakeNVData.LegacyNET; + break; + + case FORM_SET_BEV_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; + Key = (UINT16) LEGACY_BEV_QUESTION_ID; + TypeStr = STR_BEV; + TypeStrHelp = STR_BEV_HELP; + BbsType = BBS_BEV_DEVICE; + LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV; + OldData = CallbackData->BmmOldFakeNVData.LegacyBEV; + break; + + default: + DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n")); + return; + } + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); + // + // Create OneOf for each legacy device + // + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + EFI_IFR_TYPE_NUM_SIZE_8, + (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex + ); + } + + // + // Create OneOf for item "Disabled" + // + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE), + 0, + EFI_IFR_TYPE_NUM_SIZE_8, + 0xFF + ); + + // + // Get Device Order from variable + // + VarData = BdsLibGetVariableAndSize ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + &VarSize + ); + + if (NULL != VarData) { + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; + while (VarData < VarData + VarSize) { + if (DevOrder->BbsType == BbsType) { + break; + } + + VarData = (UINT8 *)((UINTN)VarData + sizeof (BBS_TYPE)); + VarData += *(UINT16 *) VarData; + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; + } + // + // Create oneof tag here for FD/HD/CD #1 #2 + // + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + // + // Create the string for oneof tag + // + UnicodeSPrint (String, sizeof (String), TypeStr, Index); + StrRef = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL); + + UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index); + StrRefHelp = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL); + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (Key + Index), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (Key + Index - CONFIG_OPTION_OFFSET), + StrRef, + StrRefHelp, + EFI_IFR_FLAG_CALLBACK, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + VarDevOrder = *(UINT16 *) ((UINTN) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16)); + + if (0xFF00 == (VarDevOrder & 0xFF00)) { + LegacyOrder[Index] = 0xFF; + Pos = (VarDevOrder & 0xFF) / 8; + Bit = 7 - ((VarDevOrder & 0xFF) % 8); + DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + } else { + LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF); + } + } + } + + CopyMem (OldData, LegacyOrder, 100); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + UpdatePageEnd (CallbackData); +} + + +/** + Dispatch the display to the next page based on NewPageId. + + @param Private The BMM context data. + @param NewPageId The original page ID. + +**/ +VOID +UpdatePageId ( + BMM_CALLBACK_DATA *Private, + UINT16 NewPageId + ) +{ + // + // For the question don't impact the page update, just ignore it. + // + if (((NewPageId >= BOOT_OPTION_DEL_QUESTION_ID) && (NewPageId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) || + ((NewPageId >= DRIVER_OPTION_DEL_QUESTION_ID) && (NewPageId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER))) { + return; + } + + if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) { + // + // If we select a handle to add driver option, advance to the add handle description page. + // + NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID; + } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) { + // + // Return to main page after "Save Changes" or "Discard Changes". + // + NewPageId = FORM_MAIN_ID; + } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) { + NewPageId = FORM_CON_COM_SETUP_ID; + } + + if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) { + Private->BmmPreviousPageId = Private->BmmCurrentPageId; + Private->BmmCurrentPageId = NewPageId; + } +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c new file mode 100644 index 0000000000..b933dd9699 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c @@ -0,0 +1,1380 @@ +/** @file + Variable operation that will be used by bootmaint + +Copyright (c) 2004 - 2015, Intel 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 "BootMaint.h" + +/** + Delete Boot Option that represent a Deleted state in BootOptionMenu. + After deleting this boot option, call Var_ChangeBootOrder to + make sure BootOrder is in valid state. + + @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to + BM_LOAD_CONTEXT marked for deletion is deleted. + @retval EFI_NOT_FOUND If can not find the boot option want to be deleted. + @return Others If failed to update the "BootOrder" variable after deletion. + +**/ +EFI_STATUS +Var_DelBootOption ( + VOID + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 BootString[10]; + EFI_STATUS Status; + UINTN Index; + UINTN Index2; + + Status = EFI_SUCCESS; + Index2 = 0; + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2)); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (!NewLoadContext->Deleted) { + continue; + } + + UnicodeSPrint ( + BootString, + sizeof (BootString), + L"Boot%04x", + NewMenuEntry->OptionNumber + ); + + EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid); + Index2++; + // + // If current Load Option is the same as BootNext, + // must delete BootNext in order to make sure + // there will be no panic on next boot + // + if (NewLoadContext->IsBootNext) { + EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid); + } + + RemoveEntryList (&NewMenuEntry->Link); + BOpt_DestroyMenuEntry (NewMenuEntry); + NewMenuEntry = NULL; + } + + BootOptionMenu.MenuNumber -= Index2; + + Status = Var_ChangeBootOrder (); + return Status; +} + +/** + After any operation on Boot####, there will be a discrepancy in BootOrder. + Since some are missing but in BootOrder, while some are present but are + not reflected by BootOrder. Then a function rebuild BootOrder from + scratch by content from BootOptionMenu is needed. + + + + + @retval EFI_SUCCESS The boot order is updated successfully. + @return EFI_STATUS other than EFI_SUCCESS if failed to + Set the "BootOrder" EFI Variable. + +**/ +EFI_STATUS +Var_ChangeBootOrder ( + VOID + ) +{ + + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *BootOrderList; + UINT16 *BootOrderListPtr; + UINTN BootOrderListSize; + UINTN Index; + + BootOrderList = NULL; + BootOrderListSize = 0; + + // + // First check whether BootOrder is present in current configuration + // + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + + // + // If exists, delete it to hold new BootOrder + // + if (BootOrderList != NULL) { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + FreePool (BootOrderList); + BootOrderList = NULL; + } + // + // Maybe here should be some check method to ensure that + // no new added boot options will be added + // but the setup engine now will give only one callback + // that is to say, user are granted only one chance to + // decide whether the boot option will be added or not + // there should be no indictor to show whether this + // is a "new" boot option + // + BootOrderListSize = BootOptionMenu.MenuNumber; + + if (BootOrderListSize > 0) { + BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16)); + ASSERT (BootOrderList != NULL); + BootOrderListPtr = BootOrderList; + + // + // Get all current used Boot#### from BootOptionMenu. + // OptionNumber in each BM_LOAD_OPTION is really its + // #### value. + // + for (Index = 0; Index < BootOrderListSize; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + *BootOrderList = (UINT16) NewMenuEntry->OptionNumber; + BootOrderList++; + } + + BootOrderList = BootOrderListPtr; + + // + // After building the BootOrderList, write it back + // + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderListSize * sizeof (UINT16), + BootOrderList + ); + // + // Changing variable without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } + return EFI_SUCCESS; +} + +/** + Delete Load Option that represent a Deleted state in BootOptionMenu. + After deleting this Driver option, call Var_ChangeDriverOrder to + make sure DriverOrder is in valid state. + + @retval EFI_SUCCESS Load Option is successfully updated. + @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted. + @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI + Variable. + +**/ +EFI_STATUS +Var_DelDriverOption ( + VOID + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 DriverString[12]; + EFI_STATUS Status; + UINTN Index; + UINTN Index2; + + Status = EFI_SUCCESS; + Index2 = 0; + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2)); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (!NewLoadContext->Deleted) { + continue; + } + + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + NewMenuEntry->OptionNumber + ); + + EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid); + Index2++; + + RemoveEntryList (&NewMenuEntry->Link); + BOpt_DestroyMenuEntry (NewMenuEntry); + NewMenuEntry = NULL; + } + + DriverOptionMenu.MenuNumber -= Index2; + + Status = Var_ChangeDriverOrder (); + return Status; +} + +/** + After any operation on Driver####, there will be a discrepancy in + DriverOrder. Since some are missing but in DriverOrder, while some + are present but are not reflected by DriverOrder. Then a function + rebuild DriverOrder from scratch by content from DriverOptionMenu is + needed. + + @retval EFI_SUCCESS The driver order is updated successfully. + @return Other status than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable. + +**/ +EFI_STATUS +Var_ChangeDriverOrder ( + VOID + ) +{ + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *DriverOrderList; + UINT16 *DriverOrderListPtr; + UINTN DriverOrderListSize; + UINTN Index; + + DriverOrderList = NULL; + DriverOrderListSize = 0; + + // + // First check whether DriverOrder is present in current configuration + // + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + + // + // If exists, delete it to hold new DriverOrder + // + if (DriverOrderList != NULL) { + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + FreePool (DriverOrderList); + DriverOrderList = NULL; + } + + DriverOrderListSize = DriverOptionMenu.MenuNumber; + + if (DriverOrderListSize > 0) { + DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16)); + ASSERT (DriverOrderList != NULL); + DriverOrderListPtr = DriverOrderList; + + // + // Get all current used Driver#### from DriverOptionMenu. + // OptionNumber in each BM_LOAD_OPTION is really its + // #### value. + // + for (Index = 0; Index < DriverOrderListSize; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber; + DriverOrderList++; + } + + DriverOrderList = DriverOrderListPtr; + + // + // After building the DriverOrderList, write it back + // + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + DriverOrderListSize * sizeof (UINT16), + DriverOrderList + ); + // + // Changing variable without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } + return EFI_SUCCESS; +} + +/** + Update the device path of "ConOut", "ConIn" and "ErrOut" + based on the new BaudRate, Data Bits, parity and Stop Bits + set. + +**/ +VOID +Var_UpdateAllConsoleOption ( + VOID + ) +{ + EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; + EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; + EFI_STATUS Status; + + OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid); + InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid); + ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid); + if (OutDevicePath != NULL) { + ChangeVariableDevicePath (OutDevicePath); + Status = gRT->SetVariable ( + L"ConOut", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (OutDevicePath), + OutDevicePath + ); + // + // Changing variable without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } + + if (InpDevicePath != NULL) { + ChangeVariableDevicePath (InpDevicePath); + Status = gRT->SetVariable ( + L"ConIn", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (InpDevicePath), + InpDevicePath + ); + // + // Changing variable without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } + + if (ErrDevicePath != NULL) { + ChangeVariableDevicePath (ErrDevicePath); + Status = gRT->SetVariable ( + L"ErrOut", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (ErrDevicePath), + ErrDevicePath + ); + // + // Changing variable without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } +} + +/** + This function delete and build multi-instance device path for + specified type of console device. + + This function clear the EFI variable defined by ConsoleName and + gEfiGlobalVariableGuid. It then build the multi-instance device + path by appending the device path of the Console (In/Out/Err) instance + in ConsoleMenu. Then it scan all corresponding console device by + scanning Terminal (built from device supporting Serial I/O instances) + devices in TerminalMenu. At last, it save a EFI variable specifed + by ConsoleName and gEfiGlobalVariableGuid. + + @param ConsoleName The name for the console device type. They are + usually "ConIn", "ConOut" and "ErrOut". + @param ConsoleMenu The console memu which is a list of console devices. + @param UpdatePageId The flag specifying which type of console device + to be processed. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateConsoleOption ( + IN UINT16 *ConsoleName, + IN BM_MENU_OPTION *ConsoleMenu, + IN UINT16 UpdatePageId + ) +{ + EFI_DEVICE_PATH_PROTOCOL *ConDevicePath; + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + EFI_STATUS Status; + VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath; + UINTN Index; + + ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid); + if (ConDevicePath != NULL) { + EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid); + FreePool (ConDevicePath); + ConDevicePath = NULL; + }; + + // + // First add all console input device from console input menu + // + for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); + + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + if (NewConsoleContext->IsActive) { + ConDevicePath = AppendDevicePathInstance ( + ConDevicePath, + NewConsoleContext->DevicePath + ); + } + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) || + ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) || + ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID)) + ) { + Vendor.Header.Type = MESSAGING_DEVICE_PATH; + Vendor.Header.SubType = MSG_VENDOR_DP; + + ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0]))); + CopyMem ( + &Vendor.Guid, + &TerminalTypeGuid[NewTerminalContext->TerminalType], + sizeof (EFI_GUID) + ); + SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); + TerminalDevicePath = AppendDevicePathNode ( + NewTerminalContext->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Vendor + ); + ASSERT (TerminalDevicePath != NULL); + ChangeTerminalDevicePath (&TerminalDevicePath, TRUE); + ConDevicePath = AppendDevicePathInstance ( + ConDevicePath, + TerminalDevicePath + ); + } + } + + if (ConDevicePath != NULL) { + Status = gRT->SetVariable ( + ConsoleName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (ConDevicePath), + ConDevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; + +} + +/** + This function delete and build multi-instance device path ConIn + console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateConsoleInpOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID); +} + +/** + This function delete and build multi-instance device path ConOut + console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateConsoleOutOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID); +} + +/** + This function delete and build multi-instance device path ErrOut + console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateErrorOutOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID); +} + +/** + This function create a currently loaded Drive Option from + the BMM. It then appends this Driver Option to the end of + the "DriverOrder" list. It append this Driver Opotion to the end + of DriverOptionMenu. + + @param CallbackData The BMM context data. + @param HiiHandle The HII handle associated with the BMM formset. + @param DescriptionData The description of this driver option. + @param OptionalData The optional load option. + @param ForceReconnect If to force reconnect. + + @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. + @retval EFI_SUCCESS If function completes successfully. + +**/ +EFI_STATUS +Var_UpdateDriverOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 *DescriptionData, + IN UINT16 *OptionalData, + IN UINT8 ForceReconnect + ) +{ + UINT16 Index; + UINT16 *DriverOrderList; + UINT16 *NewDriverOrderList; + UINT16 DriverString[12]; + UINTN DriverOrderListSize; + VOID *Buffer; + UINTN BufferSize; + UINT8 *Ptr; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BOOLEAN OptionalDataExist; + EFI_STATUS Status; + + OptionalDataExist = FALSE; + + Index = BOpt_GetDriverOptionNumber (); + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + Index + ); + + if (*DescriptionData == 0x0000) { + StrCpyS (DescriptionData, DESCRIPTION_DATA_SIZE, DriverString); + } + + BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData); + BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + if (*OptionalData != 0x0000) { + OptionalDataExist = TRUE; + BufferSize += StrSize (OptionalData); + } + + Buffer = AllocateZeroPool (BufferSize); + if (NULL == Buffer) { + return EFI_OUT_OF_RESOURCES; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + FreePool (Buffer); + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + NewLoadContext->LoadOptionSize = BufferSize; + Ptr = (UINT8 *) Buffer; + NewLoadContext->LoadOption = Ptr; + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1); + NewLoadContext->Attributes = *((UINT32 *) Ptr); + NewLoadContext->IsActive = TRUE; + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + Ptr += sizeof (UINT32); + *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); + + Ptr += sizeof (UINT16); + CopyMem ( + Ptr, + DescriptionData, + StrSize (DescriptionData) + ); + + NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData)); + ASSERT (NewLoadContext->Description != NULL); + NewMenuEntry->DisplayString = NewLoadContext->Description; + CopyMem ( + NewLoadContext->Description, + (VOID *) Ptr, + StrSize (DescriptionData) + ); + + Ptr += StrSize (DescriptionData); + CopyMem ( + Ptr, + CallbackData->LoadContext->FilePathList, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); + ASSERT (NewLoadContext->FilePathList != NULL); + + CopyMem ( + NewLoadContext->FilePathList, + (VOID *) Ptr, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->OptionNumber = Index; + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionStrDepository + ); + NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL); + + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionHelpStrDepository + ); + NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL); + + if (OptionalDataExist) { + Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + CopyMem ( + Ptr, + OptionalData, + StrSize (OptionalData) + ); + } + + Status = gRT->SetVariable ( + DriverString, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BufferSize, + Buffer + ); + if (!EFI_ERROR (Status)) { + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16)); + ASSERT (NewDriverOrderList != NULL); + if (DriverOrderList != NULL) { + CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize); + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + } + NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index; + + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + DriverOrderListSize + sizeof (UINT16), + NewDriverOrderList + ); + if (DriverOrderList != NULL) { + FreePool (DriverOrderList); + } + DriverOrderList = NULL; + FreePool (NewDriverOrderList); + if (!EFI_ERROR (Status)) { + InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); + DriverOptionMenu.MenuNumber++; + + // + // Update "change boot order" page used data, append the new add boot + // option at the end. + // + Index = 0; + while (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] != 0) { + Index++; + } + CallbackData->BmmFakeNvData.DriverOptionOrder[Index] = (UINT32) (NewMenuEntry->OptionNumber + 1); + + *DescriptionData = 0x0000; + *OptionalData = 0x0000; + } + } + return EFI_SUCCESS; +} + +/** + This function create a currently loaded Boot Option from + the BMM. It then appends this Boot Option to the end of + the "BootOrder" list. It also append this Boot Opotion to the end + of BootOptionMenu. + + @param CallbackData The BMM context data. + @param NvRamMap The file explorer formset internal state. + + @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. + @retval EFI_SUCCESS If function completes successfully. + +**/ +EFI_STATUS +Var_UpdateBootOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN FILE_EXPLORER_NV_DATA *NvRamMap + ) +{ + UINT16 *BootOrderList; + UINT16 *NewBootOrderList; + UINTN BootOrderListSize; + UINT16 BootString[10]; + VOID *Buffer; + UINTN BufferSize; + UINT8 *Ptr; + UINT16 Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BOOLEAN OptionalDataExist; + EFI_STATUS Status; + + OptionalDataExist = FALSE; + + Index = BOpt_GetBootOptionNumber () ; + UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index); + + if (NvRamMap->BootDescriptionData[0] == 0x0000) { + StrCpyS ( + NvRamMap->BootDescriptionData, + sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), + BootString + ); + } + + BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->BootDescriptionData); + BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + if (NvRamMap->BootOptionalData[0] != 0x0000) { + OptionalDataExist = TRUE; + BufferSize += StrSize (NvRamMap->BootOptionalData); + } + + Buffer = AllocateZeroPool (BufferSize); + if (NULL == Buffer) { + return EFI_OUT_OF_RESOURCES; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + NewLoadContext->LoadOptionSize = BufferSize; + Ptr = (UINT8 *) Buffer; + NewLoadContext->LoadOption = Ptr; + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; + NewLoadContext->Attributes = *((UINT32 *) Ptr); + NewLoadContext->IsActive = TRUE; + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + Ptr += sizeof (UINT32); + *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); + Ptr += sizeof (UINT16); + + CopyMem ( + Ptr, + NvRamMap->BootDescriptionData, + StrSize (NvRamMap->BootDescriptionData) + ); + + NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData)); + ASSERT (NewLoadContext->Description != NULL); + + NewMenuEntry->DisplayString = NewLoadContext->Description; + CopyMem ( + NewLoadContext->Description, + (VOID *) Ptr, + StrSize (NvRamMap->BootDescriptionData) + ); + + Ptr += StrSize (NvRamMap->BootDescriptionData); + CopyMem ( + Ptr, + CallbackData->LoadContext->FilePathList, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); + ASSERT (NewLoadContext->FilePathList != NULL); + + CopyMem ( + NewLoadContext->FilePathList, + (VOID *) Ptr, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->OptionNumber = Index; + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionStrDepository + ); + NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL); + + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionHelpStrDepository + ); + NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->HelpString, NULL); + + if (OptionalDataExist) { + Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + CopyMem (Ptr, NvRamMap->BootOptionalData, StrSize (NvRamMap->BootOptionalData)); + } + + Status = gRT->SetVariable ( + BootString, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BufferSize, + Buffer + ); + if (!EFI_ERROR (Status)) { + + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + ASSERT (BootOrderList != NULL); + NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16)); + ASSERT (NewBootOrderList != NULL); + CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize); + NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index; + + if (BootOrderList != NULL) { + FreePool (BootOrderList); + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderListSize + sizeof (UINT16), + NewBootOrderList + ); + if (!EFI_ERROR (Status)) { + + FreePool (NewBootOrderList); + NewBootOrderList = NULL; + InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + BootOptionMenu.MenuNumber++; + + // + // Update "change driver order" page used data, append the new add driver + // option at the end. + // + Index = 0; + while (CallbackData->BmmFakeNvData.BootOptionOrder[Index] != 0) { + Index++; + } + CallbackData->BmmFakeNvData.BootOptionOrder[Index] = (UINT32) (NewMenuEntry->OptionNumber + 1); + + NvRamMap->BootDescriptionData[0] = 0x0000; + NvRamMap->BootOptionalData[0] = 0x0000; + } + } + return EFI_SUCCESS; +} + +/** + This function update the "BootNext" EFI Variable. If there is + no "BootNext" specified in BMM, this EFI Variable is deleted. + It also update the BMM context data specified the "BootNext" + vaule. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can be saved. See gRT->SetVariable + for detail return information. + +**/ +EFI_STATUS +Var_UpdateBootNext ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BMM_FAKE_NV_DATA *CurrentFakeNVMap; + UINT16 Index; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + CurrentFakeNVMap = &CallbackData->BmmFakeNvData; + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + ASSERT (NULL != NewMenuEntry); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->IsBootNext = FALSE; + } + + if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) { + EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid); + return EFI_SUCCESS; + } + + NewMenuEntry = BOpt_GetMenuEntry ( + &BootOptionMenu, + CurrentFakeNVMap->BootNext + ); + ASSERT (NewMenuEntry != NULL); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + Status = gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &NewMenuEntry->OptionNumber + ); + NewLoadContext->IsBootNext = TRUE; + CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext; + return Status; +} + +/** + This function update the "BootOrder" EFI Variable based on + BMM Formset's NV map. It then refresh BootOptionMenu + with the new "BootOrder" list. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + UINT16 Index; + UINT16 OrderIndex; + UINT16 *BootOrderList; + UINTN BootOrderListSize; + UINT16 OptionNumber; + + BootOrderList = NULL; + BootOrderListSize = 0; + + // + // First check whether BootOrder is present in current configuration + // + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + if (BootOrderList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0]))); + + for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) { + for (Index = OrderIndex; Index < BootOrderListSize / sizeof (UINT16); Index++) { + if ((BootOrderList[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) { + OptionNumber = BootOrderList[Index]; + CopyMem (&BootOrderList[OrderIndex + 1], &BootOrderList[OrderIndex], (Index - OrderIndex) * sizeof (UINT16)); + BootOrderList[OrderIndex] = OptionNumber; + } + } + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderListSize, + BootOrderList + ); + // + // Changing the content without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + FreePool (BootOrderList); + + GroupMultipleLegacyBootOption4SameType (); + + BOpt_FreeMenu (&BootOptionMenu); + BOpt_GetBootOptions (CallbackData); + + return Status; + +} + +/** + This function update the "DriverOrder" EFI Variable based on + BMM Formset's NV map. It then refresh DriverOptionMenu + with the new "DriverOrder" list. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + UINT16 Index; + UINT16 *DriverOrderList; + UINT16 *NewDriverOrderList; + UINTN DriverOrderListSize; + + DriverOrderList = NULL; + DriverOrderListSize = 0; + + // + // First check whether DriverOrder is present in current configuration + // + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + + NewDriverOrderList = AllocateZeroPool (DriverOrderListSize); + + if (NewDriverOrderList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // If exists, delete it to hold new DriverOrder + // + if (DriverOrderList != NULL) { + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + FreePool (DriverOrderList); + } + + ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0]))); + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1); + } + + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + DriverOrderListSize, + NewDriverOrderList + ); + // + // Changing the content without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + BOpt_FreeMenu (&DriverOptionMenu); + BOpt_GetDriverOptions (CallbackData); + return EFI_SUCCESS; +} + +/** + Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable + is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid + is also updated. + + @param CallbackData The context data for BMM. + @param FormId The form id. + + @return EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource +**/ +EFI_STATUS +Var_UpdateBBSOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_FORM_ID FormId + ) +{ + UINTN Index; + UINTN Index2; + VOID *BootOptionVar; + CHAR16 VarName[100]; + UINTN OptionSize; + EFI_STATUS Status; + UINT32 *Attribute; + BM_MENU_OPTION *OptionMenu; + UINT8 *LegacyDev; + UINT8 *VarData; + UINTN VarSize; + LEGACY_DEV_ORDER_ENTRY *DevOrder; + UINT8 *OriginalPtr; + UINT8 *DisMap; + UINTN Pos; + UINTN Bit; + UINT16 *NewOrder; + UINT16 Tmp; + UINT16 *EnBootOption; + UINTN EnBootOptionCount; + UINT16 *DisBootOption; + UINTN DisBootOptionCount; + + DisMap = NULL; + NewOrder = NULL; + + switch (FormId) { + case FORM_SET_FD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; + LegacyDev = CallbackData->BmmFakeNvData.LegacyFD; + CallbackData->BbsType = BBS_FLOPPY; + break; + + case FORM_SET_HD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; + LegacyDev = CallbackData->BmmFakeNvData.LegacyHD; + CallbackData->BbsType = BBS_HARDDISK; + break; + + case FORM_SET_CD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; + LegacyDev = CallbackData->BmmFakeNvData.LegacyCD; + CallbackData->BbsType = BBS_CDROM; + break; + + case FORM_SET_NET_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; + LegacyDev = CallbackData->BmmFakeNvData.LegacyNET; + CallbackData->BbsType = BBS_EMBED_NETWORK; + break; + + default: + ASSERT (FORM_SET_BEV_ORDER_ID == CallbackData->BmmPreviousPageId); + OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; + LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV; + CallbackData->BbsType = BBS_BEV_DEVICE; + break; + } + + DisMap = CallbackData->BmmOldFakeNVData.DisableMap; + Status = EFI_SUCCESS; + + + // + // Update the Variable "LegacyDevOrder" + // + VarData = (UINT8 *) BdsLibGetVariableAndSize ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + &VarSize + ); + + if (VarData == NULL) { + return EFI_NOT_FOUND; + } + + OriginalPtr = VarData; + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; + + while (VarData < OriginalPtr + VarSize) { + if (DevOrder->BbsType == CallbackData->BbsType) { + break; + } + + VarData += sizeof (BBS_TYPE) + DevOrder->Length; + DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; + } + + if (VarData >= OriginalPtr + VarSize) { + FreePool (OriginalPtr); + return EFI_NOT_FOUND; + } + + NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length)); + if (NewOrder == NULL) { + FreePool (OriginalPtr); + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + if (0xFF == LegacyDev[Index]) { + break; + } + + NewOrder[Index] = LegacyDev[Index]; + } + // + // Only the enable/disable state of each boot device with same device type can be changed, + // so we can count on the index information in DevOrder. + // DisMap bit array is the only reliable source to check a device's en/dis state, + // so we use DisMap to set en/dis state of each item in NewOrder array + // + for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) { + Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF); + Pos = Tmp / 8; + Bit = 7 - (Tmp % 8); + if ((DisMap[Pos] & (1 << Bit)) != 0) { + NewOrder[Index] = (UINT16) (0xFF00 | Tmp); + Index++; + } + } + + CopyMem ( + DevOrder->Data, + NewOrder, + DevOrder->Length - sizeof (DevOrder->Length) + ); + FreePool (NewOrder); + + Status = gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + VarSize, + OriginalPtr + ); + + + // + // Update BootOrder and Boot####.Attribute + // + // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order + // + ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1); + + OrderLegacyBootOption4SameType ( + DevOrder->Data, + DevOrder->Length / sizeof (UINT16) - 1, + &EnBootOption, + &EnBootOptionCount, + &DisBootOption, + &DisBootOptionCount + ); + + // + // 2. Deactivate the DisBootOption and activate the EnBootOption + // + for (Index = 0; Index < DisBootOptionCount; Index++) { + UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + VarName, + &gEfiGlobalVariableGuid, + &OptionSize + ); + if (BootOptionVar != NULL) { + Attribute = (UINT32 *) BootOptionVar; + *Attribute &= ~LOAD_OPTION_ACTIVE; + + Status = gRT->SetVariable ( + VarName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + OptionSize, + BootOptionVar + ); + // + // Changing the content without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + FreePool (BootOptionVar); + } + } + + for (Index = 0; Index < EnBootOptionCount; Index++) { + UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + VarName, + &gEfiGlobalVariableGuid, + &OptionSize + ); + if (BootOptionVar != NULL) { + Attribute = (UINT32 *) BootOptionVar; + *Attribute |= LOAD_OPTION_ACTIVE; + + Status = gRT->SetVariable ( + VarName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + OptionSize, + BootOptionVar + ); + // + // Changing the content without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + FreePool (BootOptionVar); + } + } + + BOpt_GetBootOptions (CallbackData); + + FreePool (OriginalPtr); + FreePool (EnBootOption); + FreePool (DisBootOption); + return Status; +} + +/** + Update the Text Mode of Console. + + @param CallbackData The context data for BMM. + + @retval EFI_SUCCSS If the Text Mode of Console is updated. + @return Other value if the Text Mode of Console is not updated. + +**/ +EFI_STATUS +Var_UpdateConMode ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + UINTN Mode; + CONSOLE_OUT_MODE ModeInfo; + + Mode = CallbackData->BmmFakeNvData.ConsoleOutMode; + + Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row)); + if (!EFI_ERROR(Status)) { + Status = PcdSet32S (PcdSetupConOutColumn, (UINT32) ModeInfo.Column); + if (!EFI_ERROR (Status)){ + Status = PcdSet32S (PcdSetupConOutRow, (UINT32) ModeInfo.Row); + } + } + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c new file mode 100644 index 0000000000..6efd783ab2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c @@ -0,0 +1,399 @@ +/** @file + The platform boot manager reference implementation + +Copyright (c) 2004 - 2015, Intel 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 "BootManager.h" + +UINT16 mKeyInput; +LIST_ENTRY mBootOptionsList; +BDS_COMMON_OPTION *gOption; +CHAR16 *mDeviceTypeStr[] = { + L"Legacy BEV", + L"Legacy Floppy", + L"Legacy Hard Drive", + L"Legacy CD ROM", + L"Legacy PCMCIA", + L"Legacy USB", + L"Legacy Embedded Network", + L"Legacy Unknown Device" +}; + + +HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + BOOT_MANAGER_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = { + BOOT_MANAGER_CALLBACK_DATA_SIGNATURE, + NULL, + NULL, + { + FakeExtractConfig, + FakeRouteConfig, + BootManagerCallback + } +}; + +/** + This call back function is registered with Boot Manager formset. + When user selects a boot option, this call back function will + be triggered. The boot option is saved for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +BootManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + BDS_COMMON_OPTION *Option; + LIST_ENTRY *Link; + UINT16 KeyCount; + + if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the key count + // + KeyCount = 0; + + for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) { + Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + KeyCount++; + + gOption = Option; + + // + // Is this device the one chosen? + // + if (KeyCount == QuestionId) { + // + // Assigning the returned Key to a global allows the original routine to know what was chosen + // + mKeyInput = QuestionId; + + // + // Request to exit SendForm(), so that we could boot the selected option + // + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + break; + } + } + + return EFI_SUCCESS; + } + + // + // All other action return unsupported. + // + return EFI_UNSUPPORTED; +} + +/** + + Registers HII packages for the Boot Manger to HII Database. + It also registers the browser call back function. + + @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully. + @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered. + +**/ +EFI_STATUS +InitializeBootManager ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gBootManagerPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mBootManagerHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gBootManagerPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data + // + gBootManagerPrivate.HiiHandle = HiiAddPackages ( + &gBootManagerFormSetGuid, + gBootManagerPrivate.DriverHandle, + BootManagerVfrBin, + BdsDxeStrings, + NULL + ); + if (gBootManagerPrivate.HiiHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = EFI_SUCCESS; + } + return Status; +} + +/** + This function invokes Boot Manager. If all devices have not a chance to be connected, + the connect all will be triggered. It then enumerate all boot options. If + a boot option from the Boot Manager page is selected, Boot Manager will boot + from this boot option. + +**/ +VOID +CallBootManager ( + VOID + ) +{ + EFI_STATUS Status; + BDS_COMMON_OPTION *Option; + LIST_ENTRY *Link; + CHAR16 *ExitData; + UINTN ExitDataSize; + EFI_STRING_ID Token; + EFI_INPUT_KEY Key; + CHAR16 *HelpString; + UINTN HelpSize; + EFI_STRING_ID HelpToken; + UINT16 *TempStr; + EFI_HII_HANDLE HiiHandle; + EFI_BROWSER_ACTION_REQUEST ActionRequest; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + UINT16 DeviceType; + BOOLEAN IsLegacyOption; + BOOLEAN NeedEndOp; + + DeviceType = (UINT16) -1; + gOption = NULL; + InitializeListHead (&mBootOptionsList); + + // + // Connect all prior to entering the platform setup menu. + // + if (!gConnectAllHappened) { + BdsLibConnectAllDriversToAllControllers (); + gConnectAllHappened = TRUE; + } + + BdsLibEnumerateAllBootOption (&mBootOptionsList); + + // + // Group the legacy boot options for the same device type + // + GroupMultipleLegacyBootOption4SameType (); + + InitializeListHead (&mBootOptionsList); + BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder"); + + HiiHandle = gBootManagerPrivate.HiiHandle; + + // + // Allocate space for creation of UpdateData Buffer + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_BOOT_OPTION; + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_BOOT_OPTION_END; + + mKeyInput = 0; + NeedEndOp = FALSE; + for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) { + Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + // + // At this stage we are creating a menu entry, thus the Keys are reproduceable + // + mKeyInput++; + + // + // Don't display the hidden/inactive boot option + // + if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) { + continue; + } + + // + // Group the legacy boot option in the sub title created dynamically + // + IsLegacyOption = (BOOLEAN) ( + (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP) + ); + + if (!IsLegacyOption && NeedEndOp) { + NeedEndOp = FALSE; + HiiCreateEndOpCode (StartOpCodeHandle); + } + + if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) { + if (NeedEndOp) { + HiiCreateEndOpCode (StartOpCodeHandle); + } + + DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType; + Token = HiiSetString ( + HiiHandle, + 0, + mDeviceTypeStr[ + MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1) + ], + NULL + ); + HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); + NeedEndOp = TRUE; + } + + ASSERT (Option->Description != NULL); + + Token = HiiSetString (HiiHandle, 0, Option->Description, NULL); + + TempStr = DevicePathToStr (Option->DevicePath); + HelpSize = StrSize (TempStr) + StrSize (L"Device Path : "); + HelpString = AllocateZeroPool (HelpSize); + ASSERT (HelpString != NULL); + StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : "); + StrCatS (HelpString, HelpSize / sizeof (CHAR16), TempStr); + + HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); + + HiiCreateActionOpCode ( + StartOpCodeHandle, + mKeyInput, + Token, + HelpToken, + EFI_IFR_FLAG_CALLBACK, + 0 + ); + } + + if (NeedEndOp) { + HiiCreateEndOpCode (StartOpCodeHandle); + } + + HiiUpdateForm ( + HiiHandle, + &gBootManagerFormSetGuid, + BOOT_MANAGER_FORM_ID, + StartOpCodeHandle, + EndOpCodeHandle + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &HiiHandle, + 1, + &gBootManagerFormSetGuid, + 0, + NULL, + &ActionRequest + ); + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + if (gOption == NULL) { + return ; + } + + // + // Will leave browser, check any reset required change is applied? if yes, reset system + // + SetupResetReminder (); + + // + // Restore to original mode before launching boot option. + // + BdsSetConsoleMode (FALSE); + + // + // parse the selected option + // + Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData); + + if (!EFI_ERROR (Status)) { + gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); + PlatformBdsBootSuccess (gOption); + } else { + gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); + PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize); + gST->ConOut->OutputString ( + gST->ConOut, + GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE)) + ); + gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + } +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h new file mode 100644 index 0000000000..e26147183a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h @@ -0,0 +1,103 @@ +/** @file + The platform boot manager reference implement + +Copyright (c) 2004 - 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 _EFI_BOOT_MANAGER_H_ +#define _EFI_BOOT_MANAGER_H_ + +#include "Bds.h" +#include "FrontPage.h" + +#define BOOT_MANAGER_FORM_ID 0x1000 + +#define LABEL_BOOT_OPTION 0x00 +#define LABEL_BOOT_OPTION_END 0x01 + +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 BootManagerVfrBin[]; + +#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('B', 'M', 'C', 'B') + +typedef struct { + UINTN Signature; + + // + // HII relative handles + // + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + // + // Produced protocols + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} BOOT_MANAGER_CALLBACK_DATA; + +/** + This call back function is registered with Boot Manager formset. + When user selects a boot option, this call back function will + be triggered. The boot option is saved for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +BootManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + + Registers HII packages for the Boot Manger to HII Database. + It also registers the browser call back function. + + @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully. + @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered. + +**/ +EFI_STATUS +InitializeBootManager ( + VOID + ); + +/** + This function invokes Boot Manager. If all devices have not a chance to be connected, + the connect all will be triggered. It then enumerate all boot options. If + a boot option from the Boot Manager page is selected, Boot Manager will boot + from this boot option. + +**/ +VOID +CallBootManager ( + VOID + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni new file mode 100644 index 0000000000..e62c264da3 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr new file mode 100644 index 0000000000..0d8142c17d --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr @@ -0,0 +1,50 @@ +///** @file +// +// Browser formset. +// +// Copyright (c) 2004 - 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 + +#define BOOT_MANAGER_FORM_ID 0x1000 + +#define LABEL_BOOT_OPTION 0x00 +#define LABEL_BOOT_OPTION_END 0x01 + +#define BOOT_MANAGER_CLASS 0x00 +#define BOOT_MANAGER_SUBCLASS 0x00 + +formset + guid = BOOT_MANAGER_FORMSET_GUID, + title = STRING_TOKEN(STR_BM_BANNER), + help = STRING_TOKEN(STR_LAST_STRING), + classguid = BOOT_MANAGER_FORMSET_GUID, + + form formid = BOOT_MANAGER_FORM_ID, + title = STRING_TOKEN(STR_BM_BANNER); + + subtitle text = STRING_TOKEN(STR_LAST_STRING); + subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER); + subtitle text = STRING_TOKEN(STR_LAST_STRING); + + // + // This is where we will dynamically add choices for the Boot Manager + // + label LABEL_BOOT_OPTION; + label LABEL_BOOT_OPTION_END; + + subtitle text = STRING_TOKEN(STR_LAST_STRING); + subtitle text = STRING_TOKEN(STR_HELP_FOOTER); + + endform; + +endformset; diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c new file mode 100644 index 0000000000..6c7fc7ced4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c @@ -0,0 +1,233 @@ +/** @file + BDS routines to handle capsules. + +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 "Bds.h" + +/** + + This routine is called to see if there are any capsules we need to process. + If the boot mode is not UPDATE, then we do nothing. Otherwise find the + capsule HOBS and produce firmware volumes for them via the DXE service. + Then call the dispatcher to dispatch drivers from them. Finally, check + the status of the updates. + + This function should be called by BDS in case we need to do some + sort of processing even if there is no capsule to process. We + need to do this if an earlier update went away and we need to + clear the capsule variable so on the next reset PEI does not see it and + think there is a capsule available. + + @param BootMode the current boot mode + + @retval EFI_INVALID_PARAMETER boot mode is not correct for an update + @retval EFI_SUCCESS There is no error when processing capsule + +**/ +EFI_STATUS +EFIAPI +BdsProcessCapsules ( + EFI_BOOT_MODE BootMode + ) +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS HobPointer; + EFI_CAPSULE_HEADER *CapsuleHeader; + UINT32 Size; + UINT32 CapsuleNumber; + UINT32 CapsuleTotalNumber; + EFI_CAPSULE_TABLE *CapsuleTable; + UINT32 Index; + UINT32 CacheIndex; + UINT32 CacheNumber; + VOID **CapsulePtr; + VOID **CapsulePtrCache; + EFI_GUID *CapsuleGuidCache; + BOOLEAN NeedReset; + + CapsuleNumber = 0; + CapsuleTotalNumber = 0; + CacheIndex = 0; + CacheNumber = 0; + CapsulePtr = NULL; + CapsulePtrCache = NULL; + CapsuleGuidCache = NULL; + NeedReset = FALSE; + + // + // We don't do anything else if the boot mode is not flash-update + // + if (BootMode != BOOT_ON_FLASH_UPDATE) { + DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update.\n")); + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + // + // Find all capsule images from hob + // + HobPointer.Raw = GetHobList (); + while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) { + CapsuleTotalNumber ++; + HobPointer.Raw = GET_NEXT_HOB (HobPointer); + } + + if (CapsuleTotalNumber == 0) { + // + // We didn't find a hob, so had no errors. + // + DEBUG ((EFI_D_ERROR, "We can not find capsule data in capsule update boot mode.\n")); + DEBUG ((EFI_D_ERROR, "Please check the followings are correct if unexpected capsule update error happens.\n")); + DEBUG ((EFI_D_ERROR, "1. CapsuleX64 is built as X64 module when PEI is IA32 and DXE is X64\n")); + DEBUG ((EFI_D_ERROR, "2. Capsule data should persist in memory across a system reset.\n")); + PlatformBdsLockNonUpdatableFlash (); + return EFI_SUCCESS; + } + + // + // Init temp Capsule Data table. + // + CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber); + ASSERT (CapsulePtr != NULL); + CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber); + ASSERT (CapsulePtrCache != NULL); + CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber); + ASSERT (CapsuleGuidCache != NULL); + + // + // Find all capsule images from hob + // + HobPointer.Raw = GetHobList (); + while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) { + CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress; + HobPointer.Raw = GET_NEXT_HOB (HobPointer); + } + + // + //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install + //capsuleTable to configure table with EFI_CAPSULE_GUID + // + + // + // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating + // System to have information persist across a system reset. EFI System Table must + // point to an array of capsules that contains the same CapsuleGuid value. And agents + // searching for this type capsule will look in EFI System Table and search for the + // capsule's Guid and associated pointer to retrieve the data. Two steps below describes + // how to sorting the capsules by the unique guid and install the array to EFI System Table. + // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an + // array for later sorting capsules by CapsuleGuid. + // + for (Index = 0; Index < CapsuleTotalNumber; Index++) { + CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) { + // + // For each capsule, we compare it with known CapsuleGuid in the CacheArray. + // If already has the Guid, skip it. Whereas, record it in the CacheArray as + // an additional one. + // + CacheIndex = 0; + while (CacheIndex < CacheNumber) { + if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) { + break; + } + CacheIndex++; + } + if (CacheIndex == CacheNumber) { + CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID)); + } + } + } + + // + // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules + // whose guid is the same as it, and malloc memory for an array which preceding + // with UINT32. The array fills with entry point of capsules that have the same + // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install + // this array into EFI System Table, so that agents searching for this type capsule + // will look in EFI System Table and search for the capsule's Guid and associated + // pointer to retrieve the data. + // + CacheIndex = 0; + while (CacheIndex < CacheNumber) { + CapsuleNumber = 0; + for (Index = 0; Index < CapsuleTotalNumber; Index++) { + CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) { + if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) { + // + // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid. + // + CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader; + } + } + } + if (CapsuleNumber != 0) { + Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*); + CapsuleTable = AllocateRuntimePool (Size); + ASSERT (CapsuleTable != NULL); + CapsuleTable->CapsuleArrayNumber = CapsuleNumber; + CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*)); + Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable); + ASSERT_EFI_ERROR (Status); + } + CacheIndex++; + } + + // + // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are + // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash + // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional + // type capsule transaction could be extended. It depends on platform policy. + // + for (Index = 0; Index < CapsuleTotalNumber; Index++) { + CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) { + // + // Always reset system after all capsule processed if FMP capsule exist + // + if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)){ + NeedReset = TRUE; + } + + // + // Call capsule library to process capsule image. + // + ProcessCapsuleImage (CapsuleHeader); + } + } + + if (NeedReset) { + Print(L"Capsule Request Cold Reboot.\n"); + + for (Index = 5; Index > 0; Index--) { + Print(L"\rResetting system in %d seconds ...", Index); + gBS->Stall (1000000); + } + + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + + CpuDeadLoop (); + } + + PlatformBdsLockNonUpdatableFlash (); + + // + // Free the allocated temp memory space. + // + FreePool (CapsuleGuidCache); + FreePool (CapsulePtrCache); + FreePool (CapsulePtr); + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c new file mode 100644 index 0000000000..af2b18a047 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c @@ -0,0 +1,2591 @@ +/** @file + The platform device manager reference implementation + +Copyright (c) 2004 - 2015, Intel 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 "DeviceManager.h" + +DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = { + DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE, + NULL, + NULL, + NULL, + NULL, + { + FakeExtractConfig, + FakeRouteConfig, + DeviceManagerCallback + }, + { + FakeExtractConfig, + FakeRouteConfig, + DriverHealthCallback + } +}; + +#define MAX_MAC_ADDRESS_NODE_LIST_LEN 10 + +// +// Which Mac Address string is select +// it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form. +// +EFI_STRING mSelectedMacAddrString; + +// +// Which form Id need to be show. +// +EFI_FORM_ID mNextShowFormId = DEVICE_MANAGER_FORM_ID; + +// +// The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID +// +MAC_ADDRESS_NODE_LIST mMacDeviceList; + +DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = { + { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS }, + { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS }, + { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS }, + { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS }, + { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS }, + { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS } +}; + +HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + DEVICE_MANAGER_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + DRIVER_HEALTH_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + This function is invoked if user selected a interactive opcode from Device Manager's + Formset. The decision by user is saved to gCallbackKey for later processing. If + user set VBIOS, the new value is saved to EFI variable. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +DeviceManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + UINTN CurIndex; + + if (Action != EFI_BROWSER_ACTION_CHANGING) { + // + // All other action return unsupported. + // + return EFI_UNSUPPORTED; + } + + if (Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + gCallbackKey = QuestionId; + if ((QuestionId < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET) && (QuestionId >= NETWORK_DEVICE_LIST_KEY_OFFSET)) { + // + // If user select the mac address, need to record mac address string to support next form show. + // + for (CurIndex = 0; CurIndex < mMacDeviceList.CurListLen; CurIndex ++) { + if (mMacDeviceList.NodeList[CurIndex].QuestionId == QuestionId) { + mSelectedMacAddrString = HiiGetString (gDeviceManagerPrivate.HiiHandle, mMacDeviceList.NodeList[CurIndex].PromptId, NULL); + } + } + } + + return EFI_SUCCESS; +} + +/** + + This function registers HII packages to HII database. + + @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully. + @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered. + +**/ +EFI_STATUS +InitializeDeviceManager ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gDeviceManagerPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mDeviceManagerHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gDeviceManagerPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &gDeviceManagerPrivate.DriverHealthHandle, + &gEfiDevicePathProtocolGuid, + &mDriverHealthHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gDeviceManagerPrivate.DriverHealthConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + mMacDeviceList.CurListLen = 0; + mMacDeviceList.MaxListLen = 0; + + return Status; +} + +/** + Extract the displayed formset for given HII handle and class guid. + + @param Handle The HII handle. + @param SetupClassGuid The class guid specifies which form set will be displayed. + @param SkipCount Skip some formsets which has processed before. + @param FormSetTitle Formset title string. + @param FormSetHelp Formset help string. + @param FormSetGuid Return the formset guid for this formset. + + @retval TRUE The formset for given HII handle will be displayed. + @return FALSE The formset for given HII handle will not be displayed. + +**/ +BOOLEAN +ExtractDisplayedHiiFormFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *SetupClassGuid, + IN UINTN SkipCount, + OUT EFI_STRING_ID *FormSetTitle, + OUT EFI_STRING_ID *FormSetHelp, + OUT EFI_GUID **FormSetGuid + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINT8 *Package; + UINT8 *OpCodeData; + UINT32 Offset; + UINT32 Offset2; + UINT32 PackageListLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + EFI_GUID *ClassGuid; + UINT8 ClassGuidNum; + + ASSERT (Handle != NULL); + ASSERT (SetupClassGuid != NULL); + ASSERT (FormSetTitle != NULL); + ASSERT (FormSetHelp != NULL); + + *FormSetTitle = 0; + *FormSetHelp = 0; + ClassGuidNum = 0; + ClassGuid = NULL; + + // + // Get HII PackageList + // + BufferSize = 0; + HiiPackageList = NULL; + Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); + // + // Handle is a invalid handle. Check if Handle is corrupted. + // + ASSERT (Status != EFI_NOT_FOUND); + // + // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. + // + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + HiiPackageList = AllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Get Form package from this HII package List + // + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + Offset2 = 0; + PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); + + while (Offset < PackageListLength) { + Package = ((UINT8 *) HiiPackageList) + Offset; + CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + + if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { + // + // Search FormSet Opcode in this Form Package + // + Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); + while (Offset2 < PackageHeader.Length) { + OpCodeData = Package + Offset2; + Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + + if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { + if (SkipCount != 0) { + SkipCount --; + continue; + } + + if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) { + // + // Find FormSet OpCode + // + ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3); + ClassGuid = (EFI_GUID *) (VOID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET)); + while (ClassGuidNum-- > 0) { + if (CompareGuid (SetupClassGuid, ClassGuid)) { + CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); + CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); + *FormSetGuid = AllocateCopyPool (sizeof (EFI_GUID), &((EFI_IFR_FORM_SET *) OpCodeData)->Guid); + ASSERT (*FormSetGuid != NULL); + FreePool (HiiPackageList); + return TRUE; + } + ClassGuid ++; + } + } else { + CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); + CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); + *FormSetGuid = AllocateCopyPool (sizeof (EFI_GUID), &((EFI_IFR_FORM_SET *) OpCodeData)->Guid); + ASSERT (*FormSetGuid != NULL); + FreePool (HiiPackageList); + return TRUE; + } + } + } + } + + // + // Go to next package + // + Offset += PackageHeader.Length; + } + + FreePool (HiiPackageList); + + return FALSE; +} + +/** + Get the mac address string from the device path. + if the device path has the vlan, get the vanid also. + + @param MacAddressNode Device path begin with mac address + @param PBuffer Output string buffer contain mac address. + +**/ +BOOLEAN +GetMacAddressString( + IN MAC_ADDR_DEVICE_PATH *MacAddressNode, + OUT CHAR16 **PBuffer + ) +{ + UINTN HwAddressSize; + UINTN Index; + UINT8 *HwAddress; + EFI_DEVICE_PATH_PROTOCOL *Node; + UINT16 VlanId; + CHAR16 *String; + UINTN BufferLen; + + VlanId = 0; + String = NULL; + ASSERT(MacAddressNode != NULL); + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (MacAddressNode->IfType == 0x01 || MacAddressNode->IfType == 0x00) { + HwAddressSize = 6; + } + + // + // The output format is MAC:XX:XX:XX:...\XXXX + // The size is the Number size + ":" size + Vlan size(\XXXX) + End + // + BufferLen = (4 + 2 * HwAddressSize + (HwAddressSize - 1) + 5 + 1) * sizeof (CHAR16); + String = AllocateZeroPool (BufferLen); + if (String == NULL) { + return FALSE; + } + + *PBuffer = String; + StrCpyS (String, BufferLen / sizeof (CHAR16), L"MAC:"); + String += 4; + + // + // Convert the MAC address into a unicode string. + // + HwAddress = &MacAddressNode->MacAddress.Addr[0]; + for (Index = 0; Index < HwAddressSize; Index++) { + String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(HwAddress++), 2); + if (Index < HwAddressSize - 1) { + *String++ = L':'; + } + } + + // + // If VLAN is configured, it will need extra 5 characters like "\0005". + // Plus one unicode character for the null-terminator. + // + Node = (EFI_DEVICE_PATH_PROTOCOL *)MacAddressNode; + while (!IsDevicePathEnd (Node)) { + if (Node->Type == MESSAGING_DEVICE_PATH && Node->SubType == MSG_VLAN_DP) { + VlanId = ((VLAN_DEVICE_PATH *) Node)->VlanId; + } + Node = NextDevicePathNode (Node); + } + + if (VlanId != 0) { + *String++ = L'\\'; + String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, VlanId, 4); + } + + // + // Null terminate the Unicode string + // + *String = L'\0'; + + return TRUE; +} + +/** + Save question id and prompt id to the mac device list. + If the same mac address has saved yet, no need to add more. + + @param MacAddrString Mac address string. + + @retval EFI_SUCCESS Add the item is successful. + @return Other values if failed to Add the item. +**/ +BOOLEAN +AddIdToMacDeviceList ( + IN EFI_STRING MacAddrString + ) +{ + MENU_INFO_ITEM *TempDeviceList; + UINTN Index; + EFI_STRING StoredString; + EFI_STRING_ID PromptId; + EFI_HII_HANDLE HiiHandle; + + HiiHandle = gDeviceManagerPrivate.HiiHandle; + TempDeviceList = NULL; + + for (Index = 0; Index < mMacDeviceList.CurListLen; Index ++) { + StoredString = HiiGetString (HiiHandle, mMacDeviceList.NodeList[Index].PromptId, NULL); + if (StoredString == NULL) { + return FALSE; + } + + // + // Already has save the same mac address to the list. + // + if (StrCmp (MacAddrString, StoredString) == 0) { + return FALSE; + } + } + + PromptId = HiiSetString(HiiHandle, 0, MacAddrString, NULL); + // + // If not in the list, save it. + // + if (mMacDeviceList.MaxListLen > mMacDeviceList.CurListLen + 1) { + mMacDeviceList.NodeList[mMacDeviceList.CurListLen].PromptId = PromptId; + mMacDeviceList.NodeList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); + } else { + mMacDeviceList.MaxListLen += MAX_MAC_ADDRESS_NODE_LIST_LEN; + if (mMacDeviceList.CurListLen != 0) { + TempDeviceList = (MENU_INFO_ITEM *)AllocateCopyPool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen, (VOID *)mMacDeviceList.NodeList); + } else { + TempDeviceList = (MENU_INFO_ITEM *)AllocatePool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen); + } + + if (TempDeviceList == NULL) { + return FALSE; + } + TempDeviceList[mMacDeviceList.CurListLen].PromptId = PromptId; + TempDeviceList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); + + if (mMacDeviceList.CurListLen > 0) { + FreePool(mMacDeviceList.NodeList); + } + + mMacDeviceList.NodeList = TempDeviceList; + } + mMacDeviceList.CurListLen ++; + + return TRUE; +} + +/** + Check the devcie path, try to find whether it has mac address path. + + In this function, first need to check whether this path has mac address path. + second, when the mac address device path has find, also need to deicide whether + need to add this mac address relate info to the menu. + + @param *Node Input device which need to be check. + @param *NeedAddItem Whether need to add the menu in the network device list. + + @retval TRUE Has mac address device path. + @retval FALSE NOT Has mac address device path. + +**/ +BOOLEAN +IsMacAddressDevicePath ( + IN VOID *Node, + OUT BOOLEAN *NeedAddItem + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + CHAR16 *Buffer; + BOOLEAN ReturnVal; + + ASSERT (Node != NULL); + *NeedAddItem = FALSE; + ReturnVal = FALSE; + Buffer = NULL; + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; + + // + // find the partition device path node + // + while (!IsDevicePathEnd (DevicePath)) { + if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP)) { + ReturnVal = TRUE; + + if (DEVICE_MANAGER_FORM_ID == mNextShowFormId) { + *NeedAddItem = TRUE; + break; + } + + if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH*)DevicePath, &Buffer)) { + break; + } + + if (NETWORK_DEVICE_FORM_ID == mNextShowFormId) { + if (StrCmp (Buffer, mSelectedMacAddrString) == 0) { + *NeedAddItem = TRUE; + } + break; + } + + if (NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) { + // + // Same handle may has two network child handle, so the questionid + // has the offset of SAME_HANDLE_KEY_OFFSET. + // + if (AddIdToMacDeviceList (Buffer)) { + *NeedAddItem = TRUE; + } + break; + } + } + DevicePath = NextDevicePathNode (DevicePath); + } + + if (Buffer != NULL) { + FreePool (Buffer); + } + + return ReturnVal; +} + +/** + Check to see if the device path is for the network device. + + @param Handle The HII handle which include the mac address device path. + @param ItemCount The new add Mac address item count. + + @retval TRUE Need to add new item in the menu. + @return FALSE Do not need to add the menu about the network. + +**/ +BOOLEAN +IsNeedAddNetworkMenu ( + IN EFI_HII_HANDLE Handle, + OUT UINTN *ItemCount + ) +{ + EFI_STATUS Status; + UINTN EntryCount; + UINTN Index; + EFI_HANDLE DriverHandle; + EFI_HANDLE ControllerHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + BOOLEAN IsNeedAdd; + + IsNeedAdd = FALSE; + OpenInfoBuffer = NULL; + if ((Handle == NULL) || (ItemCount == NULL)) { + return FALSE; + } + *ItemCount = 0; + + Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle); + if (EFI_ERROR (Status)) { + return FALSE; + } + // + // Get the device path by the got Driver handle . + // + Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath); + if (EFI_ERROR (Status)) { + return FALSE; + } + TmpDevicePath = DevicePath; + + // + // Check whether this device path include mac address device path. + // If this path has mac address path, get the value whether need + // add this info to the menu and return. + // Else check more about the child handle devcie path. + // + if (IsMacAddressDevicePath(TmpDevicePath, &IsNeedAdd)) { + if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) && IsNeedAdd) { + (*ItemCount) = 1; + } + return IsNeedAdd; + } + + // + // Search whether this path is the controller path, not he child handle path. + // And the child handle has the network devcie connected. + // + TmpDevicePath = DevicePath; + Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle); + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (!IsDevicePathEnd (TmpDevicePath)) { + return FALSE; + } + + // + // Retrieve the list of agents that are consuming the specific protocol + // on ControllerHandle. + // The buffer point by OpenInfoBuffer need be free at this function. + // + Status = gBS->OpenProtocolInformation ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Inspect if ChildHandle is one of the agents. + // + Status = EFI_UNSUPPORTED; + for (Index = 0; Index < EntryCount; Index++) { + // + // Query all the children created by the controller handle's driver + // + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + Status = gBS->OpenProtocol ( + OpenInfoBuffer[Index].ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &ChildDevicePath, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Check whether this device path include mac address device path. + // + if (!IsMacAddressDevicePath(ChildDevicePath, &IsNeedAdd)) { + // + // If this path not has mac address path, check the other. + // + continue; + } else { + // + // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more. + // + if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId)) { + if (IsNeedAdd) { + (*ItemCount) += 1; + } + continue; + } else { + // + // If need to update other form, return whether need to add to the menu. + // + goto Done; + } + } + } + } + +Done: + if (OpenInfoBuffer != NULL) { + FreePool (OpenInfoBuffer); + } + return IsNeedAdd; +} + +/** + Get HiiHandle total number. + + @param HiiHandles The input HiiHandle array. + + @retval the Hiihandle count. + +**/ +UINTN +GetHiiHandleCount ( + IN EFI_HII_HANDLE *HiiHandles + ) +{ + UINTN Index; + + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + } + + return Index; +} + +/** + Insert the new HiiHandle + FormsetGuid at the NewPair[InsertOffset]. + + @param HiiHandles The input HiiHandle array. + @param GuidLists The input form set guid lists. + @param ArrayCount The input array count, new array will be arraycount + 1 size. + @param Offset The current used HiiHandle's Offset. + @param FormSetGuid The new found formset guid. + +**/ +VOID +AdjustArrayData ( + IN OUT EFI_HII_HANDLE **HiiHandles, + IN OUT EFI_GUID ***GuidLists, + IN UINTN ArrayCount, + IN UINTN Offset, + IN EFI_GUID *FormSetGuid + ) +{ + EFI_HII_HANDLE *NewHiiHandles; + EFI_GUID **NewGuidLists; + + // + // +2 means include the new HiiHandle and the last empty NULL pointer. + // + NewHiiHandles = AllocateZeroPool ((ArrayCount + 2) * sizeof (EFI_HII_HANDLE)); + ASSERT (NewHiiHandles != NULL); + + CopyMem (NewHiiHandles, *HiiHandles, Offset * sizeof (EFI_HII_HANDLE)); + NewHiiHandles[Offset] = NewHiiHandles[Offset - 1]; + CopyMem (NewHiiHandles + Offset + 1, *HiiHandles + Offset, (ArrayCount - Offset) * sizeof (EFI_HII_HANDLE)); + + NewGuidLists = AllocateZeroPool ((ArrayCount + 2) * sizeof (EFI_GUID *)); + ASSERT (NewGuidLists != NULL); + + CopyMem (NewGuidLists, *GuidLists, Offset * sizeof (EFI_GUID *)); + NewGuidLists[Offset] = FormSetGuid; + + FreePool (*HiiHandles); + *HiiHandles = NewHiiHandles; + FreePool (*GuidLists); + *GuidLists = NewGuidLists; +} + +/** + Call the browser and display the device manager to allow user + to configure the platform. + + This function create the dynamic content for device manager. It includes + section header for all class of devices, one-of opcode to set VBIOS. + + @retval EFI_SUCCESS Operation is successful. + @return Other values if failed to clean up the dynamic content from HII + database. + +**/ +EFI_STATUS +CallDeviceManager ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_STRING String; + EFI_STRING_ID Token; + EFI_STRING_ID TokenHelp; + EFI_HII_HANDLE *HiiHandles; + EFI_HII_HANDLE HiiHandle; + EFI_STRING_ID FormSetTitle; + EFI_STRING_ID FormSetHelp; + EFI_BROWSER_ACTION_REQUEST ActionRequest; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + UINTN NumHandles; + EFI_HANDLE *DriverHealthHandles; + BOOLEAN AddNetworkMenu; + UINTN AddItemCount; + UINTN NewStringLen; + EFI_STRING NewStringTitle; + EFI_GUID **GuidLists; + UINTN HandleNum; + UINTN SkipCount; + EFI_GUID *FormSetGuid; + + GuidLists = NULL; + HiiHandles = NULL; + Status = EFI_SUCCESS; + gCallbackKey = 0; + NumHandles = 0; + DriverHealthHandles = NULL; + AddNetworkMenu = FALSE; + AddItemCount = 0; + SkipCount = 0; + FormSetGuid = NULL; + + // + // Connect all prior to entering the platform setup menu. + // + if (!gConnectAllHappened) { + BdsLibConnectAllDriversToAllControllers (); + gConnectAllHappened = TRUE; + } + + HiiHandle = gDeviceManagerPrivate.HiiHandle; + if (HiiHandle == NULL) { + // + // Publish our HII data. + // + HiiHandle = HiiAddPackages ( + &gDeviceManagerFormSetGuid, + gDeviceManagerPrivate.DriverHandle, + DeviceManagerVfrBin, + BdsDxeStrings, + NULL + ); + if (HiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + gDeviceManagerPrivate.HiiHandle = HiiHandle; + } + + // + // If need show the Network device list form, clear the old save list first. + // + if ((mNextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) && (mMacDeviceList.CurListLen > 0)) { + mMacDeviceList.CurListLen = 0; + } + + // + // Update the network device form titile. + // + if (mNextShowFormId == NETWORK_DEVICE_FORM_ID) { + String = HiiGetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NULL); + NewStringLen = StrLen(mSelectedMacAddrString) * 2; + NewStringLen += (StrLen(String) + 2) * 2; + NewStringTitle = AllocatePool (NewStringLen); + UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString); + HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL); + FreePool (String); + FreePool (NewStringTitle); + } + + // + // Allocate space for creation of UpdateData Buffer + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + // + // According to the next show Form id(mNextShowFormId) to decide which form need to update. + // + StartLabel->Number = (UINT16) (LABEL_FORM_ID_OFFSET + mNextShowFormId); + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Get all the Hii handles + // + HiiHandles = HiiGetHiiHandles (NULL); + ASSERT (HiiHandles != NULL); + + HandleNum = GetHiiHandleCount (HiiHandles); + GuidLists = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_GUID *)); + ASSERT (GuidLists != NULL); + + // + // Search for formset of each class type + // + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + // + // The QuestionId in the form which will call the driver form has this asssumption. + // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET; + // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET. + // + ASSERT(Index < MAX_KEY_SECTION_LEN); + + if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiHiiPlatformSetupFormsetGuid, SkipCount, &FormSetTitle, &FormSetHelp, &FormSetGuid)) { + SkipCount = 0; + continue; + } + + // + // One HiiHandle has more than one formset can be shown, + // Insert a new pair of HiiHandle + Guid to the HiiHandles and GuidLists list. + // + if (SkipCount > 0) { + AdjustArrayData (&HiiHandles, &GuidLists, HandleNum, Index + 1, FormSetGuid); + HandleNum ++; + Index ++; + } + + String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL); + if (String == NULL) { + String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); + ASSERT (String != NULL); + } + Token = HiiSetString (HiiHandle, 0, String, NULL); + FreePool (String); + + String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL); + if (String == NULL) { + String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); + ASSERT (String != NULL); + } + TokenHelp = HiiSetString (HiiHandle, 0, String, NULL); + FreePool (String); + + // + // Network device process + // + if (IsNeedAddNetworkMenu (HiiHandles[Index], &AddItemCount)) { + if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) { + // + // Only show one menu item "Network Config" in the device manger form. + // + if (!AddNetworkMenu) { + AddNetworkMenu = TRUE; + HiiCreateGotoOpCode ( + StartOpCodeHandle, + INVALID_FORM_ID, + STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE), + STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP), + EFI_IFR_FLAG_CALLBACK, + (EFI_QUESTION_ID) QUESTION_NETWORK_DEVICE_ID + ); + } + } else if (mNextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) { + // + // In network device list form, same mac address device only show one menu. + // + while (AddItemCount > 0) { + HiiCreateGotoOpCode ( + StartOpCodeHandle, + INVALID_FORM_ID, + mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].PromptId, + STRING_TOKEN (STR_NETWORK_DEVICE_HELP), + EFI_IFR_FLAG_CALLBACK, + mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].QuestionId + ); + AddItemCount -= 1; + } + } else if (mNextShowFormId == NETWORK_DEVICE_FORM_ID) { + // + // In network device form, only the selected mac address device need to be show. + // + HiiCreateGotoOpCode ( + StartOpCodeHandle, + INVALID_FORM_ID, + Token, + TokenHelp, + EFI_IFR_FLAG_CALLBACK, + (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET) + ); + } + } else { + // + // + // Not network device process, only need to show at device manger form. + // + if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) { + HiiCreateGotoOpCode ( + StartOpCodeHandle, + INVALID_FORM_ID, + Token, + TokenHelp, + EFI_IFR_FLAG_CALLBACK, + (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET) + ); + } + } + + // + // Try to find more formset in this HiiHandle. + // + SkipCount++; + Index--; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDriverHealthProtocolGuid, + NULL, + &NumHandles, + &DriverHealthHandles + ); + + // + // If there are no drivers installed driver health protocol, do not create driver health entry in UI + // + if (NumHandles != 0) { + // + // If driver health protocol is installed, create Driver Health subtitle and entry + // + HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE), 0, 0, 0); + HiiCreateGotoOpCode ( + StartOpCodeHandle, + DRIVER_HEALTH_FORM_ID, + STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY), // Prompt text + STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP), // Help text + EFI_IFR_FLAG_CALLBACK, + DEVICE_MANAGER_KEY_DRIVER_HEALTH // Question ID + ); + + // + // Check All Driver health status + // + if (!PlaformHealthStatusCheck ()) { + // + // At least one driver in the platform are not in healthy status + // + HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH)), NULL); + } else { + // + // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry. + // + HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL); + } + } + + HiiUpdateForm ( + HiiHandle, + &gDeviceManagerFormSetGuid, + mNextShowFormId, + StartOpCodeHandle, + EndOpCodeHandle + ); + + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &HiiHandle, + 1, + &gDeviceManagerFormSetGuid, + mNextShowFormId, + NULL, + &ActionRequest + ); + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + // + // We will have returned from processing a callback, selected + // a target to display + // + if ((gCallbackKey >= DEVICE_KEY_OFFSET)) { + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET], + 1, + GuidLists[gCallbackKey - DEVICE_KEY_OFFSET], + 0, + NULL, + &ActionRequest + ); + + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + // + // Force return to Device Manager + // + gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; + goto Done; + } + + // + // Driver Health item chose. + // + if (gCallbackKey == DEVICE_MANAGER_KEY_DRIVER_HEALTH) { + CallDriverHealth (); + // + // Force return to Device Manager + // + gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; + goto Done; + } + + // + // Enter from device manager and into the network device list. + // + if (gCallbackKey == QUESTION_NETWORK_DEVICE_ID) { + mNextShowFormId = NETWORK_DEVICE_LIST_FORM_ID; + gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; + goto Done; + } + + // + // In this case, go from the network device list to the specify device. + // + if ((gCallbackKey < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET ) && (gCallbackKey >= NETWORK_DEVICE_LIST_KEY_OFFSET)) { + mNextShowFormId = NETWORK_DEVICE_FORM_ID; + gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; + goto Done; + } + + // + // Select the ESC, the gCallbackKey == 0. + // + if(mNextShowFormId - 1 < DEVICE_MANAGER_FORM_ID) { + mNextShowFormId = DEVICE_MANAGER_FORM_ID; + } else { + mNextShowFormId = (UINT16) (mNextShowFormId - 1); + gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; + } + +Done: + // + // Remove our packagelist from HII database. + // + HiiRemovePackages (HiiHandle); + gDeviceManagerPrivate.HiiHandle = NULL; + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + FreePool (HiiHandles); + + for (Index = 0; Index < HandleNum; Index++) { + if (GuidLists[Index] != NULL) { + FreePool (GuidLists[Index]); + } + } + FreePool (GuidLists); + + return Status; +} + +/** + This function is invoked if user selected a interactive opcode from Driver Health's + Formset. The decision by user is saved to gCallbackKey for later processing. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +DriverHealthCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + gCallbackKey = QuestionId; + + // + // Request to exit SendForm(), so as to switch to selected form + // + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + + return EFI_SUCCESS; + } + + // + // All other action return unsupported. + // + return EFI_UNSUPPORTED; +} + +/** + Collect and display the platform's driver health relative information, allow user to do interactive + operation while the platform is unhealthy. + + This function display a form which divided into two parts. The one list all modules which has installed + driver health protocol. The list usually contain driver name, controller name, and it's health info. + While the driver name can't be retrieved, will use device path as backup. The other part of the form provide + a choice to the user to repair all platform. + +**/ +VOID +CallDriverHealth ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_BROWSER_ACTION_REQUEST ActionRequest; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *StartLabelRepair; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_IFR_GUID_LABEL *EndLabelRepair; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + VOID *StartOpCodeHandleRepair; + VOID *EndOpCodeHandleRepair; + UINTN Index; + EFI_STRING_ID Token; + EFI_STRING_ID TokenHelp; + EFI_STRING String; + EFI_STRING TmpString; + EFI_STRING DriverName; + EFI_STRING ControllerName; + LIST_ENTRY DriverHealthList; + DRIVER_HEALTH_INFO *DriverHealthInfo; + LIST_ENTRY *Link; + EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath; + BOOLEAN RebootRequired; + BOOLEAN IsControllerNameEmpty; + UINTN StringSize; + + Index = 0; + DriverHealthInfo = NULL; + DriverDevicePath = NULL; + IsControllerNameEmpty = FALSE; + InitializeListHead (&DriverHealthList); + + HiiHandle = gDeviceManagerPrivate.DriverHealthHiiHandle; + if (HiiHandle == NULL) { + // + // Publish Driver Health HII data. + // + HiiHandle = HiiAddPackages ( + &gDeviceManagerFormSetGuid, + gDeviceManagerPrivate.DriverHealthHandle, + DriverHealthVfrBin, + BdsDxeStrings, + NULL + ); + if (HiiHandle == NULL) { + return; + } + + gDeviceManagerPrivate.DriverHealthHiiHandle = HiiHandle; + } + + // + // Allocate space for creation of UpdateData Buffer + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + StartOpCodeHandleRepair = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandleRepair != NULL); + + EndOpCodeHandleRepair = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandleRepair != NULL); + + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_DRIVER_HEALTH; + + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + StartLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL; + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_DRIVER_HEALTH_END; + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + EndLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL_END; + + HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DH_STATUS_LIST), 0, 0, 1); + + Status = GetAllControllersHealthStatus (&DriverHealthList); + ASSERT (Status != EFI_OUT_OF_RESOURCES); + + Link = GetFirstNode (&DriverHealthList); + + while (!IsNull (&DriverHealthList, Link)) { + DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); + + Status = DriverHealthGetDriverName (DriverHealthInfo->DriverHandle, &DriverName); + if (EFI_ERROR (Status)) { + // + // Can not get the Driver name, so use the Device path + // + DriverDevicePath = DevicePathFromHandle (DriverHealthInfo->DriverHandle); + DriverName = DevicePathToStr (DriverDevicePath); + } + StringSize = StrSize (DriverName); + + Status = DriverHealthGetControllerName ( + DriverHealthInfo->DriverHandle, + DriverHealthInfo->ControllerHandle, + DriverHealthInfo->ChildHandle, + &ControllerName + ); + + if (!EFI_ERROR (Status)) { + IsControllerNameEmpty = FALSE; + StringSize += StrLen (L" ") * sizeof(CHAR16); + StringSize += StrLen (ControllerName) * sizeof(CHAR16); + } else { + IsControllerNameEmpty = TRUE; + } + + // + // Add the message of the Module itself provided after the string item. + // + if ((DriverHealthInfo->MessageList != NULL) && (DriverHealthInfo->MessageList->StringId != 0)) { + TmpString = HiiGetString ( + DriverHealthInfo->MessageList->HiiHandle, + DriverHealthInfo->MessageList->StringId, + NULL + ); + ASSERT (TmpString != NULL); + + StringSize += StrLen (L" ") * sizeof(CHAR16); + StringSize += StrLen (TmpString) * sizeof(CHAR16); + + String = (EFI_STRING) AllocateZeroPool (StringSize); + ASSERT (String != NULL); + + StrCpyS (String, StringSize / sizeof(CHAR16), DriverName); + if (!IsControllerNameEmpty) { + StrCatS (String, StringSize / sizeof(CHAR16), L" "); + StrCatS (String, StringSize / sizeof(CHAR16), ControllerName); + } + + StrCatS (String, StringSize / sizeof(CHAR16), L" "); + StrCatS (String, StringSize / sizeof(CHAR16), TmpString); + + } else { + // + // Update the string will be displayed base on the driver's health status + // + switch(DriverHealthInfo->HealthStatus) { + case EfiDriverHealthStatusRepairRequired: + TmpString = GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED)); + break; + case EfiDriverHealthStatusConfigurationRequired: + TmpString = GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED)); + break; + case EfiDriverHealthStatusFailed: + TmpString = GetStringById (STRING_TOKEN (STR_OPERATION_FAILED)); + break; + case EfiDriverHealthStatusReconnectRequired: + TmpString = GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED)); + break; + case EfiDriverHealthStatusRebootRequired: + TmpString = GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED)); + break; + default: + TmpString = GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY)); + break; + } + ASSERT (TmpString != NULL); + + StringSize += StrLen (TmpString) * sizeof(CHAR16); + + String = (EFI_STRING) AllocateZeroPool (StringSize); + ASSERT (String != NULL); + + StrCpyS (String, StringSize / sizeof (CHAR16), DriverName); + if (!IsControllerNameEmpty) { + StrCatS (String, StringSize / sizeof (CHAR16), L" "); + StrCatS (String, StringSize / sizeof (CHAR16), ControllerName); + } + + StrCatS (String, StringSize / sizeof (CHAR16), TmpString); + } + + FreePool (TmpString); + + Token = HiiSetString (HiiHandle, 0, String, NULL); + FreePool (String); + + TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP)), NULL); + + HiiCreateActionOpCode ( + StartOpCodeHandle, + (EFI_QUESTION_ID) (Index + DRIVER_HEALTH_KEY_OFFSET), + Token, + TokenHelp, + EFI_IFR_FLAG_CALLBACK, + 0 + ); + Index++; + Link = GetNextNode (&DriverHealthList, Link); + } + + // + // Add End Opcode for Subtitle + // + HiiCreateEndOpCode (StartOpCodeHandle); + + HiiCreateSubTitleOpCode (StartOpCodeHandleRepair, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL), 0, 0, 1); + TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP)), NULL); + + if (PlaformHealthStatusCheck ()) { + // + // No action need to do for the platform + // + Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL); + HiiCreateActionOpCode ( + StartOpCodeHandleRepair, + 0, + Token, + TokenHelp, + EFI_IFR_FLAG_READ_ONLY, + 0 + ); + } else { + // + // Create ActionOpCode only while the platform need to do health related operation. + // + Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE)), NULL); + HiiCreateActionOpCode ( + StartOpCodeHandleRepair, + (EFI_QUESTION_ID) DRIVER_HEALTH_REPAIR_ALL_KEY, + Token, + TokenHelp, + EFI_IFR_FLAG_CALLBACK, + 0 + ); + } + + HiiCreateEndOpCode (StartOpCodeHandleRepair); + + Status = HiiUpdateForm ( + HiiHandle, + &gDriverHealthFormSetGuid, + DRIVER_HEALTH_FORM_ID, + StartOpCodeHandle, + EndOpCodeHandle + ); + ASSERT (Status != EFI_NOT_FOUND); + ASSERT (Status != EFI_BUFFER_TOO_SMALL); + + Status = HiiUpdateForm ( + HiiHandle, + &gDriverHealthFormSetGuid, + DRIVER_HEALTH_FORM_ID, + StartOpCodeHandleRepair, + EndOpCodeHandleRepair + ); + ASSERT (Status != EFI_NOT_FOUND); + ASSERT (Status != EFI_BUFFER_TOO_SMALL); + + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &HiiHandle, + 1, + &gDriverHealthFormSetGuid, + DRIVER_HEALTH_FORM_ID, + NULL, + &ActionRequest + ); + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + // + // We will have returned from processing a callback - user either hit ESC to exit, or selected + // a target to display. + // Process the diver health status states here. + // + if (gCallbackKey >= DRIVER_HEALTH_KEY_OFFSET && gCallbackKey != DRIVER_HEALTH_REPAIR_ALL_KEY) { + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + + Link = GetFirstNode (&DriverHealthList); + Index = 0; + + while (!IsNull (&DriverHealthList, Link)) { + // + // Got the item relative node in the List + // + if (Index == (gCallbackKey - DRIVER_HEALTH_KEY_OFFSET)) { + DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); + // + // Process the driver's healthy status for the specify module + // + RebootRequired = FALSE; + ProcessSingleControllerHealth ( + DriverHealthInfo->DriverHealth, + DriverHealthInfo->ControllerHandle, + DriverHealthInfo->ChildHandle, + DriverHealthInfo->HealthStatus, + &(DriverHealthInfo->MessageList), + DriverHealthInfo->HiiHandle, + &RebootRequired + ); + if (RebootRequired) { + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + break; + } + Index++; + Link = GetNextNode (&DriverHealthList, Link); + } + + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + // + // Force return to the form of Driver Health in Device Manager + // + gCallbackKey = DRIVER_HEALTH_RETURN_KEY; + } + + // + // Repair the whole platform + // + if (gCallbackKey == DRIVER_HEALTH_REPAIR_ALL_KEY) { + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + + PlatformRepairAll (&DriverHealthList); + + gCallbackKey = DRIVER_HEALTH_RETURN_KEY; + } + + // + // Remove driver health packagelist from HII database. + // + HiiRemovePackages (HiiHandle); + gDeviceManagerPrivate.DriverHealthHiiHandle = NULL; + + // + // Free driver health info list + // + while (!IsListEmpty (&DriverHealthList)) { + + Link = GetFirstNode(&DriverHealthList); + DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); + RemoveEntryList (Link); + + if (DriverHealthInfo->MessageList != NULL) { + FreePool(DriverHealthInfo->MessageList); + FreePool (DriverHealthInfo); + } + } + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + HiiFreeOpCodeHandle (StartOpCodeHandleRepair); + HiiFreeOpCodeHandle (EndOpCodeHandleRepair); + + if (gCallbackKey == DRIVER_HEALTH_RETURN_KEY) { + // + // Force return to Driver Health Form + // + gCallbackKey = DEVICE_MANAGER_KEY_DRIVER_HEALTH; + CallDriverHealth (); + } +} + + +/** + Check the Driver Health status of a single controller and try to process it if not healthy. + + This function called by CheckAllControllersHealthStatus () function in order to process a specify + contoller's health state. + + @param DriverHealthList A Pointer to the list contain all of the platform driver health information. + @param DriverHandle The handle of driver. + @param ControllerHandle The class guid specifies which form set will be displayed. + @param ChildHandle The handle of the child controller to retrieve the health + status on. This is an optional parameter that may be NULL. + @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. + @param HealthStatus The health status of the controller. + + @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL. + @retval HealthStatus The Health status of specify controller. + @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. + @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. + @retval EFI_SUCCESS The Health related operation has been taken successfully. + +**/ +EFI_STATUS +EFIAPI +GetSingleControllerHealthStatus ( + IN OUT LIST_ENTRY *DriverHealthList, + IN EFI_HANDLE DriverHandle, + IN EFI_HANDLE ControllerHandle, OPTIONAL + IN EFI_HANDLE ChildHandle, OPTIONAL + IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, + IN EFI_DRIVER_HEALTH_STATUS *HealthStatus + ) +{ + EFI_STATUS Status; + EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList; + EFI_HII_HANDLE FormHiiHandle; + DRIVER_HEALTH_INFO *DriverHealthInfo; + + if (HealthStatus == NULL) { + // + // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER + // + return EFI_INVALID_PARAMETER; + } + + // + // Assume the HealthStatus is healthy + // + *HealthStatus = EfiDriverHealthStatusHealthy; + + if (DriverHealth == NULL) { + // + // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER + // + return EFI_INVALID_PARAMETER; + } + + if (ControllerHandle == NULL) { + // + // If ControllerHandle is NULL, the return the cumulative health status of the driver + // + Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, HealthStatus, NULL, NULL); + if (*HealthStatus == EfiDriverHealthStatusHealthy) { + // + // Add the driver health related information into the list + // + DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO)); + if (DriverHealthInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE; + DriverHealthInfo->DriverHandle = DriverHandle; + DriverHealthInfo->ControllerHandle = NULL; + DriverHealthInfo->ChildHandle = NULL; + DriverHealthInfo->HiiHandle = NULL; + DriverHealthInfo->DriverHealth = DriverHealth; + DriverHealthInfo->MessageList = NULL; + DriverHealthInfo->HealthStatus = *HealthStatus; + + InsertTailList (DriverHealthList, &DriverHealthInfo->Link); + } + return Status; + } + + MessageList = NULL; + FormHiiHandle = NULL; + + // + // Collect the health status with the optional HII message list + // + Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, HealthStatus, &MessageList, &FormHiiHandle); + + if (EFI_ERROR (Status)) { + // + // If the health status could not be retrieved, then return immediately + // + return Status; + } + + // + // Add the driver health related information into the list + // + DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO)); + if (DriverHealthInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE; + DriverHealthInfo->DriverHandle = DriverHandle; + DriverHealthInfo->ControllerHandle = ControllerHandle; + DriverHealthInfo->ChildHandle = ChildHandle; + DriverHealthInfo->HiiHandle = FormHiiHandle; + DriverHealthInfo->DriverHealth = DriverHealth; + DriverHealthInfo->MessageList = MessageList; + DriverHealthInfo->HealthStatus = *HealthStatus; + + InsertTailList (DriverHealthList, &DriverHealthInfo->Link); + + return EFI_SUCCESS; +} + +/** + Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database, + and queries each EFI Driver Health Protocol to determine if one or more of the controllers + managed by each EFI Driver Health Protocol instance are not healthy. + + @param DriverHealthList A Pointer to the list contain all of the platform driver health + information. + + @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. + @retval EFI_SUCCESS All the controllers in the platform are healthy. + @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. + +**/ +EFI_STATUS +GetAllControllersHealthStatus ( + IN OUT LIST_ENTRY *DriverHealthList + ) +{ + EFI_STATUS Status; + UINTN NumHandles; + EFI_HANDLE *DriverHealthHandles; + EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth; + EFI_DRIVER_HEALTH_STATUS HealthStatus; + UINTN DriverHealthIndex; + EFI_HANDLE *Handles; + UINTN HandleCount; + UINTN ControllerIndex; + UINTN ChildIndex; + + // + // Initialize local variables + // + Handles = NULL; + DriverHealthHandles = NULL; + NumHandles = 0; + HandleCount = 0; + + HealthStatus = EfiDriverHealthStatusHealthy; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDriverHealthProtocolGuid, + NULL, + &NumHandles, + &DriverHealthHandles + ); + + if (Status == EFI_NOT_FOUND || NumHandles == 0) { + // + // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND + // + return EFI_NOT_FOUND; + } + + if (EFI_ERROR (Status) || DriverHealthHandles == NULL) { + // + // If the list of Driver Health Protocol handles can not be retrieved, then + // return EFI_OUT_OF_RESOURCES + // + return EFI_OUT_OF_RESOURCES; + } + + // + // Check the health status of all controllers in the platform + // Start by looping through all the Driver Health Protocol handles in the handle database + // + for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) { + // + // Skip NULL Driver Health Protocol handles + // + if (DriverHealthHandles[DriverHealthIndex] == NULL) { + continue; + } + + // + // Retrieve the Driver Health Protocol from DriverHandle + // + Status = gBS->HandleProtocol ( + DriverHealthHandles[DriverHealthIndex], + &gEfiDriverHealthProtocolGuid, + (VOID **)&DriverHealth + ); + if (EFI_ERROR (Status)) { + // + // If the Driver Health Protocol can not be retrieved, then skip to the next + // Driver Health Protocol handle + // + continue; + } + + // + // Check the health of all the controllers managed by a Driver Health Protocol handle + // + Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], NULL, NULL, DriverHealth, &HealthStatus); + + // + // If Status is an error code, then the health information could not be retrieved, so assume healthy + // and skip to the next Driver Health Protocol handle + // + if (EFI_ERROR (Status)) { + continue; + } + + // + // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next + // Driver Health Protocol handle + // + if (HealthStatus == EfiDriverHealthStatusHealthy) { + continue; + } + + // + // See if the list of all handles in the handle database has been retrieved + // + // + if (Handles == NULL) { + // + // Retrieve the list of all handles from the handle database + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &Handles + ); + if (EFI_ERROR (Status) || Handles == NULL) { + // + // If all the handles in the handle database can not be retrieved, then + // return EFI_OUT_OF_RESOURCES + // + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + } + // + // Loop through all the controller handles in the handle database + // + for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) { + // + // Skip NULL controller handles + // + if (Handles[ControllerIndex] == NULL) { + continue; + } + + Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL, DriverHealth, &HealthStatus); + if (EFI_ERROR (Status)) { + // + // If Status is an error code, then the health information could not be retrieved, so assume healthy + // + HealthStatus = EfiDriverHealthStatusHealthy; + } + + // + // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers + // + if (EFI_ERROR (Status)) { + continue; + } + + // + // Loop through all the child handles in the handle database + // + for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) { + // + // Skip NULL child handles + // + if (Handles[ChildIndex] == NULL) { + continue; + } + + Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex], DriverHealth, &HealthStatus); + if (EFI_ERROR (Status)) { + // + // If Status is an error code, then the health information could not be retrieved, so assume healthy + // + HealthStatus = EfiDriverHealthStatusHealthy; + } + + // + // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child + // + if (EFI_ERROR (Status)) { + continue; + } + } + } + } + + Status = EFI_SUCCESS; + +Done: + if (Handles != NULL) { + gBS->FreePool (Handles); + } + if (DriverHealthHandles != NULL) { + gBS->FreePool (DriverHealthHandles); + } + + return Status; +} + + +/** + Check the healthy status of the platform, this function will return immediately while found one driver + in the platform are not healthy. + + @retval FALSE at least one driver in the platform are not healthy. + @retval TRUE No controller install Driver Health Protocol, + or all controllers in the platform are in healthy status. +**/ +BOOLEAN +PlaformHealthStatusCheck ( + VOID + ) +{ + EFI_DRIVER_HEALTH_STATUS HealthStatus; + EFI_STATUS Status; + UINTN Index; + UINTN NoHandles; + EFI_HANDLE *DriverHealthHandles; + EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth; + BOOLEAN AllHealthy; + + // + // Initialize local variables + // + DriverHealthHandles = NULL; + DriverHealth = NULL; + + HealthStatus = EfiDriverHealthStatusHealthy; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDriverHealthProtocolGuid, + NULL, + &NoHandles, + &DriverHealthHandles + ); + // + // There are no handles match the search for Driver Health Protocol has been installed. + // + if (Status == EFI_NOT_FOUND) { + return TRUE; + } + // + // Assume all modules are healthy. + // + AllHealthy = TRUE; + + // + // Found one or more Handles. + // + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NoHandles; Index++) { + Status = gBS->HandleProtocol ( + DriverHealthHandles[Index], + &gEfiDriverHealthProtocolGuid, + (VOID **) &DriverHealth + ); + if (!EFI_ERROR (Status)) { + Status = DriverHealth->GetHealthStatus ( + DriverHealth, + NULL, + NULL, + &HealthStatus, + NULL, + NULL + ); + } + // + // Get the healthy status of the module + // + if (!EFI_ERROR (Status)) { + if (HealthStatus != EfiDriverHealthStatusHealthy) { + // + // Return immediately one driver's status not in healthy. + // + return FALSE; + } + } + } + } + return AllHealthy; +} + +/** + Processes a single controller using the EFI Driver Health Protocol associated with + that controller. This algorithm continues to query the GetHealthStatus() service until + one of the legal terminal states of the EFI Driver Health Protocol is reached. This may + require the processing of HII Messages, HII Form, and invocation of repair operations. + + @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. + @param ControllerHandle The class guid specifies which form set will be displayed. + @param ChildHandle The handle of the child controller to retrieve the health + status on. This is an optional parameter that may be NULL. + @param HealthStatus The health status of the controller. + @param MessageList An array of warning or error messages associated + with the controller specified by ControllerHandle and + ChildHandle. This is an optional parameter that may be NULL. + @param FormHiiHandle The HII handle for an HII form associated with the + controller specified by ControllerHandle and ChildHandle. + @param RebootRequired Indicate whether a reboot is required to repair the controller. +**/ +VOID +ProcessSingleControllerHealth ( + IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, + IN EFI_HANDLE ControllerHandle, OPTIONAL + IN EFI_HANDLE ChildHandle, OPTIONAL + IN EFI_DRIVER_HEALTH_STATUS HealthStatus, + IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL + IN EFI_HII_HANDLE FormHiiHandle, + IN OUT BOOLEAN *RebootRequired + ) +{ + EFI_STATUS Status; + EFI_DRIVER_HEALTH_STATUS LocalHealthStatus; + + LocalHealthStatus = HealthStatus; + // + // If the module need to be repaired or reconfiguration, will process it until + // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair + // will be in (Health, Failed, Configuration Required). + // + while(LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired || + LocalHealthStatus == EfiDriverHealthStatusRepairRequired) { + + if (LocalHealthStatus == EfiDriverHealthStatusRepairRequired) { + Status = DriverHealth->Repair ( + DriverHealth, + ControllerHandle, + ChildHandle, + RepairNotify + ); + } + // + // Via a form of the driver need to do configuration provided to process of status in + // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in + // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required). + // + if (LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired) { + if (FormHiiHandle != NULL) { + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &FormHiiHandle, + 1, + &gEfiHiiDriverHealthFormsetGuid, + 0, + NULL, + NULL + ); + ASSERT( !EFI_ERROR (Status)); + } else { + // + // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop + // + break; + } + } + + Status = DriverHealth->GetHealthStatus ( + DriverHealth, + ControllerHandle, + ChildHandle, + &LocalHealthStatus, + NULL, + &FormHiiHandle + ); + ASSERT_EFI_ERROR (Status); + + if (*MessageList != NULL) { + ProcessMessages (*MessageList); + } + } + + // + // Health status in {Healthy, Failed} may also have Messages need to process + // + if (LocalHealthStatus == EfiDriverHealthStatusHealthy || LocalHealthStatus == EfiDriverHealthStatusFailed) { + if (*MessageList != NULL) { + ProcessMessages (*MessageList); + } + } + // + // Check for RebootRequired or ReconnectRequired + // + if (LocalHealthStatus == EfiDriverHealthStatusRebootRequired) { + *RebootRequired = TRUE; + } + + // + // Do reconnect if need. + // + if (LocalHealthStatus == EfiDriverHealthStatusReconnectRequired) { + Status = gBS->DisconnectController (ControllerHandle, NULL, NULL); + if (EFI_ERROR (Status)) { + // + // Disconnect failed. Need to promote reconnect to a reboot. + // + *RebootRequired = TRUE; + } else { + gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE); + } + } +} + + +/** + Reports the progress of a repair operation. + + @param[in] Value A value between 0 and Limit that identifies the current + progress of the repair operation. + + @param[in] Limit The maximum value of Value for the current repair operation. + For example, a driver that wants to specify progress in + percent would use a Limit value of 100. + + @retval EFI_SUCCESS The progress of a repair operation is reported successfully. + +**/ +EFI_STATUS +EFIAPI +RepairNotify ( + IN UINTN Value, + IN UINTN Limit + ) +{ + UINTN Percent; + + if (Limit == 0) { + Print(L"Repair Progress Undefined\n\r"); + } else { + Percent = Value * 100 / Limit; + Print(L"Repair Progress = %3d%%\n\r", Percent); + } + return EFI_SUCCESS; +} + +/** + Processes a set of messages returned by the GetHealthStatus () + service of the EFI Driver Health Protocol + + @param MessageList The MessageList point to messages need to processed. + +**/ +VOID +ProcessMessages ( + IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList + ) +{ + UINTN MessageIndex; + EFI_STRING MessageString; + + for (MessageIndex = 0; + MessageList[MessageIndex].HiiHandle != NULL; + MessageIndex++) { + + MessageString = HiiGetString ( + MessageList[MessageIndex].HiiHandle, + MessageList[MessageIndex].StringId, + NULL + ); + if (MessageString != NULL) { + // + // User can customize the output. Just simply print out the MessageString like below. + // Also can use the HiiHandle to display message on the front page. + // + // Print(L"%s\n",MessageString); + // gBS->Stall (100000); + } + } + +} + +/** + Repair the whole platform. + + This function is the main entry for user choose "Repair All" in the front page. + It will try to do recovery job till all the driver health protocol installed modules + reach a terminal state. + + @param DriverHealthList A Pointer to the list contain all of the platform driver health + information. + +**/ +VOID +PlatformRepairAll ( + IN LIST_ENTRY *DriverHealthList + ) +{ + DRIVER_HEALTH_INFO *DriverHealthInfo; + LIST_ENTRY *Link; + BOOLEAN RebootRequired; + + ASSERT (DriverHealthList != NULL); + + RebootRequired = FALSE; + + for ( Link = GetFirstNode (DriverHealthList) + ; !IsNull (DriverHealthList, Link) + ; Link = GetNextNode (DriverHealthList, Link) + ) { + DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); + // + // Do driver health status operation by each link node + // + ASSERT (DriverHealthInfo != NULL); + + ProcessSingleControllerHealth ( + DriverHealthInfo->DriverHealth, + DriverHealthInfo->ControllerHandle, + DriverHealthInfo->ChildHandle, + DriverHealthInfo->HealthStatus, + &(DriverHealthInfo->MessageList), + DriverHealthInfo->HiiHandle, + &RebootRequired + ); + } + + if (RebootRequired) { + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } +} + +/** + + Select the best matching language according to front page policy for best user experience. + + This function supports both ISO 639-2 and RFC 4646 language codes, but language + code types may not be mixed in a single call to this function. + + @param SupportedLanguages A pointer to a Null-terminated ASCII string that + contains a set of language codes in the format + specified by Iso639Language. + @param Iso639Language If TRUE, then all language codes are assumed to be + in ISO 639-2 format. If FALSE, then all language + codes are assumed to be in RFC 4646 language format. + + @retval NULL The best matching language could not be found in SupportedLanguages. + @retval NULL There are not enough resources available to return the best matching + language. + @retval Other A pointer to a Null-terminated ASCII string that is the best matching + language in SupportedLanguages. +**/ +CHAR8 * +DriverHealthSelectBestLanguage ( + IN CHAR8 *SupportedLanguages, + IN BOOLEAN Iso639Language + ) +{ + CHAR8 *LanguageVariable; + CHAR8 *BestLanguage; + + GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID**)&LanguageVariable, NULL); + + BestLanguage = GetBestLanguage( + SupportedLanguages, + Iso639Language, + (LanguageVariable != NULL) ? LanguageVariable : "", + Iso639Language ? "eng" : "en-US", + NULL + ); + if (LanguageVariable != NULL) { + FreePool (LanguageVariable); + } + + return BestLanguage; +} + + + +/** + + This is an internal worker function to get the Component Name (2) protocol interface + and the language it supports. + + @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @param ComponentName A pointer to the Component Name (2) protocol interface. + @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the + located Component Name (2) instance. + + @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find + the best matching language it support. + @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol. + @retval Other Some error occurs when locating Component Name (2) protocol instance or finding + the supported language. + +**/ +EFI_STATUS +GetComponentNameWorker ( + IN EFI_GUID *ProtocolGuid, + IN EFI_HANDLE DriverBindingHandle, + OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName, + OUT CHAR8 **SupportedLanguage + ) +{ + EFI_STATUS Status; + + // + // Locate Component Name (2) protocol on the driver binging handle. + // + Status = gBS->OpenProtocol ( + DriverBindingHandle, + ProtocolGuid, + (VOID **) ComponentName, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Apply shell policy to select the best language. + // + *SupportedLanguage = DriverHealthSelectBestLanguage ( + (*ComponentName)->SupportedLanguages, + (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid) + ); + if (*SupportedLanguage == NULL) { + Status = EFI_UNSUPPORTED; + } + + return Status; +} + +/** + + This is an internal worker function to get driver name from Component Name (2) protocol interface. + + + @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @param DriverName A pointer to the Unicode string to return. This Unicode string is the name + of the driver specified by This. + + @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol + interface. + @retval Other The driver name cannot be retrieved from Component Name (2) protocol + interface. + +**/ +EFI_STATUS +GetDriverNameWorker ( + IN EFI_GUID *ProtocolGuid, + IN EFI_HANDLE DriverBindingHandle, + OUT CHAR16 **DriverName + ) +{ + EFI_STATUS Status; + CHAR8 *BestLanguage; + EFI_COMPONENT_NAME_PROTOCOL *ComponentName; + + // + // Retrieve Component Name (2) protocol instance on the driver binding handle and + // find the best language this instance supports. + // + Status = GetComponentNameWorker ( + ProtocolGuid, + DriverBindingHandle, + &ComponentName, + &BestLanguage + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the driver name from Component Name (2) protocol instance on the driver binging handle. + // + Status = ComponentName->GetDriverName ( + ComponentName, + BestLanguage, + DriverName + ); + FreePool (BestLanguage); + + return Status; +} + +/** + + This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface + in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name. + If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward + compatibility support. + + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @param DriverName A pointer to the Unicode string to return. This Unicode string is the name + of the driver specified by This. + + @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol + interface. + @retval Other The driver name cannot be retrieved from Component Name (2) protocol + interface. + +**/ +EFI_STATUS +DriverHealthGetDriverName ( + IN EFI_HANDLE DriverBindingHandle, + OUT CHAR16 **DriverName + ) +{ + EFI_STATUS Status; + + // + // Get driver name from UEFI 2.0 Component Name 2 protocol interface. + // + Status = GetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, DriverName); + if (EFI_ERROR (Status)) { + // + // If it fails to get the driver name from Component Name protocol interface, we should fall back on + // EFI 1.1 Component Name protocol interface. + // + Status = GetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, DriverName); + } + + return Status; +} + + + +/** + This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface + in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. + If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward + compatibility support. + + @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @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 bus drivers that attempt to retrieve the name + of the bus controller. It will not be NULL for a bus driver that attempts + to retrieve the name of a child controller. + @param ControllerName A pointer to the Unicode string to return. This Unicode string + is the name of the controller specified by ControllerHandle and ChildHandle. + + @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol + interface. + @retval Other The controller name cannot be retrieved from Component Name (2) protocol. + +**/ +EFI_STATUS +GetControllerNameWorker ( + IN EFI_GUID *ProtocolGuid, + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + CHAR8 *BestLanguage; + EFI_COMPONENT_NAME_PROTOCOL *ComponentName; + + // + // Retrieve Component Name (2) protocol instance on the driver binding handle and + // find the best language this instance supports. + // + Status = GetComponentNameWorker ( + ProtocolGuid, + DriverBindingHandle, + &ComponentName, + &BestLanguage + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the controller name from Component Name (2) protocol instance on the driver binging handle. + // + Status = ComponentName->GetControllerName ( + ComponentName, + ControllerHandle, + ChildHandle, + BestLanguage, + ControllerName + ); + FreePool (BestLanguage); + + return Status; +} + +/** + + This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface + in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. + If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward + compatibility support. + + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @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 bus drivers that attempt to retrieve the name + of the bus controller. It will not be NULL for a bus driver that attempts + to retrieve the name of a child controller. + @param ControllerName A pointer to the Unicode string to return. This Unicode string + is the name of the controller specified by ControllerHandle and ChildHandle. + + @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol + interface. + @retval Other The controller name cannot be retrieved from Component Name (2) protocol. + +**/ +EFI_STATUS +DriverHealthGetControllerName ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + + // + // Get controller name from UEFI 2.0 Component Name 2 protocol interface. + // + Status = GetControllerNameWorker ( + &gEfiComponentName2ProtocolGuid, + DriverBindingHandle, + ControllerHandle, + ChildHandle, + ControllerName + ); + if (EFI_ERROR (Status)) { + // + // If it fails to get the controller name from Component Name protocol interface, we should fall back on + // EFI 1.1 Component Name protocol interface. + // + Status = GetControllerNameWorker ( + &gEfiComponentNameProtocolGuid, + DriverBindingHandle, + ControllerHandle, + ChildHandle, + ControllerName + ); + } + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h new file mode 100644 index 0000000000..95bde8de5a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h @@ -0,0 +1,523 @@ +/** @file + The platform device manager reference implement + +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 _DEVICE_MANAGER_H_ +#define _DEVICE_MANAGER_H_ + +#include "Bds.h" +#include "FrontPage.h" +#include "DeviceManagerVfr.h" +#include + +#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('D', 'M', 'C', 'B') +#define DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'D', 'H') + + +typedef struct { + UINTN Signature; + + /// + /// Device Manager HII relative handles + /// + EFI_HII_HANDLE HiiHandle; + + /// + /// Driver Health HII relative handles + /// + EFI_HII_HANDLE DriverHealthHiiHandle; + + EFI_HANDLE DriverHandle; + EFI_HANDLE DriverHealthHandle; + + /// + /// Device Manager Produced protocols + /// + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + + /// + /// Driver Health Produced protocols + /// + EFI_HII_CONFIG_ACCESS_PROTOCOL DriverHealthConfigAccess; + + /// + /// Configuration data + /// + UINT8 VideoBios; +} DEVICE_MANAGER_CALLBACK_DATA; + + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + /// + /// HII relative handles + /// + EFI_HII_HANDLE HiiHandle; + + /// + /// Driver relative handles + /// + EFI_HANDLE DriverHandle; + EFI_HANDLE ControllerHandle; + EFI_HANDLE ChildHandle; + + EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth; + /// + /// Driver health messages of the specify Driver + /// + EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList; + + /// + /// Driver Health status + /// + EFI_DRIVER_HEALTH_STATUS HealthStatus; +} DRIVER_HEALTH_INFO; + +typedef struct { + EFI_STRING_ID PromptId; + EFI_QUESTION_ID QuestionId; +}MENU_INFO_ITEM; + +typedef struct { + UINTN CurListLen; + UINTN MaxListLen; + MENU_INFO_ITEM *NodeList; +} MAC_ADDRESS_NODE_LIST; + +#define DEVICE_MANAGER_HEALTH_INFO_FROM_LINK(a) \ + CR (a, \ + DRIVER_HEALTH_INFO, \ + Link, \ + DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE \ + ) + +#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \ + CR (a, \ + DEVICE_MANAGER_CALLBACK_DATA, \ + ConfigAccess, \ + DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \ + ) +typedef struct { + EFI_STRING_ID StringId; + UINT16 Class; +} DEVICE_MANAGER_MENU_ITEM; + +/** + This function is invoked if user selected a interactive opcode from Device Manager's + Formset. The decision by user is saved to gCallbackKey for later processing. If + user set VBIOS, the new value is saved to EFI variable. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +DeviceManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + This function is invoked if user selected a interactive opcode from Driver Health's + Formset. The decision by user is saved to gCallbackKey for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +DriverHealthCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + + +/** + + This function registers HII packages to HII database. + + @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully. + @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered. + +**/ +EFI_STATUS +InitializeDeviceManager ( + VOID + ); + +/** + + Call the browser and display the device manager to allow user + to configure the platform. + + This function create the dynamic content for device manager. It includes + section header for all class of devices, one-of opcode to set VBIOS. + + @retval EFI_SUCCESS Operation is successful. + @retval Other values if failed to clean up the dynamic content from HII + database. + +**/ +EFI_STATUS +CallDeviceManager ( + VOID + ); + + +/** + Check the Driver Health status of a single controller and try to process it if not healthy. + + This function called by CheckAllControllersHealthStatus () function in order to process a specify + contoller's health state. + + @param DriverHealthList A Pointer to the list contain all of the platform driver health information. + @param DriverHandle The handle of driver. + @param ControllerHandle The class guid specifies which form set will be displayed. + @param ChildHandle The handle of the child controller to retrieve the health + status on. This is an optional parameter that may be NULL. + @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. + @param HealthStatus The health status of the controller. + + @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL. + @retval HealthStatus The Health status of specify controller. + @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. + @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. + @retval EFI_SUCCESS The Health related operation has been taken successfully. + +**/ +EFI_STATUS +EFIAPI +GetSingleControllerHealthStatus ( + IN OUT LIST_ENTRY *DriverHealthList, + IN EFI_HANDLE DriverHandle, + IN EFI_HANDLE ControllerHandle, OPTIONAL + IN EFI_HANDLE ChildHandle, OPTIONAL + IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, + IN EFI_DRIVER_HEALTH_STATUS *HealthStatus + ); + +/** + Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database, + and queries each EFI Driver Health Protocol to determine if one or more of the controllers + managed by each EFI Driver Health Protocol instance are not healthy. + + @param DriverHealthList A Pointer to the list contain all of the platform driver health + information. + + @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. + @retval EFI_SUCCESS All the controllers in the platform are healthy. + @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. + +**/ +EFI_STATUS +GetAllControllersHealthStatus ( + IN OUT LIST_ENTRY *DriverHealthList + ); + +/** + Check the healthy status of the platform, this function will return immediately while found one driver + in the platform are not healthy. + + @retval FALSE at least one driver in the platform are not healthy. + @retval TRUE No controller install Driver Health Protocol, + or all controllers in the platform are in healthy status. +**/ +BOOLEAN +PlaformHealthStatusCheck ( + VOID + ); + +/** + Repair the whole platform. + + This function is the main entry for user choose "Repair All" in the front page. + It will try to do recovery job till all the driver health protocol installed modules + reach a terminal state. + + @param DriverHealthList A Pointer to the list contain all of the platform driver health + information. + +**/ +VOID +PlatformRepairAll ( + IN LIST_ENTRY *DriverHealthList + ); + +/** + Processes a single controller using the EFI Driver Health Protocol associated with + that controller. This algorithm continues to query the GetHealthStatus() service until + one of the legal terminal states of the EFI Driver Health Protocol is reached. This may + require the processing of HII Messages, HII Form, and invocation of repair operations. + + @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. + @param ControllerHandle The class guid specifies which form set will be displayed. + @param ChildHandle The handle of the child controller to retrieve the health + status on. This is an optional parameter that may be NULL. + @param HealthStatus The health status of the controller. + @param MessageList An array of warning or error messages associated + with the controller specified by ControllerHandle and + ChildHandle. This is an optional parameter that may be NULL. + @param FormHiiHandle The HII handle for an HII form associated with the + controller specified by ControllerHandle and ChildHandle. + @param RebootRequired Indicate whether a reboot is required to repair the controller. +**/ +VOID +ProcessSingleControllerHealth ( + IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, + IN EFI_HANDLE ControllerHandle, OPTIONAL + IN EFI_HANDLE ChildHandle, OPTIONAL + IN EFI_DRIVER_HEALTH_STATUS HealthStatus, + IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL + IN EFI_HII_HANDLE FormHiiHandle, + IN OUT BOOLEAN *RebootRequired + ); + +/** + Reports the progress of a repair operation. + + @param[in] Value A value between 0 and Limit that identifies the current + progress of the repair operation. + + @param[in] Limit The maximum value of Value for the current repair operation. + For example, a driver that wants to specify progress in + percent would use a Limit value of 100. + + @retval EFI_SUCCESS The progress of a repair operation is reported successfully. + +**/ +EFI_STATUS +EFIAPI +RepairNotify ( + IN UINTN Value, + IN UINTN Limit + ); + +/** + Processes a set of messages returned by the GetHealthStatus () + service of the EFI Driver Health Protocol + + @param MessageList The MessageList point to messages need to processed. + +**/ +VOID +ProcessMessages ( + IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList + ); + + +/** + Collect and display the platform's driver health relative information, allow user to do interactive + operation while the platform is unhealthy. + + This function display a form which divided into two parts. The one list all modules which has installed + driver health protocol. The list usually contain driver name, controller name, and it's health info. + While the driver name can't be retrieved, will use device path as backup. The other part of the form provide + a choice to the user to repair all platform. + +**/ +VOID +CallDriverHealth ( + VOID + ); + +/** + + Select the best matching language according to front page policy for best user experience. + + This function supports both ISO 639-2 and RFC 4646 language codes, but language + code types may not be mixed in a single call to this function. + + @param SupportedLanguages A pointer to a Null-terminated ASCII string that + contains a set of language codes in the format + specified by Iso639Language. + @param Iso639Language If TRUE, then all language codes are assumed to be + in ISO 639-2 format. If FALSE, then all language + codes are assumed to be in RFC 4646 language format. + + @retval NULL The best matching language could not be found in SupportedLanguages. + @retval NULL There are not enough resources available to return the best matching + language. + @retval Other A pointer to a Null-terminated ASCII string that is the best matching + language in SupportedLanguages. +**/ +CHAR8 * +DriverHealthSelectBestLanguage ( + IN CHAR8 *SupportedLanguages, + IN BOOLEAN Iso639Language + ); + +/** + + This is an internal worker function to get the Component Name (2) protocol interface + and the language it supports. + + @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @param ComponentName A pointer to the Component Name (2) protocol interface. + @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the + located Component Name (2) instance. + + @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find + the best matching language it support. + @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol. + @retval Other Some error occurs when locating Component Name (2) protocol instance or finding + the supported language. + +**/ +EFI_STATUS +GetComponentNameWorker ( + IN EFI_GUID *ProtocolGuid, + IN EFI_HANDLE DriverBindingHandle, + OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName, + OUT CHAR8 **SupportedLanguage + ); + +/** + + This is an internal worker function to get driver name from Component Name (2) protocol interface. + + + @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @param DriverName A pointer to the Unicode string to return. This Unicode string is the name + of the driver specified by This. + + @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol + interface. + @retval Other The driver name cannot be retrieved from Component Name (2) protocol + interface. + +**/ +EFI_STATUS +GetDriverNameWorker ( + IN EFI_GUID *ProtocolGuid, + IN EFI_HANDLE DriverBindingHandle, + OUT CHAR16 **DriverName + ); + +/** + + This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface + in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name. + If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward + compatibility support. + + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @param DriverName A pointer to the Unicode string to return. This Unicode string is the name + of the driver specified by This. + + @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol + interface. + @retval Other The driver name cannot be retrieved from Component Name (2) protocol + interface. + +**/ +EFI_STATUS +DriverHealthGetDriverName ( + IN EFI_HANDLE DriverBindingHandle, + OUT CHAR16 **DriverName + ); + +/** + This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface + in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. + If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward + compatibility support. + + @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @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 bus drivers that attempt to retrieve the name + of the bus controller. It will not be NULL for a bus driver that attempts + to retrieve the name of a child controller. + @param ControllerName A pointer to the Unicode string to return. This Unicode string + is the name of the controller specified by ControllerHandle and ChildHandle. + + @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol + interface. + @retval Other The controller name cannot be retrieved from Component Name (2) protocol. + +**/ +EFI_STATUS +GetControllerNameWorker ( + IN EFI_GUID *ProtocolGuid, + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, + OUT CHAR16 **ControllerName + ); + +/** + This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface + in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. + If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward + compatibility support. + + @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. + @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 bus drivers that attempt to retrieve the name + of the bus controller. It will not be NULL for a bus driver that attempts + to retrieve the name of a child controller. + @param ControllerName A pointer to the Unicode string to return. This Unicode string + is the name of the controller specified by ControllerHandle and ChildHandle. + + @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol + interface. + @retval Other The controller name cannot be retrieved from Component Name (2) protocol. + +**/ +EFI_STATUS +DriverHealthGetControllerName ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, + OUT CHAR16 **ControllerName + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni new file mode 100644 index 0000000000..1553f10bf9 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr new file mode 100644 index 0000000000..0ad671bdca --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr @@ -0,0 +1,93 @@ +///** @file +// +// Device Manager formset. +// +// Copyright (c) 2004 - 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 "DeviceManagerVfr.h" + +#define EFI_DISK_DEVICE_CLASS 0x0001 +#define EFI_VIDEO_DEVICE_CLASS 0x0002 +#define EFI_NETWORK_DEVICE_CLASS 0x0004 +#define EFI_INPUT_DEVICE_CLASS 0x0008 +#define EFI_ON_BOARD_DEVICE_CLASS 0x0010 +#define EFI_OTHER_DEVICE_CLASS 0x0020 + +#define DEVICE_MANAGER_CLASS 0x0000 +#define FRONT_PAGE_SUBCLASS 0x0003 + +formset + guid = DEVICE_MANAGER_FORMSET_GUID, + title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE), + help = STRING_TOKEN(STR_EMPTY_STRING), + classguid = DEVICE_MANAGER_FORMSET_GUID, + + form formid = DEVICE_MANAGER_FORM_ID, + title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE); + + subtitle text = STRING_TOKEN(STR_DEVICES_LIST); + // + // This is where devices get added to the device manager hierarchy + // + label EFI_DISK_DEVICE_CLASS; +// label LABEL_END; // Since next opcode is a label, so this one could be omitted to save code size + + label EFI_VIDEO_DEVICE_CLASS; +// label LABEL_END; + + label EFI_NETWORK_DEVICE_CLASS; +// label LABEL_END; + + label EFI_INPUT_DEVICE_CLASS; +// label LABEL_END; + + label EFI_ON_BOARD_DEVICE_CLASS; +// label LABEL_END; + +// label EFI_OTHER_DEVICE_CLASS; + + label LABEL_DEVICES_LIST; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + label LABEL_VBIOS; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + + endform; + + form formid = NETWORK_DEVICE_LIST_FORM_ID, + title = STRING_TOKEN(STR_FORM_NETWORK_DEVICE_LIST_TITLE); + + subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE_LIST_STRING); + + label LABEL_NETWORK_DEVICE_LIST_ID; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = NETWORK_DEVICE_FORM_ID, + title = STRING_TOKEN(STR_FORM_NETWORK_DEVICE_TITLE); + + subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE_STRING); + + label LABEL_NETWORK_DEVICE_ID; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; +endformset; + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h new file mode 100644 index 0000000000..b6b086600f --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h @@ -0,0 +1,56 @@ +/** @file + The platform device manager reference implement + +Copyright (c) 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 _DEVICE_MANAGER_VFR_H_ +#define _DEVICE_MANAGER_VFR_H_ + +#include + +#define LABEL_DEVICES_LIST 0x1100 +#define LABEL_NETWORK_DEVICE_LIST_ID 0x1101 +#define LABEL_NETWORK_DEVICE_ID 0x1102 +#define LABEL_END 0xffff +#define LABEL_FORM_ID_OFFSET 0x0100 + +#define LABEL_DRIVER_HEALTH 0x2000 +#define LABEL_DRIVER_HEALTH_END 0x2001 + +#define LABEL_DRIVER_HEALTH_REAPIR_ALL 0x3000 +#define LABEL_DRIVER_HEALTH_REAPIR_ALL_END 0x3001 + +#define LABEL_VBIOS 0x0040 + +#define INVALID_FORM_ID 0x0FFF +#define DEVICE_MANAGER_FORM_ID 0x1000 +#define NETWORK_DEVICE_LIST_FORM_ID 0x1001 +#define NETWORK_DEVICE_FORM_ID 0x1002 +#define DRIVER_HEALTH_FORM_ID 0x1003 +#define DEVICE_KEY_OFFSET 0x4000 +#define NETWORK_DEVICE_LIST_KEY_OFFSET 0x2000 +#define DEVICE_MANAGER_KEY_VBIOS 0x3000 +#define MAX_KEY_SECTION_LEN 0x1000 + +#define DEVICE_MANAGER_KEY_DRIVER_HEALTH 0x1111 +#define DRIVER_HEALTH_KEY_OFFSET 0x2000 +#define DRIVER_HEALTH_REPAIR_ALL_KEY 0x3000 +#define DRIVER_HEALTH_RETURN_KEY 0x4000 + +#define QUESTION_NETWORK_DEVICE_ID 0x3FFF +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 DeviceManagerVfrBin[]; +extern UINT8 DriverHealthVfrBin[]; + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DriverHealthVfr.Vfr b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DriverHealthVfr.Vfr new file mode 100644 index 0000000000..cb1a8f887b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DriverHealthVfr.Vfr @@ -0,0 +1,38 @@ +///** @file +// +// Driver Health formset. +// +// Copyright (c) 2004 - 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 "DeviceManagerVfr.h" + +formset + guid = DRIVER_HEALTH_FORMSET_GUID, + title = STRING_TOKEN(STR_DH_BANNER), + help = STRING_TOKEN(STR_EMPTY_STRING), + classguid = DRIVER_HEALTH_FORMSET_GUID, + + form formid = DRIVER_HEALTH_FORM_ID, + title = STRING_TOKEN(STR_DH_BANNER); + + label LABEL_DRIVER_HEALTH; + label LABEL_DRIVER_HEALTH_END; + + subtitle text = STRING_TOKEN(STR_LAST_STRING); + label LABEL_DRIVER_HEALTH_REAPIR_ALL; + label LABEL_DRIVER_HEALTH_REAPIR_ALL_END; + + subtitle text = STRING_TOKEN(STR_LAST_STRING); + subtitle text = STRING_TOKEN(STR_HELP_FOOTER); + subtitle text = STRING_TOKEN(STR_LAST_STRING); + endform; +endformset; diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c new file mode 100644 index 0000000000..f04da16598 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c @@ -0,0 +1,1480 @@ +/** @file + FrontPage routines to handle the callbacks and browser calls + +Copyright (c) 2004 - 2016, Intel 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 "Bds.h" +#include "FrontPage.h" +#include "Language.h" +#include "Hotkey.h" + +BOOLEAN mModeInitialized = FALSE; + +BOOLEAN gConnectAllHappened = FALSE; +UINTN gCallbackKey; +CHAR8 *mLanguageString; + +// +// Boot video resolution and text mode. +// +UINT32 mBootHorizontalResolution = 0; +UINT32 mBootVerticalResolution = 0; +UINT32 mBootTextModeColumn = 0; +UINT32 mBootTextModeRow = 0; +// +// BIOS setup video resolution and text mode. +// +UINT32 mSetupTextModeColumn = 0; +UINT32 mSetupTextModeRow = 0; +UINT32 mSetupHorizontalResolution = 0; +UINT32 mSetupVerticalResolution = 0; + +EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2; + +FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = { + FRONT_PAGE_CALLBACK_DATA_SIGNATURE, + NULL, + NULL, + NULL, + { + FakeExtractConfig, + FakeRouteConfig, + FrontPageCallback + } +}; + +HII_VENDOR_DEVICE_PATH mFrontPageHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + FRONT_PAGE_FORMSET_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 illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + +/** + 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 +FakeRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Configuration; + if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName) + && !HiiIsConfigHdrMatch (Configuration, &gFileExploreFormSetGuid, mFileExplorerStorageName)) { + return EFI_NOT_FOUND; + } + + *Progress = Configuration + StrLen (Configuration); + return EFI_SUCCESS; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + +**/ +EFI_STATUS +EFIAPI +FrontPageCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + CHAR8 *LangCode; + CHAR8 *Lang; + UINTN Index; + + if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { + // + // All other action return unsupported. + // + return EFI_UNSUPPORTED; + } + + gCallbackKey = QuestionId; + + if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + switch (QuestionId) { + case FRONT_PAGE_KEY_CONTINUE: + // + // This is the continue - clear the screen and return an error to get out of FrontPage loop + // + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + break; + + case FRONT_PAGE_KEY_LANGUAGE: + // + // Allocate working buffer for RFC 4646 language in supported LanguageString. + // + Lang = AllocatePool (AsciiStrSize (mLanguageString)); + ASSERT (Lang != NULL); + + Index = 0; + LangCode = mLanguageString; + while (*LangCode != 0) { + GetNextLanguage (&LangCode, Lang); + + if (Index == Value->u8) { + break; + } + + Index++; + } + + if (Index == Value->u8) { + BdsDxeSetVariableAndReportStatusCodeOnError ( + L"PlatformLang", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + AsciiStrSize (Lang), + Lang + ); + } else { + ASSERT (FALSE); + } + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + + FreePool (Lang); + break; + + default: + break; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGING) { + if (Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // 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) + // + switch (QuestionId) { + case FRONT_PAGE_KEY_BOOT_MANAGER: + // + // Boot Manager + // + break; + + case FRONT_PAGE_KEY_DEVICE_MANAGER: + // + // Device Manager + // + break; + + case FRONT_PAGE_KEY_BOOT_MAINTAIN: + // + // Boot Maintenance Manager + // + break; + + default: + gCallbackKey = 0; + break; + } + } + + return EFI_SUCCESS; +} + +/** + Initialize HII information for the FrontPage + + + @param InitializeHiiData TRUE if HII elements need to be initialized. + + @retval EFI_SUCCESS The operation is successful. + @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed. + +**/ +EFI_STATUS +InitializeFrontPage ( + IN BOOLEAN InitializeHiiData + ) +{ + EFI_STATUS Status; + CHAR8 *LangCode; + CHAR8 *Lang; + UINTN LangSize; + CHAR8 *CurrentLang; + UINTN OptionCount; + CHAR16 *StringBuffer; + EFI_HII_HANDLE HiiHandle; + VOID *OptionsOpCodeHandle; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_HII_STRING_PROTOCOL *HiiString; + UINTN StringSize; + + Lang = NULL; + StringBuffer = NULL; + + if (InitializeHiiData) { + // + // Initialize the Device Manager + // + InitializeDeviceManager (); + + // + // Initialize the Device Manager + // + InitializeBootManager (); + + gCallbackKey = 0; + + // + // Locate Hii relative protocols + // + Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gFrontPagePrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mFrontPageHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gFrontPagePrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data + // + gFrontPagePrivate.HiiHandle = HiiAddPackages ( + &gFrontPageFormSetGuid, + gFrontPagePrivate.DriverHandle, + FrontPageVfrBin, + BdsDxeStrings, + NULL + ); + if (gFrontPagePrivate.HiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + + // + // Init OpCode Handle and Allocate space for creation of UpdateData Buffer + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_SELECT_LANGUAGE; + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Collect the languages from what our current Language support is based on our VFR + // + HiiHandle = gFrontPagePrivate.HiiHandle; + + GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLang, NULL); + + // + // Get Support language list from variable. + // + if (mLanguageString == NULL){ + GetEfiGlobalVariable2 (L"PlatformLangCodes", (VOID**)&mLanguageString, NULL); + if (mLanguageString == NULL) { + mLanguageString = AllocateCopyPool ( + AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)), + (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes) + ); + ASSERT (mLanguageString != NULL); + } + } + + if (gFrontPagePrivate.LanguageToken == NULL) { + // + // Count the language list number. + // + LangCode = mLanguageString; + Lang = AllocatePool (AsciiStrSize (mLanguageString)); + ASSERT (Lang != NULL); + OptionCount = 0; + while (*LangCode != 0) { + GetNextLanguage (&LangCode, Lang); + OptionCount ++; + } + + // + // Allocate extra 1 as the end tag. + // + gFrontPagePrivate.LanguageToken = AllocateZeroPool ((OptionCount + 1) * sizeof (EFI_STRING_ID)); + ASSERT (gFrontPagePrivate.LanguageToken != NULL); + + Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString); + ASSERT_EFI_ERROR (Status); + + LangCode = mLanguageString; + OptionCount = 0; + while (*LangCode != 0) { + GetNextLanguage (&LangCode, Lang); + + StringSize = 0; + Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); + if (Status == EFI_BUFFER_TOO_SMALL) { + StringBuffer = AllocateZeroPool (StringSize); + ASSERT (StringBuffer != NULL); + Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); + ASSERT_EFI_ERROR (Status); + } + + if (EFI_ERROR (Status)) { + LangSize = AsciiStrSize (Lang); + StringBuffer = AllocatePool (LangSize * sizeof (CHAR16)); + ASSERT (StringBuffer != NULL); + AsciiStrToUnicodeStrS (Lang, StringBuffer, LangSize); + } + + ASSERT (StringBuffer != NULL); + gFrontPagePrivate.LanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL); + FreePool (StringBuffer); + + OptionCount++; + } + } + + ASSERT (gFrontPagePrivate.LanguageToken != NULL); + LangCode = mLanguageString; + OptionCount = 0; + if (Lang == NULL) { + Lang = AllocatePool (AsciiStrSize (mLanguageString)); + ASSERT (Lang != NULL); + } + while (*LangCode != 0) { + GetNextLanguage (&LangCode, Lang); + + if (CurrentLang != NULL && AsciiStrCmp (Lang, CurrentLang) == 0) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + gFrontPagePrivate.LanguageToken[OptionCount], + EFI_IFR_OPTION_DEFAULT, + EFI_IFR_NUMERIC_SIZE_1, + (UINT8) OptionCount + ); + } else { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + gFrontPagePrivate.LanguageToken[OptionCount], + 0, + EFI_IFR_NUMERIC_SIZE_1, + (UINT8) OptionCount + ); + } + + OptionCount++; + } + + if (CurrentLang != NULL) { + FreePool (CurrentLang); + } + FreePool (Lang); + + HiiCreateOneOfOpCode ( + StartOpCodeHandle, + FRONT_PAGE_KEY_LANGUAGE, + 0, + 0, + STRING_TOKEN (STR_LANGUAGE_SELECT), + STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), + EFI_IFR_FLAG_CALLBACK, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + Status = HiiUpdateForm ( + HiiHandle, + &gFrontPageFormSetGuid, + FRONT_PAGE_FORM_ID, + StartOpCodeHandle, // LABEL_SELECT_LANGUAGE + EndOpCodeHandle // LABEL_END + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + return Status; +} + +/** + Call the browser and display the front page + + @return Status code that will be returned by + EFI_FORM_BROWSER2_PROTOCOL.SendForm (). + +**/ +EFI_STATUS +CallFrontPage ( + VOID + ) +{ + EFI_STATUS Status; + EFI_BROWSER_ACTION_REQUEST ActionRequest; + + // + // Begin waiting for USER INPUT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT) + ); + + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &gFrontPagePrivate.HiiHandle, + 1, + &gFrontPageFormSetGuid, + 0, + NULL, + &ActionRequest + ); + // + // Check whether user change any option setting which needs a reset to be effective + // + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + return Status; +} + +/** + 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 returns EFI_SUCCESS always. + +**/ +EFI_STATUS +GetProducerString ( + IN EFI_GUID *ProducerGuid, + IN EFI_STRING_ID Token, + OUT CHAR16 **String + ) +{ + EFI_STRING TmpString; + + TmpString = HiiGetPackageString (ProducerGuid, Token, NULL); + if (TmpString == NULL) { + *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); + } else { + *String = TmpString; + } + + return EFI_SUCCESS; +} + +/** + Convert Processor Frequency Data to a string. + + @param ProcessorFrequency The frequency data to process + @param Base10Exponent The exponent based on 10 + @param String The string that is created + +**/ +VOID +ConvertProcessorToString ( + IN UINT16 ProcessorFrequency, + IN UINT16 Base10Exponent, + OUT CHAR16 **String + ) +{ + CHAR16 *StringBuffer; + UINTN Index; + UINT32 FreqMhz; + + if (Base10Exponent >= 6) { + FreqMhz = ProcessorFrequency; + for (Index = 0; Index < (UINTN) (Base10Exponent - 6); Index++) { + FreqMhz *= 10; + } + } else { + FreqMhz = 0; + } + + StringBuffer = AllocateZeroPool (0x20); + ASSERT (StringBuffer != NULL); + Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3); + StrCatS (StringBuffer, 0x20 / sizeof (CHAR16), L"."); + UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2); + StrCatS (StringBuffer, 0x20 / sizeof (CHAR16), L" GHz"); + *String = (CHAR16 *) StringBuffer; + return ; +} + + +/** + Convert Memory Size to a string. + + @param MemorySize The size of the memory to process + @param String The string that is created + +**/ +VOID +ConvertMemorySizeToString ( + IN UINT32 MemorySize, + OUT CHAR16 **String + ) +{ + CHAR16 *StringBuffer; + + StringBuffer = AllocateZeroPool (0x20); + ASSERT (StringBuffer != NULL); + UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6); + StrCatS (StringBuffer, 0x20 / sizeof (CHAR16), L" MB RAM"); + + *String = (CHAR16 *) StringBuffer; + + return ; +} + +/** + + 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 + // + *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); + } else { + *String = AllocatePool (StrSize * sizeof (CHAR16)); + AsciiStrToUnicodeStrS (OptionalStrStart, *String, StrSize); + } + + return EFI_SUCCESS; +} + + +/** + Update the banner information for the Front Page based on DataHub information. + +**/ +VOID +UpdateFrontPageStrings ( + VOID + ) +{ + UINT8 StrIndex; + CHAR16 *NewString; + BOOLEAN Find[5]; + EFI_STATUS Status; + EFI_STRING_ID TokenToUpdate; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_PROTOCOL *Smbios; + SMBIOS_TABLE_TYPE0 *Type0Record; + SMBIOS_TABLE_TYPE1 *Type1Record; + SMBIOS_TABLE_TYPE4 *Type4Record; + SMBIOS_TABLE_TYPE19 *Type19Record; + EFI_SMBIOS_TABLE_HEADER *Record; + + ZeroMem (Find, sizeof (Find)); + + // + // Update Front Page strings + // + Status = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID **) &Smbios + ); + if (!EFI_ERROR (Status)) { + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + do { + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + if (EFI_ERROR(Status)) { + break; + } + + if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) { + Type0Record = (SMBIOS_TABLE_TYPE0 *) Record; + StrIndex = Type0Record->BiosVersion; + GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[0] = TRUE; + } + + if (Record->Type == EFI_SMBIOS_TYPE_SYSTEM_INFORMATION) { + Type1Record = (SMBIOS_TABLE_TYPE1 *) Record; + StrIndex = Type1Record->ProductName; + GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[1] = TRUE; + } + + if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) { + Type4Record = (SMBIOS_TABLE_TYPE4 *) Record; + StrIndex = Type4Record->ProcessorVersion; + GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[2] = TRUE; + } + + if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) { + Type4Record = (SMBIOS_TABLE_TYPE4 *) Record; + ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[3] = TRUE; + } + + if ( Record->Type == EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) { + Type19Record = (SMBIOS_TABLE_TYPE19 *) Record; + ConvertMemorySizeToString ( + (UINT32)(RShiftU64((Type19Record->EndingAddress - Type19Record->StartingAddress + 1), 10)), + &NewString + ); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[4] = TRUE; + } + } while ( !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4])); + } + return ; +} + + +/** + Function waits for a given event to fire, or for an optional timeout to expire. + + @param Event The event to wait for + @param Timeout An optional timeout value in 100 ns units. + + @retval EFI_SUCCESS Event fired before Timeout expired. + @retval EFI_TIME_OUT Timout expired before Event fired.. + +**/ +EFI_STATUS +WaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout OPTIONAL + ) +{ + UINTN Index; + EFI_STATUS Status; + EFI_EVENT TimerEvent; + EFI_EVENT WaitList[2]; + + if (Timeout != 0) { + // + // Create a timer event + // + Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); + if (!EFI_ERROR (Status)) { + // + // Set the timer event + // + gBS->SetTimer ( + TimerEvent, + TimerRelative, + Timeout + ); + + // + // Wait for the original event or the timer + // + WaitList[0] = Event; + WaitList[1] = TimerEvent; + Status = gBS->WaitForEvent (2, WaitList, &Index); + gBS->CloseEvent (TimerEvent); + + // + // If the timer expired, change the return to timed out + // + if (!EFI_ERROR (Status) && Index == 1) { + Status = EFI_TIMEOUT; + } + } + } else { + // + // No timeout... just wait on the event + // + Status = gBS->WaitForEvent (1, &Event, &Index); + ASSERT (!EFI_ERROR (Status)); + ASSERT (Index == 0); + } + + return Status; +} + +/** + Function show progress bar to wait for user input. + + + @param TimeoutDefault The fault time out value before the system continue to boot. + + @retval EFI_SUCCESS User pressed some key except "Enter" + @retval EFI_TIME_OUT Timeout expired or user press "Enter" + +**/ +EFI_STATUS +ShowProgress ( + 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; + + if (TimeoutDefault != 0) { + DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n")); + + SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); + SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); + SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); + + TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION)); + + if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { + // + // Clear the progress status bar first + // + if (TmpStr != NULL) { + PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0); + } + } + + + TimeoutRemain = TimeoutDefault; + while (TimeoutRemain != 0) { + DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain)); + + Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND); + if (Status != EFI_TIMEOUT) { + break; + } + TimeoutRemain--; + + if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { + // + // Show progress + // + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault), + 0 + ); + } + } + } + + if (TmpStr != NULL) { + gBS->FreePool (TmpStr); + } + + // + // Timeout expired + // + if (TimeoutRemain == 0) { + return EFI_TIMEOUT; + } + } + + // + // User pressed some key + // + if (!PcdGetBool (PcdConInConnectOnDemand)) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + // + // User pressed enter, equivalent to select "continue" + // + return EFI_TIMEOUT; + } + } + + 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 +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ) +{ + EFI_STATUS Status; + EFI_STATUS StatusHotkey; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; + UINTN BootTextColumn; + UINTN BootTextRow; + UINT64 OsIndication; + UINTN DataSize; + EFI_INPUT_KEY Key; + + 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; + } + + + // + // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set + // + OsIndication = 0; + DataSize = sizeof(UINT64); + Status = gRT->GetVariable ( + L"OsIndications", + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &OsIndication + ); + + // + // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot + // + if (!EFI_ERROR(Status) && ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0)) { + // + // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS + // + OsIndication &= ~((UINT64)EFI_OS_INDICATIONS_BOOT_TO_FW_UI); + Status = gRT->SetVariable ( + L"OsIndications", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(UINT64), + &OsIndication + ); + // + // Changing the content without increasing its size with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + // + // Follow generic rule, Call ReadKeyStroke to connect ConIn before enter UI + // + if (PcdGetBool (PcdConInConnectOnDemand)) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &Key); + } + + // + // Ensure screen is clear when switch Console from Graphics mode to Text mode + // + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + gST->ConOut->ClearScreen (gST->ConOut); + + } else { + + HotkeyBoot (); + if (TimeoutDefault != 0xffff) { + Status = ShowProgress (TimeoutDefault); + StatusHotkey = HotkeyBoot (); + + if (!FeaturePcdGet(PcdBootlogoOnlyEnable) || !EFI_ERROR(Status) || !EFI_ERROR(StatusHotkey)){ + // + // Ensure screen is clear when switch Console from Graphics mode to Text mode + // Skip it in normal boot + // + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + gST->ConOut->ClearScreen (gST->ConOut); + } + + if (EFI_ERROR (Status)) { + // + // Timeout or user press enter to continue + // + goto Exit; + } + } + } + + // + // Boot Logo is corrupted, report it using Boot Logo protocol. + // + Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); + if (!EFI_ERROR (Status) && (BootLogo != NULL)) { + BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0); + } + + // + // Install BM HiiPackages. + // Keep BootMaint HiiPackage, so that it can be covered by global setting. + // + InitBMPackage (); + + Status = EFI_SUCCESS; + do { + // + // Set proper video resolution and text mode for setup + // + BdsSetConsoleMode (TRUE); + + InitializeFrontPage (FALSE); + + // + // Update Front Page strings + // + UpdateFrontPageStrings (); + + gCallbackKey = 0; + CallFrontPage (); + + // + // 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: + // + // Remove the installed BootMaint HiiPackages when exit. + // + FreeBMPackage (); + + // + // User chose to run the Boot Manager + // + CallBootManager (); + + // + // Reinstall BootMaint HiiPackages after exiting from Boot Manager. + // + InitBMPackage (); + 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 ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE)); + + if (mLanguageString != NULL) { + FreePool (mLanguageString); + mLanguageString = NULL; + } + // + //Will leave browser, check any reset required change is applied? if yes, reset system + // + SetupResetReminder (); + + // + // Remove the installed BootMaint HiiPackages when exit. + // + FreeBMPackage (); + +Exit: + // + // Automatically load current entry + // Note: The following lines of code only execute when Auto boot + // takes affect + // + PERF_END (NULL, "BdsTimeOut", "BDS", 0); +} + +/** + This function will change video resolution and text mode + according to defined setup mode or defined boot mode + + @param IsSetupMode Indicate mode is changed to setup mode or boot mode. + + @retval EFI_SUCCESS Mode is changed successfully. + @retval Others Mode failed to be changed. + +**/ +EFI_STATUS +EFIAPI +BdsSetConsoleMode ( + BOOLEAN IsSetupMode + ) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINT32 MaxGopMode; + UINT32 MaxTextMode; + UINT32 ModeNumber; + UINT32 NewHorizontalResolution; + UINT32 NewVerticalResolution; + UINT32 NewColumns; + UINT32 NewRows; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_STATUS Status; + UINTN Index; + UINTN CurrentColumn; + UINTN CurrentRow; + + MaxGopMode = 0; + MaxTextMode = 0; + + // + // Get current video resolution and text mode + // + 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) || (SimpleTextOut == NULL)) { + return EFI_UNSUPPORTED; + } + + if (IsSetupMode) { + // + // The requried resolution and text mode is setup mode. + // + NewHorizontalResolution = mSetupHorizontalResolution; + NewVerticalResolution = mSetupVerticalResolution; + NewColumns = mSetupTextModeColumn; + NewRows = mSetupTextModeRow; + } else { + // + // The required resolution and text mode is boot mode. + // + NewHorizontalResolution = mBootHorizontalResolution; + NewVerticalResolution = mBootVerticalResolution; + NewColumns = mBootTextModeColumn; + NewRows = mBootTextModeRow; + } + + if (GraphicsOutput != NULL) { + MaxGopMode = GraphicsOutput->Mode->MaxMode; + } + + if (SimpleTextOut != NULL) { + MaxTextMode = SimpleTextOut->Mode->MaxMode; + } + + // + // 1. If current video resolution is same with required video resolution, + // video resolution need not be changed. + // 1.1. If current text mode is same with required text mode, text mode need not be changed. + // 1.2. If current text mode is different from required text mode, text mode need be changed. + // 2. If current video resolution is different from required video resolution, we need restart whole console drivers. + // + for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) { + Status = GraphicsOutput->QueryMode ( + GraphicsOutput, + ModeNumber, + &SizeOfInfo, + &Info + ); + if (!EFI_ERROR (Status)) { + if ((Info->HorizontalResolution == NewHorizontalResolution) && + (Info->VerticalResolution == NewVerticalResolution)) { + if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) && + (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) { + // + // Current resolution is same with required resolution, check if text mode need be set + // + Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow); + ASSERT_EFI_ERROR (Status); + if (CurrentColumn == NewColumns && CurrentRow == NewRows) { + // + // If current text mode is same with required text mode. Do nothing + // + FreePool (Info); + return EFI_SUCCESS; + } else { + // + // If current text mode is different from requried text mode. Set new video mode + // + for (Index = 0; Index < MaxTextMode; Index++) { + Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow); + if (!EFI_ERROR(Status)) { + if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) { + // + // Required text mode is supported, set it. + // + Status = SimpleTextOut->SetMode (SimpleTextOut, Index); + ASSERT_EFI_ERROR (Status); + // + // Update text mode PCD. + // + Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow); + ASSERT_EFI_ERROR (Status); + FreePool (Info); + return EFI_SUCCESS; + } + } + } + if (Index == MaxTextMode) { + // + // If requried text mode is not supported, return error. + // + FreePool (Info); + return EFI_UNSUPPORTED; + } + } + } else { + // + // If current video resolution is not same with the new one, set new video resolution. + // In this case, the driver which produces simple text out need be restarted. + // + Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber); + if (!EFI_ERROR (Status)) { + FreePool (Info); + break; + } + } + } + FreePool (Info); + } + } + + if (ModeNumber == MaxGopMode) { + // + // If the resolution is not supported, return error. + // + return EFI_UNSUPPORTED; + } + + // + // Set PCD to Inform GraphicsConsole to change video resolution. + // Set PCD to Inform Consplitter to change text mode. + // + Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdConOutColumn, NewColumns); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdConOutRow, NewRows); + ASSERT_EFI_ERROR (Status); + + + // + // Video mode is changed, so restart graphics console driver and higher level driver. + // Reconnect graphics console driver and higher level driver. + // Locate all the handles with GOP protocol and reconnect it. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextOutProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < HandleCount; Index++) { + gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); + } + for (Index = 0; Index < HandleCount; Index++) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + } + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h new file mode 100644 index 0000000000..a7b1c5bca0 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h @@ -0,0 +1,254 @@ +/** @file + FrontPage routines to handle the callbacks and browser calls + +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. + +**/ + +#ifndef _FRONT_PAGE_H_ +#define _FRONT_PAGE_H_ + +#include "DeviceMngr/DeviceManager.h" +#include "BootMaint/BootMaint.h" +#include "BootMngr/BootManager.h" +#include "String.h" + + +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 FrontPageVfrBin[]; + +extern EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2; + +extern UINTN gCallbackKey; +extern BOOLEAN gConnectAllHappened; + +// +// 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; + + +#define ONE_SECOND 10000000 + +/// +/// The size of a 3 character ISO639 language code. +/// +#define ISO_639_2_ENTRY_SIZE 3 + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// +#define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001 + +// +// These are defined as the same with vfr file +// +#define FRONT_PAGE_FORM_ID 0x1000 + +#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 LABEL_SELECT_LANGUAGE 0x1000 +#define LABEL_END 0xffff + +#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('F', 'P', 'C', 'B') + +typedef struct { + UINTN Signature; + + // + // HII relative handles + // + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + EFI_STRING_ID *LanguageToken; + + // + // Produced protocols + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} FRONT_PAGE_CALLBACK_DATA; + +#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \ + CR (a, \ + FRONT_PAGE_CALLBACK_DATA, \ + ConfigAccess, \ + FRONT_PAGE_CALLBACK_DATA_SIGNATURE \ + ) + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +FakeExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ); + +/** + 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 +FakeRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +/** + This function processes the results of changes in configuration. + + + @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action - Specifies the type of action taken by the browser. + @param QuestionId - A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @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 The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + +**/ +EFI_STATUS +EFIAPI +FrontPageCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + Initialize HII information for the FrontPage + + + @param InitializeHiiData TRUE if HII elements need to be initialized. + + @retval EFI_SUCCESS The operation is successful. + @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed. + +**/ +EFI_STATUS +InitializeFrontPage ( + IN BOOLEAN InitializeHiiData + ); + +/** + 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 returns EFI_SUCCESS always. + +**/ +EFI_STATUS +GetProducerString ( + IN EFI_GUID *ProducerGuid, + IN EFI_STRING_ID Token, + OUT CHAR16 **String + ); + +/** + 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 +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ); + +/** + This function will change video resolution and text mode + according to defined setup mode or defined boot mode + + @param IsSetupMode Indicate mode is changed to setup mode or boot mode. + + @retval EFI_SUCCESS Mode is changed successfully. + @retval Others Mode failed to be changed. + +**/ +EFI_STATUS +EFIAPI +BdsSetConsoleMode ( + BOOLEAN IsSetupMode + ); + +#endif // _FRONT_PAGE_H_ + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni new file mode 100644 index 0000000000..3c083b4998 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr new file mode 100644 index 0000000000..a2d92dff51 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr @@ -0,0 +1,137 @@ +///** @file +// +// Browser formset. +// +// Copyright (c) 2007 - 2015, Intel 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 + +#define FRONT_PAGE_CLASS 0x0000 +#define FRONT_PAGE_SUBCLASS 0x0002 + +#define FRONT_PAGE_FORM_ID 0x1000 + +#define FRONT_PAGE_ITEM_ONE 0x0001 +#define FRONT_PAGE_ITEM_TWO 0x0002 +#define FRONT_PAGE_ITEM_THREE 0x0003 +#define FRONT_PAGE_ITEM_FOUR 0x0004 +#define FRONT_PAGE_ITEM_FIVE 0x0005 + +#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 LABEL_SELECT_LANGUAGE 0x1000 +#define LABEL_TIMEOUT 0x2000 +#define LABEL_END 0xffff + +formset + guid = FRONT_PAGE_FORMSET_GUID, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = FRONT_PAGE_FORMSET_GUID, + + form formid = FRONT_PAGE_FORM_ID, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL), + line 1, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL), + line 2, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED), + line 2, + align right; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION), + line 3, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE), + line 3, + align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT), +// line 0, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT), +// line 0, +// align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT), +// line 1, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT), +// line 1, +// align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT), +// line 2, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT), +// line 3, +// align left; + + + text + help = STRING_TOKEN(STR_CONTINUE_HELP), + text = STRING_TOKEN(STR_CONTINUE_PROMPT), + flags = INTERACTIVE, + key = FRONT_PAGE_KEY_CONTINUE; + + label LABEL_SELECT_LANGUAGE; + // + // This is where we will dynamically add a OneOf type op-code to select + // Languages from the currently available choices + // + label LABEL_END; + + goto FRONT_PAGE_ITEM_THREE, + prompt = STRING_TOKEN(STR_BOOT_MANAGER), + help = STRING_TOKEN(STR_BOOT_MANAGER_HELP), + flags = INTERACTIVE, + key = FRONT_PAGE_KEY_BOOT_MANAGER; + + goto FRONT_PAGE_ITEM_FOUR, + prompt = STRING_TOKEN(STR_DEVICE_MANAGER), + help = STRING_TOKEN(STR_DEVICE_MANAGER_HELP), + flags = INTERACTIVE, + key = FRONT_PAGE_KEY_DEVICE_MANAGER; + + goto FRONT_PAGE_ITEM_FIVE, + prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER), + help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP), + flags = INTERACTIVE, + key = FRONT_PAGE_KEY_BOOT_MAINTAIN; + + endform; + +endformset; diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c new file mode 100644 index 0000000000..e061991ea2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c @@ -0,0 +1,597 @@ +/** @file + Provides a way for 3rd party applications to register themselves for launch by the + Boot Manager based on hot key + +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 +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 "Hotkey.h" + + +LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList); +BDS_COMMON_OPTION *mHotkeyBootOption = NULL; +EFI_EVENT mHotkeyEvent; +VOID *mHotkeyRegistration; + + +/** + Check if the Key Option is valid or not. + + @param KeyOption The Hot Key Option to be checked. + + @retval TRUE The Hot Key Option is valid. + @retval FALSE The Hot Key Option is invalid. + +**/ +BOOLEAN +IsKeyOptionValid ( + IN EFI_KEY_OPTION *KeyOption +) +{ + UINT16 BootOptionName[10]; + UINT8 *BootOptionVar; + UINTN BootOptionSize; + UINT32 Crc; + + // + // Check whether corresponding Boot Option exist + // + UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOptionName, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + + if (BootOptionVar == NULL || BootOptionSize == 0) { + return FALSE; + } + + // + // Check CRC for Boot Option + // + gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc); + FreePool (BootOptionVar); + + return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE); +} + +/** + Try to boot the boot option triggered by hotkey. + @retval EFI_SUCCESS There is HotkeyBootOption & it is processed + @retval EFI_NOT_FOUND There is no HotkeyBootOption +**/ +EFI_STATUS +HotkeyBoot ( + VOID + ) +{ + EFI_STATUS Status; + UINTN ExitDataSize; + CHAR16 *ExitData; + + if (mHotkeyBootOption == NULL) { + return EFI_NOT_FOUND; + } + + BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath); + + // + // Clear the screen before launch this BootOption + // + gST->ConOut->Reset (gST->ConOut, FALSE); + + Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData); + + if (EFI_ERROR (Status)) { + // + // Call platform action to indicate the boot fail + // + mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); + PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize); + } else { + // + // Call platform action to indicate the boot success + // + mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); + PlatformBdsBootSuccess (mHotkeyBootOption); + } + FreePool (mHotkeyBootOption->Description); + FreePool (mHotkeyBootOption->DevicePath); + FreePool (mHotkeyBootOption->LoadOptions); + FreePool (mHotkeyBootOption); + + mHotkeyBootOption = NULL; + + return EFI_SUCCESS; +} + +/** + + This is the common notification function for HotKeys, it will be registered + with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle. + + @param KeyData A pointer to a buffer that is filled in with the keystroke + information for the key that was pressed. + + @retval EFI_SUCCESS KeyData is successfully processed. + @return EFI_NOT_FOUND Fail to find boot option variable. +**/ +EFI_STATUS +EFIAPI +HotkeyCallback ( + IN EFI_KEY_DATA *KeyData +) +{ + BOOLEAN HotkeyCatched; + LIST_ENTRY BootLists; + LIST_ENTRY *Link; + BDS_HOTKEY_OPTION *Hotkey; + UINT16 Buffer[10]; + EFI_STATUS Status; + EFI_KEY_DATA *HotkeyData; + + if (mHotkeyBootOption != NULL) { + // + // Do not process sequential hotkey stroke until the current boot option returns + // + return EFI_SUCCESS; + } + + Status = EFI_SUCCESS; + + for ( Link = GetFirstNode (&mHotkeyList) + ; !IsNull (&mHotkeyList, Link) + ; Link = GetNextNode (&mHotkeyList, Link) + ) { + HotkeyCatched = FALSE; + Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link); + + // + // Is this Key Stroke we are waiting for? + // + ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0]))); + HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey]; + if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) && + (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) && + (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? + (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE + ) + ) { + // + // For hotkey of key combination, transit to next waiting state + // + Hotkey->WaitingKey++; + + if (Hotkey->WaitingKey == Hotkey->CodeCount) { + // + // Received the whole key stroke sequence + // + HotkeyCatched = TRUE; + } + } else { + // + // Receive an unexpected key stroke, reset to initial waiting state + // + Hotkey->WaitingKey = 0; + } + + if (HotkeyCatched) { + // + // Reset to initial waiting state + // + Hotkey->WaitingKey = 0; + + // + // Launch its BootOption + // + InitializeListHead (&BootLists); + + UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber); + mHotkeyBootOption = BdsLibVariableToOption (&BootLists, Buffer); + } + } + + return Status; +} + +/** + Register the common HotKey notify function to given SimpleTextInEx protocol instance. + + @param SimpleTextInEx Simple Text Input Ex protocol instance + + @retval EFI_SUCCESS Register hotkey notification function successfully. + @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures. + +**/ +EFI_STATUS +HotkeyRegisterNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx +) +{ + UINTN Index; + EFI_STATUS Status; + LIST_ENTRY *Link; + BDS_HOTKEY_OPTION *Hotkey; + + // + // Register notification function for each hotkey + // + Link = GetFirstNode (&mHotkeyList); + + while (!IsNull (&mHotkeyList, Link)) { + Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link); + + Index = 0; + do { + Status = SimpleTextInEx->RegisterKeyNotify ( + SimpleTextInEx, + &Hotkey->KeyData[Index], + HotkeyCallback, + &Hotkey->NotifyHandle + ); + if (EFI_ERROR (Status)) { + // + // some of the hotkey registry failed + // + return Status; + } + Index ++; + } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA)))); + + Link = GetNextNode (&mHotkeyList, Link); + } + + return EFI_SUCCESS; +} + +/** + Callback function for SimpleTextInEx protocol install events + + @param Event the event that is signaled. + @param Context not used here. + +**/ +VOID +EFIAPI +HotkeyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE Handle; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx; + + while (TRUE) { + BufferSize = sizeof (EFI_HANDLE); + Status = gBS->LocateHandle ( + ByRegisterNotify, + NULL, + mHotkeyRegistration, + &BufferSize, + &Handle + ); + if (EFI_ERROR (Status)) { + // + // If no more notification events exist + // + return ; + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID **) &SimpleTextInEx + ); + ASSERT_EFI_ERROR (Status); + + HotkeyRegisterNotify (SimpleTextInEx); + } +} + +/** + Insert Key Option to hotkey list. + + @param KeyOption The Hot Key Option to be added to hotkey list. + + @retval EFI_SUCCESS Add to hotkey list success. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource. +**/ +EFI_STATUS +HotkeyInsertList ( + IN EFI_KEY_OPTION *KeyOption +) +{ + BDS_HOTKEY_OPTION *HotkeyLeft; + BDS_HOTKEY_OPTION *HotkeyRight; + UINTN Index; + EFI_BOOT_KEY_DATA KeyOptions; + UINT32 KeyShiftStateLeft; + UINT32 KeyShiftStateRight; + EFI_INPUT_KEY *InputKey; + EFI_KEY_DATA *KeyData; + + HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION)); + if (HotkeyLeft == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE; + HotkeyLeft->BootOptionNumber = KeyOption->BootOption; + + KeyOptions = KeyOption->KeyData; + + HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount; + + // + // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState + // + KeyShiftStateRight = EFI_SHIFT_STATE_VALID; + if (KeyOptions.Options.ShiftPressed) { + KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED; + } + if (KeyOptions.Options.ControlPressed) { + KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED; + } + if (KeyOptions.Options.AltPressed) { + KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED; + } + if (KeyOptions.Options.LogoPressed) { + KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED; + } + if (KeyOptions.Options.MenuPressed) { + KeyShiftStateRight |= EFI_MENU_KEY_PRESSED; + } + if (KeyOptions.Options.SysReqPressed) { + KeyShiftStateRight |= EFI_SYS_REQ_PRESSED; + } + + KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1); + + InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION)); + + Index = 0; + KeyData = &HotkeyLeft->KeyData[0]; + do { + // + // If Key CodeCount is 0, then only KeyData[0] is used; + // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used + // + KeyData->Key.ScanCode = InputKey[Index].ScanCode; + KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar; + KeyData->KeyState.KeyShiftState = KeyShiftStateLeft; + + Index++; + KeyData++; + } while (Index < HotkeyLeft->CodeCount); + InsertTailList (&mHotkeyList, &HotkeyLeft->Link); + + if (KeyShiftStateLeft != KeyShiftStateRight) { + // + // Need an extra hotkey for shift key on right + // + HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft); + if (HotkeyRight == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Index = 0; + KeyData = &HotkeyRight->KeyData[0]; + do { + // + // Key.ScanCode and Key.UnicodeChar have already been initialized, + // only need to update KeyState.KeyShiftState + // + KeyData->KeyState.KeyShiftState = KeyShiftStateRight; + + Index++; + KeyData++; + } while (Index < HotkeyRight->CodeCount); + InsertTailList (&mHotkeyList, &HotkeyRight->Link); + } + + return EFI_SUCCESS; +} + +/** + Return TRUE when the variable pointed by Name and Guid is a Key#### variable. + + @param Name The name of the variable. + @param Guid The GUID of the variable. + @param OptionNumber Return the option number parsed from the Name. + + @retval TRUE The variable pointed by Name and Guid is a Key#### variable. + @retval FALSE The variable pointed by Name and Guid isn't a Key#### variable. +**/ +BOOLEAN +IsKeyOptionVariable ( + CHAR16 *Name, + EFI_GUID *Guid, + UINT16 *OptionNumber + ) +{ + UINTN Index; + + if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) || + (StrSize (Name) != sizeof (L"Key####")) || + (StrnCmp (Name, L"Key", 3) != 0) + ) { + return FALSE; + } + + *OptionNumber = 0; + for (Index = 3; Index < 7; Index++) { + if ((Name[Index] >= L'0') && (Name[Index] <= L'9')) { + *OptionNumber = *OptionNumber * 16 + Name[Index] - L'0'; + } else if ((Name[Index] >= L'A') && (Name[Index] <= L'F')) { + *OptionNumber = *OptionNumber * 16 + Name[Index] - L'A' + 10; + } else { + return FALSE; + } + } + + return TRUE; +} + +/** + Return an array of key option numbers. + + @param Count Return the count of key option numbers. + + @return UINT16* Pointer to an array of key option numbers; +**/ +UINT16 * +EFIAPI +HotkeyGetOptionNumbers ( + OUT UINTN *Count + ) +{ + EFI_STATUS Status; + UINTN Index; + CHAR16 *Name; + EFI_GUID Guid; + UINTN NameSize; + UINTN NewNameSize; + UINT16 *OptionNumbers; + UINT16 OptionNumber; + + if (Count == NULL) { + return NULL; + } + + *Count = 0; + OptionNumbers = NULL; + + NameSize = sizeof (CHAR16); + Name = AllocateZeroPool (NameSize); + ASSERT (Name != NULL); + while (TRUE) { + NewNameSize = NameSize; + Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid); + if (Status == EFI_BUFFER_TOO_SMALL) { + Name = ReallocatePool (NameSize, NewNameSize, Name); + ASSERT (Name != NULL); + Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid); + NameSize = NewNameSize; + } + + if (Status == EFI_NOT_FOUND) { + break; + } + ASSERT_EFI_ERROR (Status); + + if (IsKeyOptionVariable (Name ,&Guid, &OptionNumber)) { + OptionNumbers = ReallocatePool ( + *Count * sizeof (UINT16), + (*Count + 1) * sizeof (UINT16), + OptionNumbers + ); + ASSERT (OptionNumbers != NULL); + for (Index = 0; Index < *Count; Index++) { + if (OptionNumber < OptionNumbers[Index]) { + break; + } + } + CopyMem (&OptionNumbers[Index + 1], &OptionNumbers[Index], (*Count - Index) * sizeof (UINT16)); + OptionNumbers[Index] = OptionNumber; + (*Count)++; + } + } + + FreePool (Name); + + return OptionNumbers; +} + +/** + + Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options. + + @retval EFI_SUCCESS Hotkey services successfully initialized. +**/ +EFI_STATUS +InitializeHotkeyService ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 BootOptionSupport; + UINT16 *KeyOptionNumbers; + UINTN KeyOptionCount; + UINTN Index; + CHAR16 KeyOptionName[8]; + EFI_KEY_OPTION *KeyOption; + + // + // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP. + // with maximum number of key presses of 3 + // Do not report the hotkey capability if PcdConInConnectOnDemand is enabled. + // + BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP; + if (!PcdGetBool (PcdConInConnectOnDemand)) { + BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY; + SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3); + } + + Status = gRT->SetVariable ( + L"BootOptionSupport", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT32), + &BootOptionSupport + ); + // + // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + KeyOptionNumbers = HotkeyGetOptionNumbers (&KeyOptionCount); + for (Index = 0; Index < KeyOptionCount; Index ++) { + UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumbers[Index]); + GetEfiGlobalVariable2 (KeyOptionName, (VOID **) &KeyOption, NULL); + ASSERT (KeyOption != NULL); + if (IsKeyOptionValid (KeyOption)) { + HotkeyInsertList (KeyOption); + } + FreePool (KeyOption); + } + + if (KeyOptionNumbers != NULL) { + FreePool (KeyOptionNumbers); + } + + // + // Register Protocol notify for Hotkey service + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + HotkeyEvent, + NULL, + &mHotkeyEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for protocol notifications on this event + // + Status = gBS->RegisterProtocolNotify ( + &gEfiSimpleTextInputExProtocolGuid, + mHotkeyEvent, + &mHotkeyRegistration + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h new file mode 100644 index 0000000000..4ee5563a22 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h @@ -0,0 +1,67 @@ +/** @file + Provides a way for 3rd party applications to register themselves for launch by the + Boot Manager based on hot key + +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. + +**/ + +#ifndef _HOTKEY_H_ +#define _HOTKEY_H_ + +#include "Bds.h" +#include "String.h" + +#define SET_BOOT_OPTION_SUPPORT_KEY_COUNT(a, c) { \ + (a) = ((a) & ~EFI_BOOT_OPTION_SUPPORT_COUNT) | (((c) << LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT)) & EFI_BOOT_OPTION_SUPPORT_COUNT); \ + } + +#define BDS_HOTKEY_OPTION_SIGNATURE SIGNATURE_32 ('B', 'd', 'K', 'O') + + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + VOID *NotifyHandle; + UINT16 BootOptionNumber; + UINT8 CodeCount; + UINT8 WaitingKey; + EFI_KEY_DATA KeyData[3]; +} BDS_HOTKEY_OPTION; + +#define BDS_HOTKEY_OPTION_FROM_LINK(a) CR (a, BDS_HOTKEY_OPTION, Link, BDS_HOTKEY_OPTION_SIGNATURE) + +/** + + Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options. + + + @param VOID + + @retval EFI_SUCCESS Hotkey services successfully initialized. + +**/ +EFI_STATUS +InitializeHotkeyService ( + VOID + ); + +/** + Try to boot the boot option triggered by hotkey. + @retval EFI_SUCCESS There is HotkeyBootOption & it is processed + @retval EFI_NOT_FOUND There is no HotkeyBootOption +**/ +EFI_STATUS +HotkeyBoot ( + VOID + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c new file mode 100644 index 0000000000..ddb2f93980 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c @@ -0,0 +1,48 @@ +/** @file + Set the level of support for Hardware Error Record Persistence that is + implemented by the platform. + +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. + +**/ + +#include "HwErrRecSupport.h" + +/** + Set the HwErrRecSupport variable contains a binary UINT16 that supplies the + level of support for Hardware Error Record Persistence that is implemented + by the platform. + +**/ +VOID +InitializeHwErrRecSupport ( + VOID + ) +{ + EFI_STATUS Status; + UINT16 HardwareErrorRecordLevel; + + HardwareErrorRecordLevel = PcdGet16 (PcdHardwareErrorRecordLevel); + + if (HardwareErrorRecordLevel != 0) { + // + // If level value equal 0, no need set to 0 to variable area because UEFI specification + // define same behavior between no value or 0 value for L"HwErrRecSupport". + // + Status = gRT->SetVariable ( + L"HwErrRecSupport", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &HardwareErrorRecordLevel + ); + ASSERT_EFI_ERROR(Status); + } +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h new file mode 100644 index 0000000000..0cf597acc7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h @@ -0,0 +1,32 @@ +/** @file + Set the level of support for Hardware Error Record Persistence that is + implemented by the platform. + +Copyright (c) 2007 - 2008, Intel 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 _HW_ERR_REC_SUPPORT_H_ +#define _HW_ERR_REC_SUPPORT_H_ + +#include "Bds.h" + +/** + Set the HwErrRecSupport variable contains a binary UINT16 that supplies the + level of support for Hardware Error Record Persistence that is implemented + by the platform. + +**/ +VOID +InitializeHwErrRecSupport ( + VOID + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c new file mode 100644 index 0000000000..39455e44da --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c @@ -0,0 +1,499 @@ +/** @file + Language settings + +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 +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 "Language.h" +#include "FrontPage.h" + +EFI_GUID mFontPackageGuid = { + 0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc} +}; + +#define NARROW_GLYPH_NUMBER 8 +#define WIDE_GLYPH_NUMBER 75 + +typedef struct { + /// + /// This 4-bytes total array length is required by HiiAddPackages() + /// + UINT32 Length; + + // + // This is the Font package definition + // + EFI_HII_PACKAGE_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; + EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER]; + EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER]; +} FONT_PACK_BIN; + +FONT_PACK_BIN mFontBin = { + sizeof (FONT_PACK_BIN), + { + sizeof (FONT_PACK_BIN) - sizeof (UINT32), + EFI_HII_PACKAGE_SIMPLE_FONTS, + }, + NARROW_GLYPH_NUMBER, + 0, + { // Narrow Glyphs + { + 0x05d0, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x4E, + 0x6E, + 0x62, + 0x32, + 0x32, + 0x3C, + 0x68, + 0x4C, + 0x4C, + 0x46, + 0x76, + 0x72, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d1, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x78, + 0x7C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x7E, + 0x7E, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d2, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x78, + 0x7C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x1C, + 0x3E, + 0x66, + 0x66, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d3, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x7E, + 0x7E, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d4, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x7C, + 0x7E, + 0x06, + 0x06, + 0x06, + 0x06, + 0x66, + 0x66, + 0x66, + 0x66, + 0x66, + 0x66, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d5, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x3C, + 0x3C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d6, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x1E, + 0x1E, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x0000, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + } + } + } +}; + +/** + Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver. + +**/ +VOID +ExportFonts ( + VOID + ) +{ + EFI_HII_HANDLE HiiHandle; + + HiiHandle = HiiAddPackages ( + &mFontPackageGuid, + gImageHandle, + &mFontBin, + NULL + ); + ASSERT (HiiHandle != NULL); +} + +/** + Get next language from language code list (with separator ';'). + + If LangCode is NULL, then ASSERT. + If Lang is NULL, then ASSERT. + + @param LangCode On input: point to first language in the list. On + output: 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; +} + +/** + Check if lang is in supported language codes according to language string. + + This code is used to check if lang is in in supported language codes. It can handle + RFC4646 and ISO639 language tags. + In ISO639 language tags, take 3-characters as a delimitation to find matched string. + In RFC4646 language tags, take semicolon as a delimitation to find matched string. + + For example: + SupportedLang = "engfraengfra" + Iso639Language = TRUE + Lang = "eng", the return value is "TRUE", or + Lang = "chs", the return value is "FALSE". + Another example: + SupportedLang = "en;fr;en-US;fr-FR" + Iso639Language = FALSE + Lang = "en", the return value is "TRUE", or + Lang = "zh", the return value is "FALSE". + + @param SupportedLang Platform supported language codes. + @param Lang Configured language. + @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646. + + @retval TRUE lang is in supported language codes. + @retval FALSE lang is not in supported language codes. + +**/ +BOOLEAN +IsLangInSupportedLangCodes( + IN CHAR8 *SupportedLang, + IN CHAR8 *Lang, + IN BOOLEAN Iso639Language + ) +{ + UINTN Index; + UINTN CompareLength; + UINTN LanguageLength; + + if (Iso639Language) { + CompareLength = ISO_639_2_ENTRY_SIZE; + for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) { + if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) { + // + // Successfully find the Lang string in SupportedLang string. + // + return TRUE; + } + } + return FALSE; + } else { + // + // Compare RFC4646 language code + // + for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++); + + for (; *SupportedLang != '\0'; SupportedLang += CompareLength) { + // + // Skip ';' characters in SupportedLang + // + for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++); + // + // Determine the length of the next language code in SupportedLang + // + for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++); + + if ((CompareLength == LanguageLength) && + (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) { + // + // Successfully find the Lang string in SupportedLang string. + // + return TRUE; + } + } + return FALSE; + } +} + +/** + Initialize Lang or PlatformLang variable, if Lang or PlatformLang variable is not found, + or it has been set to an unsupported value(not one of platform supported language codes), + set the default language code to it. + + @param LangName Language name, L"Lang" or L"PlatformLang". + @param SupportedLang Platform supported language codes. + @param DefaultLang Default language code. + @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646, + TRUE for L"Lang" LangName or FALSE for L"PlatformLang" LangName. + +**/ +VOID +InitializeLangVariable ( + IN CHAR16 *LangName, + IN CHAR8 *SupportedLang, + IN CHAR8 *DefaultLang, + IN BOOLEAN Iso639Language + ) +{ + CHAR8 *Lang; + + // + // Find current Lang or PlatformLang from EFI Variable. + // + GetEfiGlobalVariable2 (LangName, (VOID **) &Lang, NULL); + // + // If Lang or PlatformLang variable is not found, + // or it has been set to an unsupported value(not one of the supported language codes), + // set the default language code to it. + // + if ((Lang == NULL) || !IsLangInSupportedLangCodes (SupportedLang, Lang, Iso639Language)) { + // + // The default language code should be one of the supported language codes. + // + ASSERT (IsLangInSupportedLangCodes (SupportedLang, DefaultLang, Iso639Language)); + BdsDxeSetVariableAndReportStatusCodeOnError ( + LangName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + AsciiStrSize (DefaultLang), + DefaultLang + ); + } + + if (Lang != NULL) { + FreePool (Lang); + } +} + +/** + Determine the current language that will be used + based on language related EFI Variables. + + @param LangCodesSettingRequired - If required to set LangCodes variable + +**/ +VOID +InitializeLanguage ( + BOOLEAN LangCodesSettingRequired + ) +{ + EFI_STATUS Status; + CHAR8 *LangCodes; + CHAR8 *PlatformLangCodes; + + ExportFonts (); + + LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes); + PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes); + if (LangCodesSettingRequired) { + if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) { + // + // UEFI 2.0 depricated this variable so we support turning it off + // + Status = gRT->SetVariable ( + L"LangCodes", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + AsciiStrSize (LangCodes), + LangCodes + ); + // + // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } + + Status = gRT->SetVariable ( + L"PlatformLangCodes", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + AsciiStrSize (PlatformLangCodes), + PlatformLangCodes + ); + // + // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + } + + if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) { + // + // UEFI 2.0 depricated this variable so we support turning it off + // + InitializeLangVariable (L"Lang", LangCodes, (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang), TRUE); + } + InitializeLangVariable (L"PlatformLang", PlatformLangCodes, (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang), FALSE); +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h new file mode 100644 index 0000000000..31c65f1824 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h @@ -0,0 +1,51 @@ +/** @file + Language setting + +Copyright (c) 2004 - 2008, Intel 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 _LANGUAGE_H_ +#define _LANGUAGE_H_ + +#include "String.h" + +/** + Get next language from language code list (with separator ';'). + + If LangCode is NULL, then ASSERT. + If Lang is NULL, then ASSERT. + + @param LangCode On input: point to first language in the list. On + output: 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 + ); + +/** + Determine the current language that will be used + based on language related EFI Variables. + + @param LangCodesSettingRequired If required to set LangCode variable + +**/ +VOID +InitializeLanguage ( + BOOLEAN LangCodesSettingRequired + ); + +#endif // _LANGUAGE_H_ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c new file mode 100644 index 0000000000..700e3e6626 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c @@ -0,0 +1,436 @@ +/** @file + Perform the platform memory test + +Copyright (c) 2004 - 2015, Intel 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 "Bds.h" +#include "String.h" + +// +// BDS Platform Functions +// +/** + + Show progress bar with title above it. It only works in Graphics mode. + + + @param TitleForeground Foreground color for Title. + @param TitleBackground Background color for Title. + @param Title Title above progress bar. + @param ProgressColor Progress bar color. + @param Progress Progress (0-100) + @param PreviousValue The previous value of the progress. + + @retval EFI_STATUS Success update the progress bar + +**/ +EFI_STATUS +PlatformBdsShowProgress ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, + IN CHAR16 *Title, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, + IN UINTN Progress, + IN UINTN PreviousValue + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UINT32 SizeOfX; + UINT32 SizeOfY; + UINT32 ColorDepth; + UINT32 RefreshRate; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; + UINTN BlockHeight; + UINTN BlockWidth; + UINTN BlockNum; + UINTN PosX; + UINTN PosY; + UINTN Index; + + if (Progress > 100) { + return EFI_INVALID_PARAMETER; + } + + UgaDraw = NULL; + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput + ); + if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { + GraphicsOutput = NULL; + + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw + ); + } + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + SizeOfX = 0; + SizeOfY = 0; + if (GraphicsOutput != NULL) { + SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; + SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; + } else if (UgaDraw != NULL) { + Status = UgaDraw->GetMode ( + UgaDraw, + &SizeOfX, + &SizeOfY, + &ColorDepth, + &RefreshRate + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + } else { + return EFI_UNSUPPORTED; + } + + BlockWidth = SizeOfX / 100; + BlockHeight = SizeOfY / 50; + + BlockNum = Progress; + + PosX = 0; + PosY = SizeOfY * 48 / 50; + + if (BlockNum == 0) { + // + // Clear progress area + // + SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); + + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &Color, + EfiBltVideoFill, + 0, + 0, + 0, + PosY - EFI_GLYPH_HEIGHT - 1, + SizeOfX, + SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), + SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) &Color, + EfiUgaVideoFill, + 0, + 0, + 0, + PosY - EFI_GLYPH_HEIGHT - 1, + SizeOfX, + SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), + SizeOfX * sizeof (EFI_UGA_PIXEL) + ); + } else { + return EFI_UNSUPPORTED; + } + } + // + // Show progress by drawing blocks + // + for (Index = PreviousValue; Index < BlockNum; Index++) { + PosX = Index * BlockWidth; + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &ProgressColor, + EfiBltVideoFill, + 0, + 0, + PosX, + PosY, + BlockWidth - 1, + BlockHeight, + (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) &ProgressColor, + EfiUgaVideoFill, + 0, + 0, + PosX, + PosY, + BlockWidth - 1, + BlockHeight, + (BlockWidth) * sizeof (EFI_UGA_PIXEL) + ); + } else { + return EFI_UNSUPPORTED; + } + } + + PrintXY ( + (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2, + PosY - EFI_GLYPH_HEIGHT - 1, + &TitleForeground, + &TitleBackground, + Title + ); + + return EFI_SUCCESS; +} + +/** + Perform the memory test base on the memory test intensive level, + and update the memory resource. + + @param Level The memory test intensive level. + + @retval EFI_STATUS Success test all the system memory and update + the memory resource + +**/ +EFI_STATUS +EFIAPI +BdsMemoryTest ( + IN EXTENDMEM_COVERAGE_LEVEL Level + ) +{ + EFI_STATUS Status; + EFI_STATUS KeyStatus; + EFI_STATUS InitStatus; + EFI_STATUS ReturnStatus; + BOOLEAN RequireSoftECCInit; + EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; + UINT64 TestedMemorySize; + UINT64 TotalMemorySize; + UINTN TestPercent; + UINT64 PreviousValue; + BOOLEAN ErrorOut; + BOOLEAN TestAbort; + EFI_INPUT_KEY Key; + CHAR16 StrPercent[80]; + CHAR16 *StrTotalMemory; + CHAR16 *Pos; + CHAR16 *TmpStr; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; + BOOLEAN IsFirstBoot; + UINT32 TempData; + UINTN StrTotalMemorySize; + + ReturnStatus = EFI_SUCCESS; + ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); + + StrTotalMemorySize = 128; + Pos = AllocateZeroPool (StrTotalMemorySize); + + if (Pos == NULL) { + return ReturnStatus; + } + + StrTotalMemory = Pos; + + TestedMemorySize = 0; + TotalMemorySize = 0; + PreviousValue = 0; + ErrorOut = FALSE; + TestAbort = FALSE; + + SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); + SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); + SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); + + RequireSoftECCInit = FALSE; + + Status = gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + (VOID **) &GenMemoryTest + ); + if (EFI_ERROR (Status)) { + FreePool (Pos); + return EFI_SUCCESS; + } + + InitStatus = GenMemoryTest->MemoryTestInit ( + GenMemoryTest, + Level, + &RequireSoftECCInit + ); + if (InitStatus == EFI_NO_MEDIA) { + // + // The PEI codes also have the relevant memory test code to check the memory, + // it can select to test some range of the memory or all of them. If PEI code + // checks all the memory, this BDS memory test will has no not-test memory to + // do the test, and then the status of EFI_NO_MEDIA will be returned by + // "MemoryTestInit". So it does not need to test memory again, just return. + // + FreePool (Pos); + return EFI_SUCCESS; + } + + if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { + TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST)); + + if (TmpStr != NULL) { + PrintXY (10, 10, NULL, NULL, TmpStr); + FreePool (TmpStr); + } + } else { + DEBUG ((EFI_D_INFO, "Enter memory test.\n")); + } + do { + Status = GenMemoryTest->PerformMemoryTest ( + GenMemoryTest, + &TestedMemorySize, + &TotalMemorySize, + &ErrorOut, + TestAbort + ); + if (ErrorOut && (Status == EFI_DEVICE_ERROR)) { + TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR)); + if (TmpStr != NULL) { + PrintXY (10, 10, NULL, NULL, TmpStr); + FreePool (TmpStr); + } + + ASSERT (0); + } + + if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { + TempData = (UINT32) DivU64x32 (TotalMemorySize, 16); + TestPercent = (UINTN) DivU64x32 ( + DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16), + TempData + ); + if (TestPercent != PreviousValue) { + UnicodeValueToString (StrPercent, 0, TestPercent, 0); + TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT)); + if (TmpStr != NULL) { + // + // TmpStr size is 64, StrPercent is reserved to 16. + // + StrnCatS ( + StrPercent, + sizeof (StrPercent) / sizeof (CHAR16), + TmpStr, + sizeof (StrPercent) / sizeof (CHAR16) - StrLen (StrPercent) - 1 + ); + PrintXY (10, 10, NULL, NULL, StrPercent); + FreePool (TmpStr); + } + + TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + TestPercent, + (UINTN) PreviousValue + ); + FreePool (TmpStr); + } + } + + PreviousValue = TestPercent; + } else { + DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n")); + } + + if (!PcdGetBool (PcdConInConnectOnDemand)) { + KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) { + if (!RequireSoftECCInit) { + if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { + TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + 100, + (UINTN) PreviousValue + ); + FreePool (TmpStr); + } + + PrintXY (10, 10, NULL, NULL, L"100"); + } + Status = GenMemoryTest->Finished (GenMemoryTest); + goto Done; + } + + TestAbort = TRUE; + } + } + } while (Status != EFI_NOT_FOUND); + + Status = GenMemoryTest->Finished (GenMemoryTest); + +Done: + if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { + UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0); + if (StrTotalMemory[0] == L',') { + StrTotalMemory++; + StrTotalMemorySize -= sizeof (CHAR16); + } + + TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED)); + if (TmpStr != NULL) { + StrnCatS ( + StrTotalMemory, + StrTotalMemorySize / sizeof (CHAR16), + TmpStr, + StrTotalMemorySize / sizeof (CHAR16) - StrLen (StrTotalMemory) - 1 + ); + FreePool (TmpStr); + } + + PrintXY (10, 10, NULL, NULL, StrTotalMemory); + PlatformBdsShowProgress ( + Foreground, + Background, + StrTotalMemory, + Color, + 100, + (UINTN) PreviousValue + ); + + } else { + DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize)); + } + + FreePool (Pos); + + + // + // Use a DynamicHii type pcd to save the boot status, which is used to + // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration. + // + IsFirstBoot = PcdGetBool(PcdBootState); + if (IsFirstBoot) { + Status = PcdSetBoolS(PcdBootState, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Set PcdBootState to FALSE failed.\n")); + } + } + + return ReturnStatus; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/String.c b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/String.c new file mode 100644 index 0000000000..d02001b4d1 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/String.c @@ -0,0 +1,59 @@ +/** @file + String support + +Copyright (c) 2004 - 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 "Bds.h" +#include "Language.h" +#include "FrontPage.h" + +EFI_HII_HANDLE gStringPackHandle; + +EFI_GUID mBdsStringPackGuid = { + 0x7bac95d3, 0xddf, 0x42f3, {0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a} +}; + +/** + Initialize HII global accessor for string support. + +**/ +VOID +InitializeStringSupport ( + VOID + ) +{ + gStringPackHandle = HiiAddPackages ( + &mBdsStringPackGuid, + gImageHandle, + BdsDxeStrings, + NULL + ); + ASSERT (gStringPackHandle != NULL); +} + +/** + Get string by string id from HII Interface + + + @param Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ) +{ + return HiiGetString (gStringPackHandle, Id, NULL); +} diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/String.h b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/String.h new file mode 100644 index 0000000000..005b2bdbd2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/String.h @@ -0,0 +1,65 @@ +/** @file + String support + +Copyright (c) 2004 - 2009, Intel 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 "Bds.h" + +extern EFI_HII_HANDLE gStringPackHandle; + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// + +extern UINT8 BdsDxeStrings[]; + +/** + Get string by string id from HII Interface + + + @param Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ); + +/** + Initialize HII global accessor for string support. + +**/ +VOID +InitializeStringSupport ( + VOID + ); + +/** + Call the browser and display the front page + + @return Status code that will be returned by + EFI_FORM_BROWSER2_PROTOCOL.SendForm (). + +**/ +EFI_STATUS +CallFrontPage ( + VOID + ); + +#endif // _STRING_H_ diff --git a/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni new file mode 100644 index 0000000000..040ed92c36 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/ComponentName.c b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/ComponentName.c new file mode 100644 index 0000000000..d637decb94 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/ComponentName.c @@ -0,0 +1,167 @@ +/** @file + UEFI Component Name(2) protocol implementation for VGA Class 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 "VgaClass.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gVgaClassComponentName = { + VgaClassComponentNameGetDriverName, + VgaClassComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gVgaClassComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) VgaClassComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) VgaClassComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVgaClassDriverNameTable[] = { + { + "eng;en", + L"VGA Class Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language 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 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 +VgaClassComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mVgaClassDriverNameTable, + DriverName, + (BOOLEAN)(This == &gVgaClassComponentName) + ); +} + +/** + 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 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + 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 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 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 +VgaClassComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.c b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.c new file mode 100644 index 0000000000..ca13989d5f --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.c @@ -0,0 +1,1288 @@ +/** @file + VGA Class Driver that managers VGA devices and produces Simple Text Output Protocol. + +Copyright (c) 2006 - 2009, Intel 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 "VgaClass.h" + +// +// EFI Driver Binding Protocol for the VGA Class Driver +// +EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding = { + VgaClassDriverBindingSupported, + VgaClassDriverBindingStart, + VgaClassDriverBindingStop, + 0xa, + NULL, + NULL +}; + +// +// Local variables +// +CHAR16 CrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; + +// +// This list is used to define the valid extend chars. +// It also provides a mapping from Unicode to PCANSI or +// ASCII. The ASCII mapping we just made up. +// +// +UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { + { + BOXDRAW_HORIZONTAL, + 0xc4, + L'-' + }, + { + BOXDRAW_VERTICAL, + 0xb3, + L'|' + }, + { + BOXDRAW_DOWN_RIGHT, + 0xda, + L'/' + }, + { + BOXDRAW_DOWN_LEFT, + 0xbf, + L'\\' + }, + { + BOXDRAW_UP_RIGHT, + 0xc0, + L'\\' + }, + { + BOXDRAW_UP_LEFT, + 0xd9, + L'/' + }, + { + BOXDRAW_VERTICAL_RIGHT, + 0xc3, + L'|' + }, + { + BOXDRAW_VERTICAL_LEFT, + 0xb4, + L'|' + }, + { + BOXDRAW_DOWN_HORIZONTAL, + 0xc2, + L'+' + }, + { + BOXDRAW_UP_HORIZONTAL, + 0xc1, + L'+' + }, + { + BOXDRAW_VERTICAL_HORIZONTAL, + 0xc5, + L'+' + }, + { + BOXDRAW_DOUBLE_HORIZONTAL, + 0xcd, + L'-' + }, + { + BOXDRAW_DOUBLE_VERTICAL, + 0xba, + L'|' + }, + { + BOXDRAW_DOWN_RIGHT_DOUBLE, + 0xd5, + L'/' + }, + { + BOXDRAW_DOWN_DOUBLE_RIGHT, + 0xd6, + L'/' + }, + { + BOXDRAW_DOUBLE_DOWN_RIGHT, + 0xc9, + L'/' + }, + { + BOXDRAW_DOWN_LEFT_DOUBLE, + 0xb8, + L'\\' + }, + { + BOXDRAW_DOWN_DOUBLE_LEFT, + 0xb7, + L'\\' + }, + { + BOXDRAW_DOUBLE_DOWN_LEFT, + 0xbb, + L'\\' + }, + { + BOXDRAW_UP_RIGHT_DOUBLE, + 0xd4, + L'\\' + }, + { + BOXDRAW_UP_DOUBLE_RIGHT, + 0xd3, + L'\\' + }, + { + BOXDRAW_DOUBLE_UP_RIGHT, + 0xc8, + L'\\' + }, + { + BOXDRAW_UP_LEFT_DOUBLE, + 0xbe, + L'/' + }, + { + BOXDRAW_UP_DOUBLE_LEFT, + 0xbd, + L'/' + }, + { + BOXDRAW_DOUBLE_UP_LEFT, + 0xbc, + L'/' + }, + { + BOXDRAW_VERTICAL_RIGHT_DOUBLE, + 0xc6, + L'|' + }, + { + BOXDRAW_VERTICAL_DOUBLE_RIGHT, + 0xc7, + L'|' + }, + { + BOXDRAW_DOUBLE_VERTICAL_RIGHT, + 0xcc, + L'|' + }, + { + BOXDRAW_VERTICAL_LEFT_DOUBLE, + 0xb5, + L'|' + }, + { + BOXDRAW_VERTICAL_DOUBLE_LEFT, + 0xb6, + L'|' + }, + { + BOXDRAW_DOUBLE_VERTICAL_LEFT, + 0xb9, + L'|' + }, + { + BOXDRAW_DOWN_HORIZONTAL_DOUBLE, + 0xd1, + L'+' + }, + { + BOXDRAW_DOWN_DOUBLE_HORIZONTAL, + 0xd2, + L'+' + }, + { + BOXDRAW_DOUBLE_DOWN_HORIZONTAL, + 0xcb, + L'+' + }, + { + BOXDRAW_UP_HORIZONTAL_DOUBLE, + 0xcf, + L'+' + }, + { + BOXDRAW_UP_DOUBLE_HORIZONTAL, + 0xd0, + L'+' + }, + { + BOXDRAW_DOUBLE_UP_HORIZONTAL, + 0xca, + L'+' + }, + { + BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, + 0xd8, + L'+' + }, + { + BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, + 0xd7, + L'+' + }, + { + BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, + 0xce, + L'+' + }, + + { + BLOCKELEMENT_FULL_BLOCK, + 0xdb, + L'*' + }, + { + BLOCKELEMENT_LIGHT_SHADE, + 0xb0, + L'+' + }, + + { + GEOMETRICSHAPE_UP_TRIANGLE, + 0x1e, + L'^' + }, + { + GEOMETRICSHAPE_RIGHT_TRIANGLE, + 0x10, + L'>' + }, + { + GEOMETRICSHAPE_DOWN_TRIANGLE, + 0x1f, + L'v' + }, + { + GEOMETRICSHAPE_LEFT_TRIANGLE, + 0x11, + L'<' + }, + + { + ARROW_LEFT, + 0x3c, + L'<' + }, + + { + ARROW_UP, + 0x18, + L'^' + }, + + { + ARROW_RIGHT, + 0x3e, + L'>' + }, + + { + ARROW_DOWN, + 0x19, + L'v' + }, + + { + 0x0000, + 0x00, + 0x00 + } +}; + +/** + Entrypoint of this VGA Class Driver. + + This function is the entrypoint of this VGA Class Driver. It installs Driver Binding + Protocols together with Component Name Protocols. + + @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. + +**/ +EFI_STATUS +EFIAPI +InitializeVgaClass( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gVgaClassDriverBinding, + ImageHandle, + &gVgaClassComponentName, + &gVgaClassComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Internal worker function to program CRTC register via PCI I/O Protocol. + + @param VgaClassDev device instance object + @param Address Address of register to write + @param Data Data to write to register. + +**/ +VOID +WriteCrtc ( + IN VGA_CLASS_DEV *VgaClassDev, + IN UINT16 Address, + IN UINT8 Data + ) +{ + VgaClassDev->PciIo->Io.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthUint8, + VgaClassDev->VgaMiniPort->CrtcAddressRegisterBar, + VgaClassDev->VgaMiniPort->CrtcAddressRegisterOffset, + 1, + &Address + ); + + VgaClassDev->PciIo->Io.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthUint8, + VgaClassDev->VgaMiniPort->CrtcDataRegisterBar, + VgaClassDev->VgaMiniPort->CrtcDataRegisterOffset, + 1, + &Data + ); +} + +/** + Internal worker function to set cursor's position to VgaClass device + + @param VgaClassDev Private data structure for device instance. + @param Column Colomn of position to set cursor to. + @param Row Row of position to set cursor to. + @param MaxColumn Max value of column. + +**/ +VOID +SetVideoCursorPosition ( + IN VGA_CLASS_DEV *VgaClassDev, + IN UINTN Column, + IN UINTN Row, + IN UINTN MaxColumn + ) +{ + Column = Column & 0xff; + Row = Row & 0xff; + MaxColumn = MaxColumn & 0xff; + + WriteCrtc ( + VgaClassDev, + CRTC_CURSOR_LOCATION_HIGH, + (UINT8) ((Row * MaxColumn + Column) >> 8) + ); + WriteCrtc ( + VgaClassDev, + CRTC_CURSOR_LOCATION_LOW, + (UINT8) ((Row * MaxColumn + Column) & 0xff) + ); +} + +/** + Internal worker function to detect if a Unicode char is for Box Drawing text graphics. + + @param Graphic Unicode char to test. + @param PcAnsi Pointer to PCANSI equivalent of Graphic for output. + If NULL, then PCANSI value is not returned. + @param Ascii Pointer to ASCII equivalent of Graphic for output. + If NULL, then ASCII value is not returned. + + @retval TRUE Gpaphic is a supported Unicode Box Drawing character. + @retval FALSE Gpaphic is not a supported Unicode Box Drawing character. + +**/ +BOOLEAN +LibIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ) +{ + UNICODE_TO_CHAR *Table; + + // + // Unicode drawing code charts are all in the 0x25xx range, arrows are 0x21xx. + // So first filter out values not in these 2 ranges. + // + if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { + return FALSE; + } + + // + // Search UnicodeToPcAnsiOrAscii table for matching entry. + // + for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { + if (Graphic == Table->Unicode) { + if (PcAnsi != NULL) { + *PcAnsi = Table->PcAnsi; + } + + if (Ascii != NULL) { + *Ascii = Table->Ascii; + } + + return TRUE; + } + } + + // + // If value is not found in UnicodeToPcAnsiOrAscii table, then return FALSE. + // + return FALSE; +} + +/** + Internal worker function to check whether input value is an ASCII char. + + @param Char Character to check. + + @retval TRUE Input value is an ASCII char. + @retval FALSE Input value is not an ASCII char. + +**/ +BOOLEAN +IsValidAscii ( + IN CHAR16 Char + ) +{ + if ((Char >= 0x20) && (Char <= 0x7f)) { + return TRUE; + } + + return FALSE; +} + +/** + Internal worker function to check whether input value is a unicode control char. + + @param Char Character to check. + + @retval TRUE Input value is a unicode control char. + @retval FALSE Input value is not a unicode control char. + +**/ +BOOLEAN +IsValidEfiCntlChar ( + IN CHAR16 Char + ) +{ + if (Char == CHAR_NULL || Char == CHAR_BACKSPACE || Char == CHAR_LINEFEED || Char == CHAR_CARRIAGE_RETURN) { + return TRUE; + } + + return FALSE; +} + +/** + Tests to see if this driver supports a given controller. + + This function implments EFI_DRIVER_BINDING_PROTOCOL.Supported(). + It Checks if this driver supports the controller specified. Any Controller + with VgaMiniPort Protocol and Pci I/O protocol can be supported. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @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 EFI_ALREADY_STARTED This driver is already running on this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +VgaClassDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + + // + // Checks if Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return Status; +} + +/** + Starts the device controller. + + This function implments EFI_DRIVER_BINDING_PROTOCOL.Start(). + It starts the device specified by Controller with the driver based on PCI I/O Protocol + and VgaMiniPort Protocol. It creates context for device instance and install EFI_SIMPLE_TEXT_OUT_PROTOCOL. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @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 The device was started. + @retval other Fail to start the device. + +**/ +EFI_STATUS +EFIAPI +VgaClassDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + EFI_PCI_IO_PROTOCOL *PciIo; + VGA_CLASS_DEV *VgaClassPrivate; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Report that VGA Class driver is being enabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE, + DevicePath + ); + + // + // Open the PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the VGA Mini Port Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + (VOID **) &VgaMiniPort, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate the private device structure + // + VgaClassPrivate = AllocateZeroPool (sizeof (VGA_CLASS_DEV)); + ASSERT (VgaClassPrivate != NULL); + + // + // Initialize the private device structure + // + VgaClassPrivate->Signature = VGA_CLASS_DEV_SIGNATURE; + VgaClassPrivate->Handle = Controller; + VgaClassPrivate->VgaMiniPort = VgaMiniPort; + VgaClassPrivate->PciIo = PciIo; + + VgaClassPrivate->SimpleTextOut.Reset = VgaClassReset; + VgaClassPrivate->SimpleTextOut.OutputString = VgaClassOutputString; + VgaClassPrivate->SimpleTextOut.TestString = VgaClassTestString; + VgaClassPrivate->SimpleTextOut.ClearScreen = VgaClassClearScreen; + VgaClassPrivate->SimpleTextOut.SetAttribute = VgaClassSetAttribute; + VgaClassPrivate->SimpleTextOut.SetCursorPosition = VgaClassSetCursorPosition; + VgaClassPrivate->SimpleTextOut.EnableCursor = VgaClassEnableCursor; + VgaClassPrivate->SimpleTextOut.QueryMode = VgaClassQueryMode; + VgaClassPrivate->SimpleTextOut.SetMode = VgaClassSetMode; + + VgaClassPrivate->SimpleTextOut.Mode = &VgaClassPrivate->SimpleTextOutputMode; + VgaClassPrivate->SimpleTextOutputMode.MaxMode = VgaMiniPort->MaxMode; + VgaClassPrivate->DevicePath = DevicePath; + + // + // Initialize the VGA device. + // + Status = VgaClassPrivate->SimpleTextOut.SetAttribute ( + &VgaClassPrivate->SimpleTextOut, + EFI_TEXT_ATTR (EFI_WHITE, EFI_BLACK) + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = VgaClassPrivate->SimpleTextOut.Reset ( + &VgaClassPrivate->SimpleTextOut, + FALSE + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = VgaClassPrivate->SimpleTextOut.EnableCursor ( + &VgaClassPrivate->SimpleTextOut, + TRUE + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextOutProtocolGuid, + &VgaClassPrivate->SimpleTextOut, + NULL + ); + + return Status; + +ErrorExit: + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + DevicePath + ); + + return Status; + +} + +/** + Starts the device controller. + + This function implments EFI_DRIVER_BINDING_PROTOCOL.Stop(). + It stops this driver on Controller. Support stoping any child handles + created by this driver. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param ControllerHandle A handle to the device being stopped. + @param NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param ChildHandleBuffer An array of child handles to be freed. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +VgaClassDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; + VGA_CLASS_DEV *VgaClassPrivate; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOut, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (SimpleTextOut); + + // + // Report that VGA Class driver is being disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE, + VgaClassPrivate->DevicePath + ); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + &VgaClassPrivate->SimpleTextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Release PCI I/O and VGA Mini Port Protocols on the controller handle. + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + FreePool (VgaClassPrivate); + + return EFI_SUCCESS; +} + +/** + Resets the text output device hardware. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset(). + It resets the text output device hardware. The cursor position is set to (0, 0), + and the screen is cleared to the default background color for the output device. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param ExtendedVerification Indicates that the driver may perform a more exhaustive + verification 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 +VgaClassReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassPrivate; + + VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (This); + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_RESET, + VgaClassPrivate->DevicePath + ); + + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + + Status = This->SetMode (This, 0); + if (EFI_ERROR (Status)) { + return Status; + } + + return This->ClearScreen (This); +} + +/** + Writes a Unicode string to the output device. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString(). + It writes a Unicode string to the output device. This is the most basic output mechanism + on an output device. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param String The Null-terminated Unicode string to be displayed on the output device(s). + + @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 +VgaClassOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ) +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassDev; + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + UINTN MaxColumn; + UINTN MaxRow; + UINT32 VideoChar; + CHAR8 GraphicChar; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + Mode = This->Mode; + + Status = This->QueryMode ( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Parse each character of the string to output + // + for (; *String != CHAR_NULL; String++) { + + switch (*String) { + case CHAR_BACKSPACE: + if (Mode->CursorColumn > 0) { + Mode->CursorColumn--; + } + break; + + case CHAR_LINEFEED: + if (Mode->CursorRow == (INT32) (MaxRow - 1)) { + // + // Scroll the screen by copying the contents + // of the VGA display up one line + // + VgaClassDev->PciIo->CopyMem ( + VgaClassDev->PciIo, + EfiPciIoWidthUint32, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset + MaxColumn * 2, + ((MaxRow - 1) * MaxColumn) >> 1 + ); + + // + // Print Blank Line of spaces with the current color attributes + // + VideoChar = (Mode->Attribute << 8) | ' '; + VideoChar = (VideoChar << 16) | VideoChar; + VgaClassDev->PciIo->Mem.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthFillUint32, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset + (MaxRow - 1) * MaxColumn * 2, + MaxColumn >> 1, + &VideoChar + ); + } + + if (Mode->CursorRow < (INT32) (MaxRow - 1)) { + Mode->CursorRow++; + } + break; + + case CHAR_CARRIAGE_RETURN: + Mode->CursorColumn = 0; + break; + + default: + if (!LibIsValidTextGraphics (*String, &GraphicChar, NULL)) { + // + // If this character is not ,Box Drawing text graphics, then convert it to ASCII. + // + GraphicChar = (CHAR8) *String; + if (!IsValidAscii (GraphicChar)) { + // + // If not valid ASCII char, convert it to "?" + // + GraphicChar = '?'; + } + } + + VideoChar = (Mode->Attribute << 8) | GraphicChar; + VgaClassDev->PciIo->Mem.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthUint16, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset + ((Mode->CursorRow * MaxColumn + Mode->CursorColumn) * 2), + 1, + &VideoChar + ); + + if (Mode->CursorColumn >= (INT32) (MaxColumn - 1)) { + This->OutputString (This, CrLfString); + } else { + Mode->CursorColumn++; + } + break; + } + } + + SetVideoCursorPosition ( + VgaClassDev, + (UINTN) Mode->CursorColumn, + (UINTN) Mode->CursorRow, + MaxColumn + ); + + return EFI_SUCCESS; +} + +/** + Verifies that all characters in a Unicode string can be output to the target device. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString(). + It verifies that all characters in a Unicode string can be output to the target device. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param String 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 +VgaClassTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ) +{ + while (*String != CHAR_NULL) { + if (!(IsValidAscii (*String) || IsValidEfiCntlChar (*String) || LibIsValidTextGraphics (*String, NULL, NULL))) { + return EFI_UNSUPPORTED; + } + + String++; + } + + return EFI_SUCCESS; +} + +/** + Clears the output device(s) display to the currently selected background color. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen(). + The ClearScreen() function clears the output device(s) display to the currently + selected background color. The cursor position is set to (0, 0). + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + + @retval EFI_SUCESS 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 +VgaClassClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassDev; + UINTN MaxRow; + UINTN MaxColumn; + UINT32 VideoChar; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + + Status = This->QueryMode ( + This, + This->Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return Status; + } + + VideoChar = (This->Mode->Attribute << 8) | ' '; + VideoChar = (VideoChar << 16) | VideoChar; + VgaClassDev->PciIo->Mem.Write ( + VgaClassDev->PciIo, + EfiPciIoWidthFillUint32, + VgaClassDev->VgaMiniPort->VgaMemoryBar, + VgaClassDev->VgaMiniPort->VgaMemoryOffset, + (MaxRow * MaxColumn) >> 1, + &VideoChar + ); + + This->SetCursorPosition (This, 0, 0); + + return EFI_SUCCESS; +} + +/** + Sets the background and foreground colors for theOutputString() and ClearScreen() functions. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). + It sets the background and foreground colors for the OutputString() and ClearScreen() functions. + The color mask can be set even when the device is in an invalid text mode. + Devices supporting a different number of text colors are required to emulate the above colors + to the best of the device's capabilities. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param Attribute The attribute to set. + Bits 0..3 are the foreground color, + and bits 4..6 are the background color. + + @retval EFI_SUCCESS The requested attributes were set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + +**/ +EFI_STATUS +EFIAPI +VgaClassSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +{ + if (Attribute <= EFI_MAX_ATTRIBUTE) { + This->Mode->Attribute = (INT32) Attribute; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + +/** + Sets the current coordinates of the cursor position. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition(). + It sets the current coordinates of the cursor position. + The upper left corner of the screen is defined as coordinate (0, 0). + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param Column Column of position to set the cursor to. + @param Row Row of position to set the cursor to. + + @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 +VgaClassSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +{ + EFI_STATUS Status; + VGA_CLASS_DEV *VgaClassDev; + UINTN MaxColumn; + UINTN MaxRow; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + + Status = This->QueryMode ( + This, + This->Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Column >= MaxColumn || Row >= MaxRow) { + return EFI_UNSUPPORTED; + } + + SetVideoCursorPosition (VgaClassDev, Column, Row, MaxColumn); + + This->Mode->CursorColumn = (INT32) Column; + This->Mode->CursorRow = (INT32) Row; + + return EFI_SUCCESS; +} + +/** + Makes the cursor visible or invisible. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.EnableCursor(). + It makes the cursor visible or invisible. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param Visible If TRUE, the cursor is set to be visible. + If FALSE, the cursor is set to be invisible. + + @retval EFI_SUCESS 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 does not support visibility control of the cursor. + +**/ +EFI_STATUS +EFIAPI +VgaClassEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +{ + VGA_CLASS_DEV *VgaClassDev; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + if (Visible) { + if (This->Mode->Mode == 1) { + // + // 80 * 50 + // + WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x06); + WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x07); + } else { + // + // 80 * 25 + // + WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x0e); + WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x0f); + } + } else { + WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x20); + } + + This->Mode->CursorVisible = Visible; + return EFI_SUCCESS; +} + +/** + Returns information for an available text mode that the output device(s) supports. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). + It returns information for an available text mode that the output device(s) supports. + It is required that all output devices support at least 80x25 text mode. This mode is defined to be mode 0. + If the output devices support 80x50, that is defined to be mode 1. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param ModeNumber The mode number to return information on. + @param Columns Columen in current mode number + @param Rows Row in current mode number. + + @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 +VgaClassQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +{ + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + *Columns = 0; + *Rows = 0; + return EFI_UNSUPPORTED; + } + + switch (ModeNumber) { + case 0: + *Columns = 80; + *Rows = 25; + break; + + case 1: + *Columns = 80; + *Rows = 50; + break; + + default: + *Columns = 0; + *Rows = 0; + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Sets the output device(s) to a specified mode. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). + It sets the output device(s) to the requested mode. + On success the device is in the geometry for the requested mode, + and the device has been cleared to the current background color with the cursor at (0,0). + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param ModeNumber The text mode 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 +VgaClassSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + VGA_CLASS_DEV *VgaClassDev; + + VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + This->ClearScreen (This); + + This->Mode->Mode = (INT32) ModeNumber; + + return VgaClassDev->VgaMiniPort->SetMode (VgaClassDev->VgaMiniPort, ModeNumber); +} diff --git a/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.h b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.h new file mode 100644 index 0000000000..5cfa704001 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.h @@ -0,0 +1,484 @@ +/** @file + Internal include file of the VGA Class 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. + +**/ + + +#ifndef _VGA_CLASS_H__ +#define _VGA_CLASS_H__ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gVgaClassComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gVgaClassComponentName2; + + +// +// Structure for tuple containing mapping among uniocde, PC Ansi and ASCII code. +// +typedef struct { + CHAR16 Unicode; + CHAR8 PcAnsi; + CHAR8 Ascii; +} UNICODE_TO_CHAR; + +// +// VGA specific registers +// +#define CRTC_CURSOR_START 0xA +#define CRTC_CURSOR_END 0xB + +#define CRTC_CURSOR_LOCATION_HIGH 0xE +#define CRTC_CURSOR_LOCATION_LOW 0xF + +#define EFI_MAX_ATTRIBUTE 0x7f + +// +// VGA Class Device Structure +// +#define VGA_CLASS_DEV_SIGNATURE SIGNATURE_32 ('V', 'G', 'A', 'C') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOut; + EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} VGA_CLASS_DEV; + +#define VGA_CLASS_DEV_FROM_THIS(a) CR (a, VGA_CLASS_DEV, SimpleTextOut, VGA_CLASS_DEV_SIGNATURE) + +// +// Driver Binding Protocol functions +// + +/** + Tests to see if this driver supports a given controller. + + This function implments EFI_DRIVER_BINDING_PROTOCOL.Supported(). + It Checks if this driver supports the controller specified. Any Controller + with VgaMiniPort Protocol and Pci I/O protocol can be supported. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @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 EFI_ALREADY_STARTED This driver is already running on this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +VgaClassDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Starts the device controller. + + This function implments EFI_DRIVER_BINDING_PROTOCOL.Start(). + It starts the device specified by Controller with the driver based on PCI I/O Protocol + and VgaMiniPort Protocol. It creates context for device instance and install EFI_SIMPLE_TEXT_OUT_PROTOCOL. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @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 The device was started. + @retval other Fail to start the device. + +**/ +EFI_STATUS +EFIAPI +VgaClassDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Starts the device controller. + + This function implments EFI_DRIVER_BINDING_PROTOCOL.Stop(). + It stops this driver on Controller. Support stoping any child handles + created by this driver. + + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param ControllerHandle A handle to the device being stopped. + @param NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param ChildHandleBuffer An array of child handles to be freed. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +VgaClassDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ); + +// +// EFI Component Name Functions +// + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language 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 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 +VgaClassComponentNameGetDriverName ( + 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 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + 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 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 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 +VgaClassComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// Simple Text Output Protocol functions +// +/** + Resets the text output device hardware. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset(). + It resets the text output device hardware. The cursor position is set to (0, 0), + and the screen is cleared to the default background color for the output device. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param ExtendedVerification Indicates that the driver may perform a more exhaustive + verification 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 +VgaClassReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Writes a Unicode string to the output device. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString(). + It writes a Unicode string to the output device. This is the most basic output mechanism + on an output device. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param String The Null-terminated Unicode string to be displayed on the output device(s). + + @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 +VgaClassOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +/** + Verifies that all characters in a Unicode string can be output to the target device. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString(). + It verifies that all characters in a Unicode string can be output to the target device. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param String 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 +VgaClassTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +/** + Clears the output device(s) display to the currently selected background color. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen(). + The ClearScreen() function clears the output device(s) display to the currently + selected background color. The cursor position is set to (0, 0). + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + + @retval EFI_SUCESS 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 +VgaClassClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +/** + Sets the background and foreground colors for theOutputString() and ClearScreen() functions. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). + It sets the background and foreground colors for the OutputString() and ClearScreen() functions. + The color mask can be set even when the device is in an invalid text mode. + Devices supporting a different number of text colors are required to emulate the above colors + to the best of the device's capabilities. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param Attribute The attribute to set. + Bits 0..3 are the foreground color, + and bits 4..6 are the background color. + + @retval EFI_SUCCESS The requested attributes were set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + +**/ +EFI_STATUS +EFIAPI +VgaClassSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ); + +/** + Sets the current coordinates of the cursor position. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition(). + It sets the current coordinates of the cursor position. + The upper left corner of the screen is defined as coordinate (0, 0). + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param Column Column of position to set the cursor to. + @param Row Row of position to set the cursor to. + + @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 +VgaClassSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + +/** + Makes the cursor visible or invisible. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.EnableCursor(). + It makes the cursor visible or invisible. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param Visible If TRUE, the cursor is set to be visible. + If FALSE, the cursor is set to be invisible. + + @retval EFI_SUCESS 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 does not support visibility control of the cursor. + +**/ +EFI_STATUS +EFIAPI +VgaClassEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ); + +/** + Returns information for an available text mode that the output device(s) supports. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). + It returns information for an available text mode that the output device(s) supports. + It is required that all output devices support at least 80x25 text mode. This mode is defined to be mode 0. + If the output devices support 80x50, that is defined to be mode 1. + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param ModeNumber The mode number to return information on. + @param Columns Columen in current mode number + @param Rows Row in current mode number. + + @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 +VgaClassQueryMode ( + 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. + + This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). + It sets the output device(s) to the requested mode. + On success the device is in the geometry for the requested mode, + and the device has been cleared to the current background color with the cursor at (0,0). + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param ModeNumber The text mode 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 +VgaClassSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf new file mode 100644 index 0000000000..2faba9d6f7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf @@ -0,0 +1,64 @@ +## @file +# VGA Class Driver that managers VGA devices and produces Simple Text Output 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 +# 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 = VgaClassDxe + MODULE_UNI_FILE = VgaClassDxe.uni + FILE_GUID = BF89F10D-B205-474f-96E3-7A7BB1B4A407 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeVgaClass + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gVgaClassDriverBinding +# COMPONENT_NAME = gVgaClassComponentName +# COMPONENT_NAME2 = gVgaClassComponentName2 +# + +[Sources] + ComponentName.c + VgaClass.h + VgaClass.c + + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +[LibraryClasses] + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + UefiLib + UefiDriverEntryPoint + DebugLib + + +[Protocols] + gEfiSimpleTextOutProtocolGuid ## BY_START + gEfiVgaMiniPortProtocolGuid ## TO_START + gEfiPciIoProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## TO_START + +[UserExtensions.TianoCore."ExtraFiles"] + VgaClassDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.uni b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.uni new file mode 100644 index 0000000000..23bb5c3693 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxeExtra.uni new file mode 100644 index 0000000000..4c0cda97c0 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c new file mode 100644 index 0000000000..e48b6382ff --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c @@ -0,0 +1,536 @@ +/** @file + Uses the services of the I/O Library to produce the CPU I/O Protocol + +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 "CpuIo.h" + +// +// Handle for the CPU I/O Protocol +// +EFI_HANDLE mHandle = NULL; + +// +// CPU I/O Protocol inatance +// +EFI_CPU_IO_PROTOCOL mCpuIo = { + { + CpuMemoryServiceRead, + CpuMemoryServiceWrite + }, + { + CpuIoServiceRead, + CpuIoServiceWrite + } +}; + +// +// Lookup table for increment values based on transfer widths +// +UINT8 mInStride[] = { + 1, // EfiCpuIoWidthUint8 + 2, // EfiCpuIoWidthUint16 + 4, // EfiCpuIoWidthUint32 + 8, // EfiCpuIoWidthUint64 + 0, // EfiCpuIoWidthFifoUint8 + 0, // EfiCpuIoWidthFifoUint16 + 0, // EfiCpuIoWidthFifoUint32 + 0, // EfiCpuIoWidthFifoUint64 + 1, // EfiCpuIoWidthFillUint8 + 2, // EfiCpuIoWidthFillUint16 + 4, // EfiCpuIoWidthFillUint32 + 8 // EfiCpuIoWidthFillUint64 +}; + +// +// Lookup table for increment values based on transfer widths +// +UINT8 mOutStride[] = { + 1, // EfiCpuIoWidthUint8 + 2, // EfiCpuIoWidthUint16 + 4, // EfiCpuIoWidthUint32 + 8, // EfiCpuIoWidthUint64 + 1, // EfiCpuIoWidthFifoUint8 + 2, // EfiCpuIoWidthFifoUint16 + 4, // EfiCpuIoWidthFifoUint32 + 8, // EfiCpuIoWidthFifoUint64 + 0, // EfiCpuIoWidthFillUint8 + 0, // EfiCpuIoWidthFillUint16 + 0, // EfiCpuIoWidthFillUint32 + 0 // EfiCpuIoWidthFillUint64 +}; + +/** + Check parameters to a CPU I/O Protocol service request. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The parameters for this request pass the checks. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +CpuIoCheckParameter ( + IN BOOLEAN MmioOperation, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT64 MaxCount; + UINT64 Limit; + + // + // Check to see if Buffer is NULL + // + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Width is in the valid range + // + if ((UINT32)Width >= EfiCpuIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + // + // For FIFO type, the target address won't increase during the access, + // so treat Count as 1 + // + if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) { + Count = 1; + } + + // + // Check to see if Width is in the valid range for I/O Port operations + // + Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Address is aligned + // + if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) { + return EFI_UNSUPPORTED; + } + + // + // Check to see if any address associated with this transfer exceeds the maximum + // allowed address. The maximum address implied by the parameters passed in is + // Address + Size * Count. If the following condition is met, then the transfer + // is not supported. + // + // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1 + // + // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count + // can also be the maximum integer value supported by the CPU, this range + // check must be adjusted to avoid all overflow conditions. + // + // The following form of the range check is equivalent but assumes that + // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1). + // + Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS); + if (Count == 0) { + if (Address > Limit) { + return EFI_UNSUPPORTED; + } + } else { + MaxCount = RShiftU64 (Limit, Width); + if (MaxCount < (Count - 1)) { + return EFI_UNSUPPORTED; + } + if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { + return EFI_UNSUPPORTED; + } + } + + // + // Check to see if Buffer is aligned + // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.) + // + if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Reads memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuMemoryServiceRead ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride = mInStride[Width]; + OutStride = mOutStride[Width]; + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { + if (OperationWidth == EfiCpuIoWidthUint8) { + *Uint8Buffer = MmioRead8 ((UINTN)Address); + } else if (OperationWidth == EfiCpuIoWidthUint16) { + *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); + } else if (OperationWidth == EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); + } else if (OperationWidth == EfiCpuIoWidthUint64) { + *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address); + } + } + return EFI_SUCCESS; +} + +/** + Writes memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuMemoryServiceWrite ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride = mInStride[Width]; + OutStride = mOutStride[Width]; + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { + if (OperationWidth == EfiCpuIoWidthUint8) { + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + } else if (OperationWidth == EfiCpuIoWidthUint16) { + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + } else if (OperationWidth == EfiCpuIoWidthUint32) { + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } else if (OperationWidth == EfiCpuIoWidthUint64) { + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); + } + } + return EFI_SUCCESS; +} + +/** + Reads I/O registers. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuIoServiceRead ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride = mInStride[Width]; + OutStride = mOutStride[Width]; + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { + if (OperationWidth == EfiCpuIoWidthUint8) { + *Uint8Buffer = IoRead8 ((UINTN)Address); + } else if (OperationWidth == EfiCpuIoWidthUint16) { + *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address); + } else if (OperationWidth == EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address); + } + } + + return EFI_SUCCESS; +} + +/** + Write I/O registers. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuIoServiceWrite ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + // + // Make sure the parameters are valid + // + Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride = mInStride[Width]; + OutStride = mOutStride[Width]; + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { + if (OperationWidth == EfiCpuIoWidthUint8) { + IoWrite8 ((UINTN)Address, *Uint8Buffer); + } else if (OperationWidth == EfiCpuIoWidthUint16) { + IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + } else if (OperationWidth == EfiCpuIoWidthUint32) { + IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } + } + + return EFI_SUCCESS; +} + +/** + The user Entry Point for module CpuIo. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +CpuIoInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIoProtocolGuid); + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiCpuIoProtocolGuid, &mCpuIo, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h new file mode 100644 index 0000000000..6eba9c09e7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h @@ -0,0 +1,226 @@ +/** @file + Internal include file of CPU I/O DXE Driver. + + Copyright (c) 2004 - 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 __CPU_IO_DXE_H__ +#define __CPU_IO_DXE_H__ + + +#include + +#include + +#include +#include +#include +#include + +#define MAX_IO_PORT_ADDRESS 0xFFFF + +/** + Reads memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuMemoryServiceRead ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Writes memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuMemoryServiceWrite ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Reads I/O registers. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuIoServiceRead ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Write I/O registers. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuIoServiceWrite ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf new file mode 100644 index 0000000000..368fa75bbb --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf @@ -0,0 +1,51 @@ +## @file +# Module that produces the Framework CPU I/O Protocol using the services of the I/O Library +# +# 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 +# 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 = CpuIoDxe + MODULE_UNI_FILE = CpuIoDxe.uni + FILE_GUID = BAE7599F-3C6B-43b7-BDF0-9CE07AA91AA6 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = CpuIoInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + CpuIo.c + CpuIo.h + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + BaseLib + DebugLib + IoLib + UefiBootServicesTableLib + +[Protocols] + gEfiCpuIoProtocolGuid ## PRODUCES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + CpuIoDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.uni b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.uni new file mode 100644 index 0000000000..68fa4ec31a Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxeExtra.uni new file mode 100644 index 0000000000..6bc7525414 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c new file mode 100644 index 0000000000..91f7c7ecf9 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c @@ -0,0 +1,587 @@ +/** @file + This code produces the Data Hub protocol. It preloads the data hub + with status information copied in from PEI HOBs. + +Copyright (c) 2006 - 2015, Intel 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 "DataHub.h" + +// +// Since this driver will only ever produce one instance of the Logging Hub +// protocol you are not required to dynamically allocate the PrivateData. +// +DATA_HUB_INSTANCE mPrivateData; + +/** + Log data record into the data logging hub + + @param This Protocol instance structure + @param DataRecordGuid GUID that defines record contents + @param ProducerName GUID that defines the name of the producer of the data + @param DataRecordClass Class that defines generic record type + @param RawData Data Log record as defined by DataRecordGuid + @param RawDataSize Size of Data Log data in bytes + + @retval EFI_SUCCESS If data was logged + @retval EFI_OUT_OF_RESOURCES If data was not logged due to lack of system + resources. +**/ +EFI_STATUS +EFIAPI +DataHubLogData ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_GUID *DataRecordGuid, + IN EFI_GUID *ProducerName, + IN UINT64 DataRecordClass, + IN VOID *RawData, + IN UINT32 RawDataSize + ) +{ + EFI_STATUS Status; + DATA_HUB_INSTANCE *Private; + EFI_DATA_ENTRY *LogEntry; + UINT32 TotalSize; + UINT32 RecordSize; + EFI_DATA_RECORD_HEADER *Record; + VOID *Raw; + DATA_HUB_FILTER_DRIVER *FilterEntry; + LIST_ENTRY *Link; + LIST_ENTRY *Head; + EFI_TIME LogTime; + + Private = DATA_HUB_INSTANCE_FROM_THIS (This); + + // + // Combine the storage for the internal structs and a copy of the log record. + // Record follows PrivateLogEntry. The consumer will be returned a pointer + // to Record so we don't what it to be the thing that was allocated from + // pool, so the consumer can't free an data record by mistake. + // + RecordSize = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize; + TotalSize = sizeof (EFI_DATA_ENTRY) + RecordSize; + + // + // First try to get log time at TPL level <= TPL_CALLBACK. + // + ZeroMem (&LogTime, sizeof (LogTime)); + if (EfiGetCurrentTpl() <= TPL_CALLBACK) { + gRT->GetTime (&LogTime, NULL); + } + + // + // The Logging action is the critical section, so it is locked. + // The MTC asignment & update and logging must be an + // atomic operation, so use the lock. + // + Status = EfiAcquireLockOrFail (&Private->DataLock); + if (EFI_ERROR (Status)) { + // + // Reentrancy detected so exit! + // + return Status; + } + + LogEntry = AllocatePool (TotalSize); + + if (LogEntry == NULL) { + EfiReleaseLock (&Private->DataLock); + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (LogEntry, TotalSize); + + Record = (EFI_DATA_RECORD_HEADER *) (LogEntry + 1); + Raw = (VOID *) (Record + 1); + + // + // Build Standard Log Header + // + Record->Version = EFI_DATA_RECORD_HEADER_VERSION; + Record->HeaderSize = (UINT16) sizeof (EFI_DATA_RECORD_HEADER); + Record->RecordSize = RecordSize; + CopyMem (&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID)); + CopyMem (&Record->ProducerName, ProducerName, sizeof (EFI_GUID)); + Record->DataRecordClass = DataRecordClass; + + // + // Ensure LogMonotonicCount is not zero + // + Record->LogMonotonicCount = ++Private->GlobalMonotonicCount; + + CopyMem (&Record->LogTime, &LogTime, sizeof (LogTime)); + + // + // Insert log into the internal linked list. + // + LogEntry->Signature = EFI_DATA_ENTRY_SIGNATURE; + LogEntry->Record = Record; + LogEntry->RecordSize = sizeof (EFI_DATA_ENTRY) + RawDataSize; + InsertTailList (&Private->DataListHead, &LogEntry->Link); + + CopyMem (Raw, RawData, RawDataSize); + + EfiReleaseLock (&Private->DataLock); + + // + // Send Signal to all the filter drivers which are interested + // in the record's class and guid. + // + Head = &Private->FilterDriverListHead; + for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) { + FilterEntry = FILTER_ENTRY_FROM_LINK (Link); + if (((FilterEntry->ClassFilter & DataRecordClass) != 0) && + (CompareGuid (&FilterEntry->FilterDataRecordGuid, &gZeroGuid) || + CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid))) { + gBS->SignalEvent (FilterEntry->Event); + } + } + + return EFI_SUCCESS; +} + +/** + Search the Head doubly linked list for the passed in MTC. Return the + matching element in Head and the MTC on the next entry. + + @param Head Head of Data Log linked list. + @param ClassFilter Only match the MTC if it is in the same Class as the + ClassFilter. + @param PtrCurrentMTC On IN contians MTC to search for. On OUT contians next + MTC in the data log list or zero if at end of the list. + + @retval EFI_DATA_LOG_ENTRY Return pointer to data log data from Head list. + @retval NULL If no data record exists. + +**/ +EFI_DATA_RECORD_HEADER * +GetNextDataRecord ( + IN LIST_ENTRY *Head, + IN UINT64 ClassFilter, + IN OUT UINT64 *PtrCurrentMTC + ) + +{ + EFI_DATA_ENTRY *LogEntry; + LIST_ENTRY *Link; + BOOLEAN ReturnFirstEntry; + EFI_DATA_RECORD_HEADER *Record; + EFI_DATA_ENTRY *NextLogEntry; + + // + // If MonotonicCount == 0 just return the first one + // + ReturnFirstEntry = (BOOLEAN) (*PtrCurrentMTC == 0); + + Record = NULL; + for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) { + LogEntry = DATA_ENTRY_FROM_LINK (Link); + if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) { + // + // Skip any entry that does not have the correct ClassFilter + // + continue; + } + + if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) { + // + // Return record to the user + // + Record = LogEntry->Record; + + // + // Calculate the next MTC value. If there is no next entry set + // MTC to zero. + // + *PtrCurrentMTC = 0; + for (Link = GetNextNode(Head, Link); Link != Head; Link = GetNextNode(Head, Link)) { + NextLogEntry = DATA_ENTRY_FROM_LINK (Link); + if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) { + // + // Return the MTC of the next thing to search for if found + // + *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount; + break; + } + } + // + // Record found exit loop and return + // + break; + } + } + + return Record; +} + +/** + Search the Head list for a EFI_DATA_HUB_FILTER_DRIVER member that + represents Event and return it. + + @param Head Pointer to head of dual linked list of EFI_DATA_HUB_FILTER_DRIVER structures. + @param Event Event to be search for in the Head list. + + @retval EFI_DATA_HUB_FILTER_DRIVER Returned if Event stored in the Head doubly linked list. + @retval NULL If Event is not in the list + +**/ +DATA_HUB_FILTER_DRIVER * +FindFilterDriverByEvent ( + IN LIST_ENTRY *Head, + IN EFI_EVENT Event + ) +{ + DATA_HUB_FILTER_DRIVER *FilterEntry; + LIST_ENTRY *Link; + + for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) { + FilterEntry = FILTER_ENTRY_FROM_LINK (Link); + if (FilterEntry->Event == Event) { + return FilterEntry; + } + } + + return NULL; +} + +/** + + Get a previously logged data record and the MonotonicCount for the next + availible Record. This allows all records or all records later + than a give MonotonicCount to be returned. If an optional FilterDriverEvent + is passed in with a MonotonicCout of zero return the first record + not yet read by the filter driver. If FilterDriverEvent is NULL and + MonotonicCount is zero return the first data record. + + @param This Pointer to the EFI_DATA_HUB_PROTOCOL instance. + @param MonotonicCount Specifies the Record to return. On input, zero means + return the first record. On output, contains the next + record to availible. Zero indicates no more records. + @param FilterDriverEvent If FilterDriverEvent is not passed in a MonotonicCount + of zero, it means to return the first data record. + If FilterDriverEvent is passed in, then a MonotonicCount + of zero means to return the first data not yet read by + FilterDriverEvent. + @param Record Returns a dynamically allocated memory buffer with a data + record that matches MonotonicCount. + + @retval EFI_SUCCESS Data was returned in Record. + @retval EFI_INVALID_PARAMETER FilterDriverEvent was passed in but does not exist. + @retval EFI_NOT_FOUND MonotonicCount does not match any data record in the + system. If a MonotonicCount of zero was passed in, then + no data records exist in the system. + @retval EFI_OUT_OF_RESOURCES Record was not returned due to lack of system resources. + +**/ +EFI_STATUS +EFIAPI +DataHubGetNextRecord ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN OUT UINT64 *MonotonicCount, + IN EFI_EVENT *FilterDriverEvent, OPTIONAL + OUT EFI_DATA_RECORD_HEADER **Record + ) +{ + DATA_HUB_INSTANCE *Private; + DATA_HUB_FILTER_DRIVER *FilterDriver; + UINT64 ClassFilter; + + Private = DATA_HUB_INSTANCE_FROM_THIS (This); + + FilterDriver = NULL; + ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG | + EFI_DATA_RECORD_CLASS_ERROR | + EFI_DATA_RECORD_CLASS_DATA | + EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + + // + // If FilterDriverEvent is NULL, then return the next record + // + if (FilterDriverEvent == NULL) { + *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); + if (*Record == NULL) { + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; + } + + // + // For events the beginning is the last unread record. This info is + // stored in the instance structure, so we must look up the event + // to get the data. + // + FilterDriver = FindFilterDriverByEvent ( + &Private->FilterDriverListHead, + *FilterDriverEvent + ); + if (FilterDriver == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Use the Class filter the event was created with. + // + ClassFilter = FilterDriver->ClassFilter; + + // + // Retrieve the next record or the first record. + // + if (*MonotonicCount != 0 || FilterDriver->GetNextMonotonicCount == 0) { + *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); + if (*Record == NULL) { + return EFI_NOT_FOUND; + } + + if (*MonotonicCount != 0) { + // + // If this was not the last record then update the count associated with the filter + // + FilterDriver->GetNextMonotonicCount = *MonotonicCount; + } else { + // + // Save the MonotonicCount of the last record which has been read + // + FilterDriver->GetNextMonotonicCount = (*Record)->LogMonotonicCount; + } + return EFI_SUCCESS; + } + + // + // This is a request to read the first record that has not been read yet. + // Set MonotoicCount to the last record successfuly read + // + *MonotonicCount = FilterDriver->GetNextMonotonicCount; + + // + // Retrieve the last record successfuly read again, but do not return it since + // it has already been returned before. + // + *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); + if (*Record == NULL) { + return EFI_NOT_FOUND; + } + + if (*MonotonicCount != 0) { + // + // Update the count associated with the filter + // + FilterDriver->GetNextMonotonicCount = *MonotonicCount; + + // + // Retrieve the record after the last record successfuly read + // + *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); + if (*Record == NULL) { + return EFI_NOT_FOUND; + } + } + + return EFI_SUCCESS; +} + +/** + This function registers the data hub filter driver that is represented + by FilterEvent. Only one instance of each FilterEvent can be registered. + After the FilterEvent is registered, it will be signaled so it can sync + with data records that have been recorded prior to the FilterEvent being + registered. + + @param This Pointer to The EFI_DATA_HUB_PROTOCOL instance. + @param FilterEvent The EFI_EVENT to signal whenever data that matches + FilterClass is logged in the system. + @param FilterTpl The maximum EFI_TPL at which FilterEvent can be + signaled. It is strongly recommended that you use the + lowest EFI_TPL possible. + @param FilterClass FilterEvent will be signaled whenever a bit in + EFI_DATA_RECORD_HEADER.DataRecordClass is also set in + FilterClass. If FilterClass is zero, no class-based + filtering will be performed. + @param FilterDataRecordGuid FilterEvent will be signaled whenever FilterDataRecordGuid + matches EFI_DATA_RECORD_HEADER.DataRecordGuid. If + FilterDataRecordGuid is NULL, then no GUID-based filtering + will be performed. + + @retval EFI_SUCCESS The filter driver event was registered. + @retval EFI_ALREADY_STARTED FilterEvent was previously registered and cannot be + registered again. + @retval EFI_OUT_OF_RESOURCES The filter driver event was not registered due to lack of + system resources. + +**/ +EFI_STATUS +EFIAPI +DataHubRegisterFilterDriver ( + IN EFI_DATA_HUB_PROTOCOL * This, + IN EFI_EVENT FilterEvent, + IN EFI_TPL FilterTpl, + IN UINT64 FilterClass, + IN EFI_GUID * FilterDataRecordGuid OPTIONAL + ) + +{ + DATA_HUB_INSTANCE *Private; + DATA_HUB_FILTER_DRIVER *FilterDriver; + + Private = DATA_HUB_INSTANCE_FROM_THIS (This); + + FilterDriver = (DATA_HUB_FILTER_DRIVER *) AllocateZeroPool (sizeof (DATA_HUB_FILTER_DRIVER)); + if (FilterDriver == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize filter driver info + // + FilterDriver->Signature = EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE; + FilterDriver->Event = FilterEvent; + FilterDriver->Tpl = FilterTpl; + FilterDriver->GetNextMonotonicCount = 0; + if (FilterClass == 0) { + FilterDriver->ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG | + EFI_DATA_RECORD_CLASS_ERROR | + EFI_DATA_RECORD_CLASS_DATA | + EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } else { + FilterDriver->ClassFilter = FilterClass; + } + + if (FilterDataRecordGuid != NULL) { + CopyMem (&FilterDriver->FilterDataRecordGuid, FilterDataRecordGuid, sizeof (EFI_GUID)); + } + // + // Search for duplicate entries + // + if (FindFilterDriverByEvent (&Private->FilterDriverListHead, FilterEvent) != NULL) { + FreePool (FilterDriver); + return EFI_ALREADY_STARTED; + } + // + // Make insertion an atomic operation with the lock. + // + EfiAcquireLock (&Private->DataLock); + InsertTailList (&Private->FilterDriverListHead, &FilterDriver->Link); + EfiReleaseLock (&Private->DataLock); + + // + // Signal the Filter driver we just loaded so they will recieve all the + // previous history. If we did not signal here we would have to wait until + // the next data was logged to get the history. In a case where no next + // data was logged we would never get synced up. + // + gBS->SignalEvent (FilterEvent); + + return EFI_SUCCESS; +} + +/** + Remove a Filter Driver, so it no longer gets called when data + information is logged. + + @param This Protocol instance structure + + @param FilterEvent Event that represents a filter driver that is to be + Unregistered. + + @retval EFI_SUCCESS If FilterEvent was unregistered + @retval EFI_NOT_FOUND If FilterEvent does not exist +**/ +EFI_STATUS +EFIAPI +DataHubUnregisterFilterDriver ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_EVENT FilterEvent + ) +{ + DATA_HUB_INSTANCE *Private; + DATA_HUB_FILTER_DRIVER *FilterDriver; + + Private = DATA_HUB_INSTANCE_FROM_THIS (This); + + // + // Search for duplicate entries + // + FilterDriver = FindFilterDriverByEvent ( + &Private->FilterDriverListHead, + FilterEvent + ); + if (FilterDriver == NULL) { + return EFI_NOT_FOUND; + } + // + // Make removal an atomic operation with the lock + // + EfiAcquireLock (&Private->DataLock); + RemoveEntryList (&FilterDriver->Link); + EfiReleaseLock (&Private->DataLock); + + return EFI_SUCCESS; +} + + + +/** + Driver's Entry point routine that install Driver to produce Data Hub protocol. + + @param ImageHandle Module's image handle + @param SystemTable Pointer of EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS Logging Hub protocol installed + @retval Other No protocol installed, unload driver. + +**/ +EFI_STATUS +EFIAPI +DataHubInstall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 HighMontonicCount; + + mPrivateData.Signature = DATA_HUB_INSTANCE_SIGNATURE; + mPrivateData.DataHub.LogData = DataHubLogData; + mPrivateData.DataHub.GetNextRecord = DataHubGetNextRecord; + mPrivateData.DataHub.RegisterFilterDriver = DataHubRegisterFilterDriver; + mPrivateData.DataHub.UnregisterFilterDriver = DataHubUnregisterFilterDriver; + + // + // Initialize Private Data in CORE_LOGGING_HUB_INSTANCE that is + // required by this protocol + // + InitializeListHead (&mPrivateData.DataListHead); + InitializeListHead (&mPrivateData.FilterDriverListHead); + + EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY); + + // + // Make sure we get a bigger MTC number on every boot! + // + Status = gRT->GetNextHighMonotonicCount (&HighMontonicCount); + if (EFI_ERROR (Status)) { + // + // if system service fails pick a sane value. + // + mPrivateData.GlobalMonotonicCount = 0; + } else { + mPrivateData.GlobalMonotonicCount = LShiftU64 ((UINT64) HighMontonicCount, 32); + } + // + // Make a new handle and install the protocol + // + mPrivateData.Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &mPrivateData.Handle, + &gEfiDataHubProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPrivateData.DataHub + ); + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.h b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.h new file mode 100644 index 0000000000..de2e3f34ff --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.h @@ -0,0 +1,131 @@ +/** @file + This code supports a the private implementation + of the Data Hub protocol + +Copyright (c) 2006 - 2015, Intel 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 _DATA_HUB_H_ +#define _DATA_HUB_H_ + + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DATA_HUB_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', 'u', 'b') +typedef struct { + UINT32 Signature; + + EFI_HANDLE Handle; + + // + // Produced protocol(s) + // + EFI_DATA_HUB_PROTOCOL DataHub; + + // + // Private Data + // + // + // Updates to GlobalMonotonicCount, LogListHead, and FilterDriverListHead + // must be locked. + // + EFI_LOCK DataLock; + + // + // Runing Monotonic Count to use for each error record. + // Increment AFTER use in an error record. + // + UINT64 GlobalMonotonicCount; + + // + // List of EFI_DATA_ENTRY structures. This is the data log! The list + // must be in assending order of LogMonotonicCount. + // + LIST_ENTRY DataListHead; + + // + // List of EFI_DATA_HUB_FILTER_DRIVER structures. Represents all + // the registered filter drivers. + // + LIST_ENTRY FilterDriverListHead; + +} DATA_HUB_INSTANCE; + +#define DATA_HUB_INSTANCE_FROM_THIS(this) CR (this, DATA_HUB_INSTANCE, DataHub, DATA_HUB_INSTANCE_SIGNATURE) + +// +// Private data structure to contain the data log. One record per +// structure. Head pointer to the list is the Log member of +// EFI_DATA_ENTRY. Record is a copy of the data passed in. +// +#define EFI_DATA_ENTRY_SIGNATURE SIGNATURE_32 ('D', 'r', 'e', 'c') +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + + EFI_DATA_RECORD_HEADER *Record; + + UINTN RecordSize; + +} EFI_DATA_ENTRY; + +#define DATA_ENTRY_FROM_LINK(link) CR (link, EFI_DATA_ENTRY, Link, EFI_DATA_ENTRY_SIGNATURE) + +// +// Private data to contain the filter driver Event and it's +// associated EFI_TPL. +// +#define EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE SIGNATURE_32 ('D', 'h', 'F', 'd') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + + // + // Store Filter Driver Event and Tpl level it can be Signaled at. + // + EFI_EVENT Event; + EFI_TPL Tpl; + + // + // Monotonic count on the get next operation for Event. + // Zero indicates get next has not been called for this event yet. + // + UINT64 GetNextMonotonicCount; + + // + // Filter driver will register what class filter should be used. + // + UINT64 ClassFilter; + + // + // Filter driver will register what record guid filter should be used. + // + EFI_GUID FilterDataRecordGuid; + +} DATA_HUB_FILTER_DRIVER; + +#define FILTER_ENTRY_FROM_LINK(link) CR (link, DATA_HUB_FILTER_DRIVER, Link, EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE) + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf new file mode 100644 index 0000000000..834c3b3148 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf @@ -0,0 +1,85 @@ +## @file +# This driver initializes and installs the Data Hub protocol. +# +# The data hub is a volatile database that is intended as the major focus for the accumulation of +# manageability data.T he hub is fed by "producers" with chunks of data in a defined format. +# Consumers may then extract the data in temporal "log" order.As an example, progress codes might +# be recorded in the data hub for future processing.Ot her data contributed to the data hub might +# include, for example, statistics on enumerated items such as memory, add-in buses, and add-in +# cards and data on errors encountered during boot (for example, the system did not boot off the +# network because the cable was not plugged in). +# Some classes of data have defined formats.For example, the amount of memory in the system is +# reported in a standard format so that consumers can be written to extract the data.O ther data is +# system specific.For example, additional detail on errors might be specific to the driver that +# discovered the error.The consumer might be a driver that tabularizes data from the data hub, +# providing a mechanism for the raw data to be made available to the OS for post-processing by +# OS-based applications. +# The intent of the data hub is for drivers that enumerate and configure parts of the system to report +# their discoveries to the data hub.This data can then be extracted by other drivers that report those +# discoveries using standard manageability interfaces such as SMBIOS and Intelligent Platform +# Management Interface (IPMI).The alternative to a data-hub-like architecture is to require all +# drivers to be aware of all reporting formats. +# For more information, please ref http://www.intel.com/technology/framework/ +# +# Copyright (c) 2006 - 2015, Intel 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 = DataHubDxe + MODULE_UNI_FILE = DataHubDxe.uni + FILE_GUID = 53BCC14F-C24F-434C-B294-8ED2D4CC1860 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DataHubInstall + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DataHub.h + DataHub.c + + +[Packages] + IntelFrameworkPkg/IntelFrameworkPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + + +[Guids] + gZeroGuid ## SOMETIMES_CONSUMES ## GUID + + +[Protocols] + gEfiDataHubProtocolGuid ## PRODUCES + + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + DataHubDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.uni b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.uni new file mode 100644 index 0000000000..2e62686103 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxeExtra.uni new file mode 100644 index 0000000000..27b2ae3bdc Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErr.c b/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErr.c new file mode 100644 index 0000000000..48522c01af --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErr.c @@ -0,0 +1,151 @@ +/** @file + Data Hub filter driver that takes DEBUG () info from Data Hub and writes it + to StdErr if it exists. + +Copyright (c) 2006 - 2009, Intel 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 + +EFI_DATA_HUB_PROTOCOL *mDataHub = NULL; + +EFI_EVENT mDataHubStdErrEvent; + +/** + Event handler registered with the Data Hub to parse EFI_DEBUG_CODE. This + handler reads the Data Hub and sends any DEBUG info to StdErr. + + @param Event The event that occured, not used + @param Context DataHub Protocol Pointer +**/ +VOID +EFIAPI +DataHubStdErrEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_DATA_RECORD_HEADER *Record; + DATA_HUB_STATUS_CODE_DATA_RECORD *DataRecord; + UINT64 Mtc; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto; + INT32 OldAttribute; + + DataHub = (EFI_DATA_HUB_PROTOCOL *) Context; + + // + // If StdErr is not yet initialized just return a DEBUG print in the BDS + // after consoles are connect will make sure data gets flushed properly + // when StdErr is availible. + // + if (gST == NULL) { + return ; + } + + if (gST->StdErr == NULL) { + return ; + } + + // + // Mtc of zero means return the next record that has not been read by the + // event handler. + // + Mtc = 0; + do { + Status = DataHub->GetNextRecord (DataHub, &Mtc, &mDataHubStdErrEvent, &Record); + if (!EFI_ERROR (Status)) { + if (CompareGuid (&Record->DataRecordGuid, &gEfiDataHubStatusCodeRecordGuid)) { + DataRecord = (DATA_HUB_STATUS_CODE_DATA_RECORD *) (((CHAR8 *) Record) + Record->HeaderSize); + + if (DataRecord->Data.HeaderSize > 0) { + if (CompareGuid (&DataRecord->Data.Type, &gEfiStatusCodeDataTypeDebugGuid)) { + // + // If the Data record is from a DEBUG () then send it to Standard Error + // + Sto = gST->StdErr; + OldAttribute = Sto->Mode->Attribute; + Sto->SetAttribute (Sto, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK)); + Sto->OutputString (Sto, (CHAR16 *) (DataRecord + 1)); + Sto->SetAttribute (Sto, OldAttribute); + } + } + } + } + } while ((Mtc != 0) && !EFI_ERROR (Status)); +} + +/** + Register an event handler with the Data Hub to parse EFI_DEBUG_CODE. This + handler reads the Data Hub and sends any DEBUG info to StdErr. + + @param ImageHandle Image handle of this driver. + @param SystemTable Pointer to EFI system table. + + @retval EFI_SUCCESS The event handler was registered. + @retval EFI_OUT_OF_RESOURCES The event hadler was not registered due to lack of system resources. +**/ +EFI_STATUS +EFIAPI +DataHubStdErrInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT64 DataClass; + + gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **) &mDataHub); + // + // Should never fail due to Depex grammer. + // + ASSERT (mDataHub != NULL); + + // + // Create an event and register it with the filter driver + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + DataHubStdErrEventHandler, + mDataHub, + &mDataHubStdErrEvent + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DataClass = EFI_DATA_RECORD_CLASS_DEBUG | EFI_DATA_RECORD_CLASS_ERROR; + Status = mDataHub->RegisterFilterDriver ( + mDataHub, + mDataHubStdErrEvent, + TPL_CALLBACK, + DataClass, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (mDataHubStdErrEvent); + } + + return Status; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf b/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf new file mode 100644 index 0000000000..f9dede864c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf @@ -0,0 +1,57 @@ +## @file +# This driver takes DEBUG info from Data Hub and writes it to StdErr if it exists. +# +# 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 +# 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 = DataHubStdErrDxe + MODULE_UNI_FILE = DataHubStdErrDxe.uni + FILE_GUID = CA515306-00CE-4032-874E-11B755FF6866 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DataHubStdErrInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DataHubStdErr.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + BaseMemoryLib + UefiDriverEntryPoint + DebugLib + +[Guids] + gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## UNDEFINED # DataRecord Date Type + gEfiDataHubStatusCodeRecordGuid ## SOMETIMES_CONSUMES ## UNDEFINED # DataRecordGuid + + +[Protocols] + gEfiDataHubProtocolGuid ## CONSUMES + +[Depex] + gEfiDataHubProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + DataHubStdErrDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.uni b/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.uni new file mode 100644 index 0000000000..88aac304ad Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxeExtra.uni new file mode 100644 index 0000000000..9ef673b8a8 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c new file mode 100644 index 0000000000..12508b4335 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c @@ -0,0 +1,608 @@ +/** @file + FFS file access utilities. + + 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 "FwVolDriver.h" + +#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address)) + +/** + Set File State in the FfsHeader. + + @param State File state to be set into FFS header. + @param FfsHeader Points to the FFS file header + +**/ +VOID +SetFileState ( + IN UINT8 State, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + // + // Set File State in the FfsHeader + // + FfsHeader->State = (EFI_FFS_FILE_STATE) (FfsHeader->State ^ State); + return ; +} + +/** + Get the FFS file state by checking the highest bit set in the header's state field. + + @param ErasePolarity Erase polarity attribute of the firmware volume + @param FfsHeader Points to the FFS file header + + @return FFS File state + +**/ +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + EFI_FFS_FILE_STATE FileState; + UINT8 HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && ((HighestBit & FileState) == 0)) { + HighestBit >>= 1; + } + + return (EFI_FFS_FILE_STATE) HighestBit; +} + +/** + Convert the Buffer Address to LBA Entry Address. + + @param FvDevice Cached FvDevice + @param BufferAddress Address of Buffer + @param LbaListEntry Pointer to the got LBA entry that contains the address. + + @retval EFI_NOT_FOUND Buffer address is out of FvDevice. + @retval EFI_SUCCESS LBA entry is found for Buffer address. + +**/ +EFI_STATUS +Buffer2LbaEntry ( + IN FV_DEVICE *FvDevice, + IN EFI_PHYSICAL_ADDRESS BufferAddress, + OUT LBA_ENTRY **LbaListEntry + ) +{ + LBA_ENTRY *LbaEntry; + LIST_ENTRY *Link; + + Link = FvDevice->LbaHeader.ForwardLink; + LbaEntry = (LBA_ENTRY *) Link; + + // + // Locate LBA which contains the address + // + while (&LbaEntry->Link != &FvDevice->LbaHeader) { + if ((EFI_PHYSICAL_ADDRESS) (UINTN) (LbaEntry->StartingAddress) > BufferAddress) { + break; + } + + Link = LbaEntry->Link.ForwardLink; + LbaEntry = (LBA_ENTRY *) Link; + } + + if (&LbaEntry->Link == &FvDevice->LbaHeader) { + return EFI_NOT_FOUND; + } + + Link = LbaEntry->Link.BackLink; + LbaEntry = (LBA_ENTRY *) Link; + + if (&LbaEntry->Link == &FvDevice->LbaHeader) { + return EFI_NOT_FOUND; + } + + *LbaListEntry = LbaEntry; + + return EFI_SUCCESS; +} + +/** + Convert the Buffer Address to LBA Address & Offset. + + @param FvDevice Cached FvDevice + @param BufferAddress Address of Buffer + @param Lba Pointer to the gob Lba value + @param Offset Pointer to the got Offset + + @retval EFI_NOT_FOUND Buffer address is out of FvDevice. + @retval EFI_SUCCESS LBA and Offset is found for Buffer address. + +**/ +EFI_STATUS +Buffer2Lba ( + IN FV_DEVICE *FvDevice, + IN EFI_PHYSICAL_ADDRESS BufferAddress, + OUT EFI_LBA *Lba, + OUT UINTN *Offset + ) +{ + LBA_ENTRY *LbaEntry; + EFI_STATUS Status; + + LbaEntry = NULL; + + Status = Buffer2LbaEntry ( + FvDevice, + BufferAddress, + &LbaEntry + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *Lba = LbaEntry->LbaIndex; + *Offset = (UINTN) BufferAddress - (UINTN) LbaEntry->StartingAddress; + + return EFI_SUCCESS; +} + +/** + Check if a block of buffer is erased. + + @param ErasePolarity Erase polarity attribute of the firmware volume + @param Buffer The buffer to be checked + @param BufferSize Size of the buffer in bytes + + @retval TRUE The block of buffer is erased + @retval FALSE The block of buffer is not erased + +**/ +BOOLEAN +IsBufferErased ( + IN UINT8 ErasePolarity, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +{ + UINTN Count; + UINT8 EraseByte; + + if (ErasePolarity == 1) { + EraseByte = 0xFF; + } else { + EraseByte = 0; + } + + for (Count = 0; Count < BufferSize; Count++) { + if (Buffer[Count] != EraseByte) { + return FALSE; + } + } + + return TRUE; +} + +/** + Verify checksum of the firmware volume header. + + @param FvHeader Points to the firmware volume header to be checked + + @retval TRUE Checksum verification passed + @retval FALSE Checksum verification failed + +**/ +BOOLEAN +VerifyFvHeaderChecksum ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +{ + UINT16 Checksum; + + Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength); + + if (Checksum == 0) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Verify checksum of the FFS file header. + + @param FfsHeader Points to the FFS file header to be checked + + @retval TRUE Checksum verification passed + @retval FALSE Checksum verification failed + +**/ +BOOLEAN +VerifyHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + UINT8 HeaderChecksum; + + if (IS_FFS_FILE2 (FfsHeader)) { + HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER2)); + } else { + HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER)); + } + HeaderChecksum = (UINT8) (HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File); + + if (HeaderChecksum == 0) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Verify checksum of the FFS file data. + + @param FfsHeader Points to the FFS file header to be checked + + @retval TRUE Checksum verification passed + @retval FALSE Checksum verification failed + +**/ +BOOLEAN +VerifyFileChecksum ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + UINT8 FileChecksum; + EFI_FV_FILE_ATTRIBUTES Attributes; + + Attributes = FfsHeader->Attributes; + + if ((Attributes & FFS_ATTRIB_CHECKSUM) != 0) { + + // + // Check checksum of FFS data + // + if (IS_FFS_FILE2 (FfsHeader)) { + FileChecksum = CalculateSum8 ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER2)); + } else { + FileChecksum = CalculateSum8 ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER)); + } + FileChecksum = (UINT8) (FileChecksum + FfsHeader->IntegrityCheck.Checksum.File); + + if (FileChecksum == 0) { + return TRUE; + } else { + return FALSE; + } + + } else { + + if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { + return FALSE; + } else { + return TRUE; + } + } + +} + +/** + Check if it's a valid FFS file header. + + @param ErasePolarity Erase polarity attribute of the firmware volume + @param FfsHeader Points to the FFS file header to be checked + + @retval TRUE Valid FFS file header + @retval FALSE Invalid FFS file header + +**/ +BOOLEAN +IsValidFFSHeader ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + EFI_FFS_FILE_STATE FileState; + + // + // Check if it is a free space + // + if (IsBufferErased ( + ErasePolarity, + (UINT8 *) FfsHeader, + sizeof (EFI_FFS_FILE_HEADER) + )) { + return FALSE; + } + + FileState = GetFileState (ErasePolarity, FfsHeader); + + switch (FileState) { + case EFI_FILE_HEADER_CONSTRUCTION: + // + // fall through + // + case EFI_FILE_HEADER_INVALID: + return FALSE; + + case EFI_FILE_HEADER_VALID: + // + // fall through + // + case EFI_FILE_DATA_VALID: + // + // fall through + // + case EFI_FILE_MARKED_FOR_UPDATE: + // + // fall through + // + case EFI_FILE_DELETED: + // + // Here we need to verify header checksum + // + if (!VerifyHeaderChecksum (FfsHeader)) { + return FALSE; + } + break; + + default: + // + // return + // + return FALSE; + } + + return TRUE; +} + +/** + Get next possible of Firmware File System Header. + + @param ErasePolarity Erase polarity attribute of the firmware volume + @param FfsHeader Points to the FFS file header to be skipped. + + @return Pointer to next FFS header. + +**/ +EFI_PHYSICAL_ADDRESS +GetNextPossibleFileHeader ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + UINT32 FileLength; + UINT32 SkipLength; + + if (!IsValidFFSHeader (ErasePolarity, FfsHeader)) { + // + // Skip this header + // + if (IS_FFS_FILE2 (FfsHeader)) { + return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2); + } else { + return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + sizeof (EFI_FFS_FILE_HEADER); + } + } + + if (IS_FFS_FILE2 (FfsHeader)) { + FileLength = FFS_FILE2_SIZE (FfsHeader); + } else { + FileLength = FFS_FILE_SIZE (FfsHeader); + } + + // + // Since FileLength is not multiple of 8, we need skip some bytes + // to get next possible header + // + SkipLength = FileLength; + while ((SkipLength & 0x07) != 0) { + SkipLength++; + } + + return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + SkipLength; +} + +/** + Search FFS file with the same FFS name in FV Cache. + + @param FvDevice Cached FV image. + @param FfsHeader Points to the FFS file header to be skipped. + @param StateBit FFS file state bit to be checked. + + @return Pointer to next found FFS header. NULL will return if no found. + +**/ +EFI_FFS_FILE_HEADER * +DuplicateFileExist ( + IN FV_DEVICE *FvDevice, + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_FFS_FILE_STATE StateBit + ) +{ + UINT8 *Ptr; + EFI_FFS_FILE_HEADER *NextFfsFile; + + // + // Search duplicate file, not from the beginning of FV, + // just search the next ocurrence of this file + // + NextFfsFile = FfsHeader; + + do { + Ptr = (UINT8 *) PHYSICAL_ADDRESS_TO_POINTER ( + GetNextPossibleFileHeader (FvDevice->ErasePolarity, + NextFfsFile) + ); + NextFfsFile = (EFI_FFS_FILE_HEADER *) Ptr; + + if ((UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (FvDevice->CachedFv) + FvDevice->FwVolHeader->FvLength - Ptr < + sizeof (EFI_FFS_FILE_HEADER) + ) { + break; + } + + if (!IsValidFFSHeader (FvDevice->ErasePolarity, NextFfsFile)) { + continue; + } + + if (!VerifyFileChecksum (NextFfsFile)) { + continue; + } + + if (CompareGuid (&NextFfsFile->Name, &FfsHeader->Name)) { + if (GetFileState (FvDevice->ErasePolarity, NextFfsFile) == StateBit) { + return NextFfsFile; + } + } + } while (Ptr < (UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (FvDevice->CachedFv) + FvDevice->FwVolHeader->FvLength); + + return NULL; +} + +/** + Change FFS file header state and write to FV. + + @param FvDevice Cached FV image. + @param FfsHeader Points to the FFS file header to be updated. + @param State FFS file state to be set. + + @retval EFI_SUCCESS File state is writen into FV. + @retval others File state can't be writen into FV. + +**/ +EFI_STATUS +UpdateHeaderBit ( + IN FV_DEVICE *FvDevice, + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_FFS_FILE_STATE State + ) +{ + EFI_STATUS Status; + EFI_LBA Lba; + UINTN Offset; + UINTN NumBytesWritten; + + Lba = 0; + Offset = 0; + + SetFileState (State, FfsHeader); + + Buffer2Lba ( + FvDevice, + (EFI_PHYSICAL_ADDRESS) (UINTN) (&FfsHeader->State), + &Lba, + &Offset + ); + // + // Write the state byte into FV + // + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvDevice->Fvb->Write ( + FvDevice->Fvb, + Lba, + Offset, + &NumBytesWritten, + &FfsHeader->State + ); + return Status; +} + +/** + Check if it's a valid FFS file. + Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first. + + @param FvDevice Cached FV image. + @param FfsHeader Points to the FFS file to be checked + + @retval TRUE Valid FFS file + @retval FALSE Invalid FFS file + +**/ +BOOLEAN +IsValidFFSFile ( + IN FV_DEVICE *FvDevice, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + EFI_FFS_FILE_STATE FileState; + UINT8 ErasePolarity; + + ErasePolarity = FvDevice->ErasePolarity; + + FileState = GetFileState (ErasePolarity, FfsHeader); + + switch (FileState) { + case EFI_FILE_DATA_VALID: + if (!VerifyFileChecksum (FfsHeader)) { + return FALSE; + } + + if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { + break; + } + // + // Check if there is another duplicated file with the EFI_FILE_DATA_VALID + // + if (DuplicateFileExist (FvDevice, FfsHeader, EFI_FILE_DATA_VALID) != NULL) { + return FALSE; + } + + break; + + case EFI_FILE_MARKED_FOR_UPDATE: + if (!VerifyFileChecksum (FfsHeader)) { + return FALSE; + } + + if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { + // + // since its data area is not unperturbed, it cannot be reclaimed, + // marked it as deleted + // + UpdateHeaderBit (FvDevice, FfsHeader, EFI_FILE_DELETED); + return TRUE; + + } else if (DuplicateFileExist (FvDevice, FfsHeader, EFI_FILE_DATA_VALID) != NULL) { + // + // Here the found file is more recent than this file, + // mark it as deleted + // + UpdateHeaderBit (FvDevice, FfsHeader, EFI_FILE_DELETED); + return TRUE; + + } else { + return TRUE; + } + + break; + + case EFI_FILE_DELETED: + if (!VerifyFileChecksum (FfsHeader)) { + return FALSE; + } + + break; + + default: + return FALSE; + } + + return TRUE; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwPadFile.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwPadFile.c new file mode 100644 index 0000000000..8d53d879bd --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwPadFile.c @@ -0,0 +1,1228 @@ +/** @file + Implements functions to pad firmware file. + + 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 "FwVolDriver.h" + +/** + Calculate the checksum for a PAD file. + + @param PadFileHeader The Pad File to be caculeted the checksum. + +**/ +VOID +SetPadFileChecksum ( + IN EFI_FFS_FILE_HEADER *PadFileHeader + ) +{ + if ((PadFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) { + + if (IS_FFS_FILE2 (PadFileHeader)) { + // + // Calculate checksum of Pad File Data + // + PadFileHeader->IntegrityCheck.Checksum.File = + CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2)); + + } else { + // + // Calculate checksum of Pad File Data + // + PadFileHeader->IntegrityCheck.Checksum.File = + CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER)); + } + + } else { + + PadFileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + + } + + return ; +} + +/** + Create a PAD File in the Free Space. + + @param FvDevice Firmware Volume Device. + @param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted. + @param Size Pad file Size, not include the header. + @param PadFileEntry The Ffs File Entry that points to this Pad File. + + @retval EFI_SUCCESS Successfully create a PAD file. + @retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file. + @retval EFI_INVALID_PARAMETER Size is not 8 byte alignment. + @retval EFI_DEVICE_ERROR Free space is not erased. +**/ +EFI_STATUS +FvCreatePadFileInFreeSpace ( + IN FV_DEVICE *FvDevice, + IN FREE_SPACE_ENTRY *FreeSpaceEntry, + IN UINTN Size, + OUT FFS_FILE_LIST_ENTRY **PadFileEntry + ) +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *PadFileHeader; + UINTN Offset; + UINTN NumBytesWritten; + UINTN StateOffset; + UINT8 *StartPos; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + UINTN HeaderSize; + UINTN FileSize; + + HeaderSize = sizeof (EFI_FFS_FILE_HEADER); + FileSize = Size + HeaderSize; + if (FileSize > 0x00FFFFFF) { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + FileSize = Size + HeaderSize; + } + + if (FreeSpaceEntry->Length < FileSize) { + return EFI_OUT_OF_RESOURCES; + } + + if ((Size & 0x07) != 0) { + return EFI_INVALID_PARAMETER; + } + + StartPos = FreeSpaceEntry->StartingAddress; + + // + // First double check the space + // + if (!IsBufferErased ( + FvDevice->ErasePolarity, + StartPos, + FileSize + )) { + return EFI_DEVICE_ERROR; + } + + PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos; + + // + // Create File Step 1 + // + SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader); + + Offset = (UINTN) (StartPos - FvDevice->CachedFv); + StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + StateOffset, + &NumBytesWritten, + &PadFileHeader->State + ); + if (EFI_ERROR (Status)) { + SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader); + return Status; + } + // + // Update Free Space Entry, since header is allocated + // + FreeSpaceEntry->Length -= HeaderSize; + FreeSpaceEntry->StartingAddress += HeaderSize; + + // + // Fill File Name Guid, here we assign a NULL-GUID to Pad files + // + ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID)); + + // + // Fill File Type, checksum(0), Attributes(0), Size + // + PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFileHeader->Attributes = 0; + if ((FileSize) > 0x00FFFFFF) { + ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) FileSize; + *(UINT32 *) PadFileHeader->Size &= 0xFF000000; + PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; + } else { + *(UINT32 *) PadFileHeader->Size &= 0xFF000000; + *(UINT32 *) PadFileHeader->Size |= FileSize; + } + + SetHeaderChecksum (PadFileHeader); + SetPadFileChecksum (PadFileHeader); + + Offset = (UINTN) (StartPos - FvDevice->CachedFv); + + NumBytesWritten = HeaderSize; + Status = FvcWrite ( + FvDevice, + Offset, + &NumBytesWritten, + (UINT8 *) PadFileHeader + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Step 2, then Mark header valid, since no data write, + // mark the data valid at the same time. + // + SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader); + SetFileState (EFI_FILE_DATA_VALID, PadFileHeader); + + Offset = (UINTN) (StartPos - FvDevice->CachedFv); + StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + StateOffset, + &NumBytesWritten, + &PadFileHeader->State + ); + if (EFI_ERROR (Status)) { + SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader); + SetFileState (EFI_FILE_DATA_VALID, PadFileHeader); + return Status; + } + // + // Update Free Space Entry, since header is allocated + // + FreeSpaceEntry->Length -= Size; + FreeSpaceEntry->StartingAddress += Size; + + // + // If successfully, insert an FfsFileEntry at the end of ffs file list + // + FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); + ASSERT (FfsFileEntry != NULL); + + FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) StartPos; + InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); + + *PadFileEntry = FfsFileEntry; + FvDevice->CurrentFfsFile = FfsFileEntry; + + return EFI_SUCCESS; +} + +/** + Fill pad file header within firmware cache. + + @param PadFileHeader The start of the Pad File Buffer. + @param PadFileLength The length of the pad file including the header. + +**/ +VOID +FvFillPadFile ( + IN EFI_FFS_FILE_HEADER *PadFileHeader, + IN UINTN PadFileLength + ) +{ + // + // Fill File Name Guid, here we assign a NULL-GUID to Pad files + // + ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID)); + + // + // Fill File Type, checksum(0), Attributes(0), Size + // + PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFileHeader->Attributes = 0; + if (PadFileLength > 0x00FFFFFF) { + ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) PadFileLength; + *(UINT32 *) PadFileHeader->Size &= 0xFF000000; + PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; + } else { + *(UINT32 *) PadFileHeader->Size &= 0xFF000000; + *(UINT32 *) PadFileHeader->Size |= PadFileLength; + } + + SetHeaderChecksum (PadFileHeader); + SetPadFileChecksum (PadFileHeader); + + // + // Set File State to 0x00000111 + // + SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader); + SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader); + SetFileState (EFI_FILE_DATA_VALID, PadFileHeader); + + return ; +} + +/** + Create entire FFS file. + + @param FileHeader Starting Address of a Buffer that hold the FFS File image. + @param FfsFileBuffer The source buffer that contains the File Data. + @param BufferSize The length of FfsFileBuffer. + @param ActualFileSize Size of FFS file. + @param FileName The Guid of Ffs File. + @param FileType The type of the written Ffs File. + @param FileAttributes The attributes of the written Ffs File. + + @retval EFI_INVALID_PARAMETER File type is not valid. + @retval EFI_SUCCESS FFS file is successfully created. + +**/ +EFI_STATUS +FvFillFfsFile ( + OUT EFI_FFS_FILE_HEADER *FileHeader, + IN UINT8 *FfsFileBuffer, + IN UINTN BufferSize, + IN UINTN ActualFileSize, + IN EFI_GUID *FileName, + IN EFI_FV_FILETYPE FileType, + IN EFI_FV_FILE_ATTRIBUTES FileAttributes + ) +{ + EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute; + EFI_FFS_FILE_HEADER *TmpFileHeader; + + // + // File Type value 0x0E~0xE0 are reserved + // + if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) { + return EFI_INVALID_PARAMETER; + } + + TmpFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer; + // + // First fill all fields ready in FfsFileBuffer + // + CopyGuid (&TmpFileHeader->Name, FileName); + TmpFileHeader->Type = FileType; + + // + // Convert the FileAttributes to FFSFileAttributes + // + FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute); + + TmpFileHeader->Attributes = TmpFileAttribute; + + if (ActualFileSize > 0x00FFFFFF) { + ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize; + *(UINT32 *) FileHeader->Size &= 0xFF000000; + FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; + } else { + *(UINT32 *) FileHeader->Size &= 0xFF000000; + *(UINT32 *) FileHeader->Size |= ActualFileSize; + } + + SetHeaderChecksum (TmpFileHeader); + SetFileChecksum (TmpFileHeader, ActualFileSize); + + SetFileState (EFI_FILE_HEADER_CONSTRUCTION, TmpFileHeader); + SetFileState (EFI_FILE_HEADER_VALID, TmpFileHeader); + SetFileState (EFI_FILE_DATA_VALID, TmpFileHeader); + + // + // Copy data from FfsFileBuffer to FileHeader(cache) + // + CopyMem (FileHeader, FfsFileBuffer, BufferSize); + + return EFI_SUCCESS; +} + +/** + Fill some other extra space using 0xFF(Erase Value). + + @param ErasePolarity Fv erase value. + @param FileHeader Point to the start of FFS File. + @param ExtraLength The pading length. + +**/ +VOID +FvAdjustFfsFile ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN UINTN ExtraLength + ) +{ + UINT8 *Ptr; + UINT8 PadingByte; + + if (IS_FFS_FILE2 (FileHeader)) { + Ptr = (UINT8 *) FileHeader + FFS_FILE2_SIZE (FileHeader); + } else { + Ptr = (UINT8 *) FileHeader + FFS_FILE_SIZE (FileHeader); + } + + if (ErasePolarity == 0) { + PadingByte = 0; + } else { + PadingByte = 0xFF; + } + // + // Fill the non-used space with Padding Byte + // + SetMem (Ptr, ExtraLength, PadingByte); + + return ; +} + +/** + Free File List entry pointed by FileListHead. + + @param FileListHeader FileListEntry Header. + +**/ +VOID +FreeFileList ( + IN LIST_ENTRY *FileListHead + ) +{ + FFS_FILE_LIST_ENTRY *FfsFileEntry; + LIST_ENTRY *NextEntry; + + FfsFileEntry = (FFS_FILE_LIST_ENTRY *) (FileListHead->ForwardLink); + + // + // Loop the whole list entry to free resources + // + while (&FfsFileEntry->Link != FileListHead) { + NextEntry = (&FfsFileEntry->Link)->ForwardLink; + FreePool (FfsFileEntry); + FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry; + } + + return ; +} + +/** + Create a new file within a PAD file area. + + @param FvDevice Firmware Volume Device. + @param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state). + @param BufferSize The size of FfsFileBuffer. + @param ActualFileSize The actual file length, it may not be multiples of 8. + @param FileName The FFS File Name. + @param FileType The FFS File Type. + @param FileAttributes The Attributes of the FFS File to be created. + + @retval EFI_SUCCESS Successfully create a new file within the found PAD file area. + @retval EFI_OUT_OF_RESOURCES No suitable PAD file is found. + @retval other errors New file is created failed. + +**/ +EFI_STATUS +FvCreateNewFileInsidePadFile ( + IN FV_DEVICE *FvDevice, + IN UINT8 *FfsFileBuffer, + IN UINTN BufferSize, + IN UINTN ActualFileSize, + IN EFI_GUID *FileName, + IN EFI_FV_FILETYPE FileType, + IN EFI_FV_FILE_ATTRIBUTES FileAttributes + ) +{ + UINTN RequiredAlignment; + FFS_FILE_LIST_ENTRY *PadFileEntry; + EFI_STATUS Status; + UINTN PadAreaLength; + UINTN PadSize; + EFI_FFS_FILE_HEADER *FileHeader; + EFI_FFS_FILE_HEADER *OldPadFileHeader; + EFI_FFS_FILE_HEADER *PadFileHeader; + EFI_FFS_FILE_HEADER *TailPadFileHeader; + UINTN StateOffset; + UINTN Offset; + UINTN NumBytesWritten; + UINT8 *StartPos; + LIST_ENTRY NewFileList; + FFS_FILE_LIST_ENTRY *NewFileListEntry; + FFS_FILE_LIST_ENTRY *FfsEntry; + FFS_FILE_LIST_ENTRY *NextFfsEntry; + + // + // First get the required alignment from the File Attributes + // + RequiredAlignment = GetRequiredAlignment (FileAttributes); + + // + // Find a suitable PAD File + // + Status = FvLocatePadFile ( + FvDevice, + BufferSize, + RequiredAlignment, + &PadSize, + &PadFileEntry + ); + + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader; + + // + // Step 1: Update Pad File Header + // + SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldPadFileHeader); + + StartPos = PadFileEntry->FfsHeader; + + Offset = (UINTN) (StartPos - FvDevice->CachedFv); + StateOffset = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + StateOffset, + &NumBytesWritten, + &OldPadFileHeader->State + ); + if (EFI_ERROR (Status)) { + SetFileState (EFI_FILE_HEADER_CONSTRUCTION, OldPadFileHeader); + return Status; + } + + // + // Step 2: Update Pad area + // + InitializeListHead (&NewFileList); + + if (IS_FFS_FILE2 (OldPadFileHeader)) { + PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER); + PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2)); + } else { + PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER); + PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER)); + } + + if (PadSize != 0) { + // + // Insert a PAD file before to achieve required alignment + // + FvFillPadFile (PadFileHeader, PadSize); + NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); + ASSERT (NewFileListEntry != NULL); + NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader; + InsertTailList (&NewFileList, &NewFileListEntry->Link); + } + + FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize); + + Status = FvFillFfsFile ( + FileHeader, + FfsFileBuffer, + BufferSize, + ActualFileSize, + FileName, + FileType, + FileAttributes + ); + if (EFI_ERROR (Status)) { + FreeFileList (&NewFileList); + return Status; + } + + NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); + ASSERT (NewFileListEntry != NULL); + + NewFileListEntry->FfsHeader = (UINT8 *) FileHeader; + InsertTailList (&NewFileList, &NewFileListEntry->Link); + + FvDevice->CurrentFfsFile = NewFileListEntry; + + if (PadAreaLength > (BufferSize + PadSize)) { + if ((PadAreaLength - BufferSize - PadSize) >= sizeof (EFI_FFS_FILE_HEADER)) { + // + // we can insert another PAD file + // + TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize); + FvFillPadFile (TailPadFileHeader, PadAreaLength - BufferSize - PadSize); + + NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); + ASSERT (NewFileListEntry != NULL); + + NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader; + InsertTailList (&NewFileList, &NewFileListEntry->Link); + } else { + // + // because left size cannot hold another PAD file header, + // adjust the writing file size (just in cache) + // + FvAdjustFfsFile ( + FvDevice->ErasePolarity, + FileHeader, + PadAreaLength - BufferSize - PadSize + ); + } + } + // + // Start writing to FV + // + if (IS_FFS_FILE2 (OldPadFileHeader)) { + StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2); + } else { + StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER); + } + + Offset = (UINTN) (StartPos - FvDevice->CachedFv); + + NumBytesWritten = PadAreaLength; + Status = FvcWrite ( + FvDevice, + Offset, + &NumBytesWritten, + StartPos + ); + if (EFI_ERROR (Status)) { + FreeFileList (&NewFileList); + FvDevice->CurrentFfsFile = NULL; + return Status; + } + + // + // Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID + // + SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader); + + StartPos = PadFileEntry->FfsHeader; + + Offset = (UINTN) (StartPos - FvDevice->CachedFv); + StateOffset = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + StateOffset, + &NumBytesWritten, + &OldPadFileHeader->State + ); + if (EFI_ERROR (Status)) { + SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader); + FreeFileList (&NewFileList); + FvDevice->CurrentFfsFile = NULL; + return Status; + } + + // + // If all successfully, update FFS_FILE_LIST + // + + // + // Delete old pad file entry + // + FfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink; + NextFfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink; + + FreePool (PadFileEntry); + + FfsEntry->Link.ForwardLink = NewFileList.ForwardLink; + (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link; + NextFfsEntry->Link.BackLink = NewFileList.BackLink; + (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link; + + return EFI_SUCCESS; +} + +/** + Free all FfsBuffer. + + @param NumOfFiles Number of FfsBuffer. + @param FfsBuffer An array of pointer to an FFS File Buffer + +**/ +VOID +FreeFfsBuffer ( + IN UINTN NumOfFiles, + IN UINT8 **FfsBuffer + ) +{ + UINTN Index; + for (Index = 0; Index < NumOfFiles; Index++) { + if (FfsBuffer[Index] != NULL) { + FreePool (FfsBuffer[Index]); + } + } +} + +/** + Create multiple files within a PAD File area. + + @param FvDevice Firmware Volume Device. + @param PadFileEntry The pad file entry to be written in. + @param NumOfFiles Total File number to be written. + @param BufferSize The array of buffer size of each FfsBuffer. + @param ActualFileSize The array of actual file size. + @param PadSize The array of leading pad file size for each FFS File + @param FfsBuffer The array of Ffs Buffer pointer. + @param FileData The array of EFI_FV_WRITE_FILE_DATA structure, + used to get name, attributes, type, etc. + + @retval EFI_SUCCESS Add the input multiple files into PAD file area. + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval other error Files can't be added into PAD file area. + +**/ +EFI_STATUS +FvCreateMultipleFilesInsidePadFile ( + IN FV_DEVICE *FvDevice, + IN FFS_FILE_LIST_ENTRY *PadFileEntry, + IN UINTN NumOfFiles, + IN UINTN *BufferSize, + IN UINTN *ActualFileSize, + IN UINTN *PadSize, + IN UINT8 **FfsBuffer, + IN EFI_FV_WRITE_FILE_DATA *FileData + ) +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *OldPadFileHeader; + UINTN Index; + EFI_FFS_FILE_HEADER *PadFileHeader; + EFI_FFS_FILE_HEADER *FileHeader; + EFI_FFS_FILE_HEADER *TailPadFileHeader; + UINTN TotalSize; + UINTN PadAreaLength; + LIST_ENTRY NewFileList; + FFS_FILE_LIST_ENTRY *NewFileListEntry; + UINTN Offset; + UINTN NumBytesWritten; + UINT8 *StartPos; + FFS_FILE_LIST_ENTRY *FfsEntry; + FFS_FILE_LIST_ENTRY *NextFfsEntry; + + InitializeListHead (&NewFileList); + + NewFileListEntry = NULL; + + OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader; + if (IS_FFS_FILE2 (OldPadFileHeader)) { + PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2); + } else { + PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER); + } + + Status = UpdateHeaderBit ( + FvDevice, + OldPadFileHeader, + EFI_FILE_MARKED_FOR_UPDATE + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Update PAD area + // + TotalSize = 0; + if (IS_FFS_FILE2 (OldPadFileHeader)) { + PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2)); + } else { + PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER)); + } + FileHeader = PadFileHeader; + + for (Index = 0; Index < NumOfFiles; Index++) { + if (PadSize[Index] != 0) { + FvFillPadFile (PadFileHeader, PadSize[Index]); + NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); + if (NewFileListEntry == NULL) { + FreeFileList (&NewFileList); + return EFI_OUT_OF_RESOURCES; + } + + NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader; + InsertTailList (&NewFileList, &NewFileListEntry->Link); + } + + FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]); + Status = FvFillFfsFile ( + FileHeader, + FfsBuffer[Index], + BufferSize[Index], + ActualFileSize[Index], + FileData[Index].NameGuid, + FileData[Index].Type, + FileData[Index].FileAttributes + ); + if (EFI_ERROR (Status)) { + FreeFileList (&NewFileList); + return Status; + } + + NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); + if (NewFileListEntry == NULL) { + FreeFileList (&NewFileList); + return EFI_OUT_OF_RESOURCES; + } + + NewFileListEntry->FfsHeader = (UINT8 *) FileHeader; + InsertTailList (&NewFileList, &NewFileListEntry->Link); + + PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]); + TotalSize += PadSize[Index]; + TotalSize += BufferSize[Index]; + } + + FvDevice->CurrentFfsFile = NewFileListEntry; + // + // Maybe we need a tail pad file + // + if (PadAreaLength > TotalSize) { + if ((PadAreaLength - TotalSize) >= sizeof (EFI_FFS_FILE_HEADER)) { + // + // we can insert another PAD file + // + TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[NumOfFiles - 1]); + FvFillPadFile (TailPadFileHeader, PadAreaLength - TotalSize); + + NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); + if (NewFileListEntry == NULL) { + FreeFileList (&NewFileList); + FvDevice->CurrentFfsFile = NULL; + return EFI_OUT_OF_RESOURCES; + } + + NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader; + InsertTailList (&NewFileList, &NewFileListEntry->Link); + } else { + // + // because left size cannot hold another PAD file header, + // adjust the writing file size (just in cache) + // + FvAdjustFfsFile ( + FvDevice->ErasePolarity, + FileHeader, + PadAreaLength - TotalSize + ); + } + } + // + // Start writing to FV + // + if (IS_FFS_FILE2 (OldPadFileHeader)) { + StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2); + } else { + StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER); + } + + Offset = (UINTN) (StartPos - FvDevice->CachedFv); + + NumBytesWritten = PadAreaLength; + Status = FvcWrite ( + FvDevice, + Offset, + &NumBytesWritten, + StartPos + ); + if (EFI_ERROR (Status)) { + FreeFileList (&NewFileList); + FvDevice->CurrentFfsFile = NULL; + return Status; + } + + Status = UpdateHeaderBit ( + FvDevice, + OldPadFileHeader, + EFI_FILE_HEADER_INVALID + ); + if (EFI_ERROR (Status)) { + FreeFileList (&NewFileList); + FvDevice->CurrentFfsFile = NULL; + return Status; + } + + // + // Update File List Link + // + + // + // First delete old pad file entry + // + FfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink; + NextFfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink; + + FreePool (PadFileEntry); + + FfsEntry->Link.ForwardLink = NewFileList.ForwardLink; + (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link; + NextFfsEntry->Link.BackLink = NewFileList.BackLink; + (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link; + + return EFI_SUCCESS; +} + +/** + Create multiple files within the Free Space. + + @param FvDevice Firmware Volume Device. + @param FreeSpaceEntry Indicating in which Free Space(Cache) the multiple files will be inserted. + @param NumOfFiles Total File number to be written. + @param BufferSize The array of buffer size of each FfsBuffer. + @param ActualFileSize The array of actual file size. + @param PadSize The array of leading pad file size for each FFS File + @param FfsBuffer The array of Ffs Buffer pointer. + @param FileData The array of EFI_FV_WRITE_FILE_DATA structure, + used to get name, attributes, type, etc. + + @retval EFI_SUCCESS Add the input multiple files into PAD file area. + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval other error Files can't be added into PAD file area. + +**/ +EFI_STATUS +FvCreateMultipleFilesInsideFreeSpace ( + IN FV_DEVICE *FvDevice, + IN FREE_SPACE_ENTRY *FreeSpaceEntry, + IN UINTN NumOfFiles, + IN UINTN *BufferSize, + IN UINTN *ActualFileSize, + IN UINTN *PadSize, + IN UINT8 **FfsBuffer, + IN EFI_FV_WRITE_FILE_DATA *FileData + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_FFS_FILE_HEADER *PadFileHeader; + EFI_FFS_FILE_HEADER *FileHeader; + UINTN TotalSize; + LIST_ENTRY NewFileList; + FFS_FILE_LIST_ENTRY *NewFileListEntry; + UINTN Offset; + UINTN NumBytesWritten; + UINT8 *StartPos; + + InitializeListHead (&NewFileList); + + NewFileListEntry = NULL; + + TotalSize = 0; + StartPos = FreeSpaceEntry->StartingAddress; + PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos; + FileHeader = PadFileHeader; + + for (Index = 0; Index < NumOfFiles; Index++) { + if (PadSize[Index] != 0) { + FvFillPadFile (PadFileHeader, PadSize[Index]); + NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); + if (NewFileListEntry == NULL) { + FreeFileList (&NewFileList); + return EFI_OUT_OF_RESOURCES; + } + + NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader; + InsertTailList (&NewFileList, &NewFileListEntry->Link); + } + + FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]); + Status = FvFillFfsFile ( + FileHeader, + FfsBuffer[Index], + BufferSize[Index], + ActualFileSize[Index], + FileData[Index].NameGuid, + FileData[Index].Type, + FileData[Index].FileAttributes + ); + if (EFI_ERROR (Status)) { + FreeFileList (&NewFileList); + return Status; + } + + NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); + if (NewFileListEntry == NULL) { + FreeFileList (&NewFileList); + return EFI_OUT_OF_RESOURCES; + } + + NewFileListEntry->FfsHeader = (UINT8 *) FileHeader; + InsertTailList (&NewFileList, &NewFileListEntry->Link); + + PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]); + TotalSize += PadSize[Index]; + TotalSize += BufferSize[Index]; + } + + if (FreeSpaceEntry->Length < TotalSize) { + FreeFileList (&NewFileList); + return EFI_OUT_OF_RESOURCES; + } + + FvDevice->CurrentFfsFile = NewFileListEntry; + + // + // Start writing to FV + // + Offset = (UINTN) (StartPos - FvDevice->CachedFv); + + NumBytesWritten = TotalSize; + Status = FvcWrite ( + FvDevice, + Offset, + &NumBytesWritten, + StartPos + ); + if (EFI_ERROR (Status)) { + FreeFileList (&NewFileList); + FvDevice->CurrentFfsFile = NULL; + return Status; + } + + FreeSpaceEntry->Length -= TotalSize; + FreeSpaceEntry->StartingAddress += TotalSize; + + NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileList.ForwardLink); + + while (NewFileListEntry != (FFS_FILE_LIST_ENTRY *) &NewFileList) { + InsertTailList (&FvDevice->FfsFileListHeader, &NewFileListEntry->Link); + NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileListEntry->Link.ForwardLink); + } + + return EFI_SUCCESS; +} + +/** + Write multiple files into FV in reliable method. + + @param FvDevice Firmware Volume Device. + @param NumOfFiles Total File number to be written. + @param FileData The array of EFI_FV_WRITE_FILE_DATA structure, + used to get name, attributes, type, etc + @param FileOperation The array of operation for each file. + + @retval EFI_SUCCESS Files are added into FV. + @retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files. + @retval EFI_INVALID_PARAMETER File number is less than or equal to 1. + @retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files. + +**/ +EFI_STATUS +FvCreateMultipleFiles ( + IN FV_DEVICE *FvDevice, + IN UINTN NumOfFiles, + IN EFI_FV_WRITE_FILE_DATA *FileData, + IN BOOLEAN *FileOperation + ) +{ + EFI_STATUS Status; + UINT8 *FfsBuffer[MAX_FILES]; + UINTN Index1; + UINTN Index2; + UINTN BufferSize[MAX_FILES]; + UINTN ActualFileSize[MAX_FILES]; + UINTN RequiredAlignment[MAX_FILES]; + UINTN PadSize[MAX_FILES]; + FFS_FILE_LIST_ENTRY *PadFileEntry; + UINTN TotalSizeNeeded; + FREE_SPACE_ENTRY *FreeSpaceEntry; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN Key; + EFI_GUID FileNameGuid; + EFI_FV_FILETYPE OldFileType; + EFI_FV_FILE_ATTRIBUTES OldFileAttributes; + UINTN OldFileSize; + FFS_FILE_LIST_ENTRY *OldFfsFileEntry[MAX_FILES]; + EFI_FFS_FILE_HEADER *OldFileHeader[MAX_FILES]; + BOOLEAN IsCreateFile; + UINTN HeaderSize; + + // + // To use this function, we must ensure that the NumOfFiles is great + // than 1 + // + if (NumOfFiles <= 1) { + return EFI_INVALID_PARAMETER; + } + + if (NumOfFiles > MAX_FILES) { + return EFI_UNSUPPORTED; + } + + Fv = &FvDevice->Fv; + + SetMem (FfsBuffer, NumOfFiles, 0); + SetMem (RequiredAlignment, NumOfFiles, 8); + SetMem (PadSize, NumOfFiles, 0); + ZeroMem (OldFfsFileEntry, sizeof (OldFfsFileEntry)); + ZeroMem (OldFileHeader, sizeof (OldFileHeader)); + + // + // Adjust file size + // + for (Index1 = 0; Index1 < NumOfFiles; Index1++) { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER); + ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize; + if (ActualFileSize[Index1] > 0x00FFFFFF) { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize; + } + BufferSize[Index1] = ActualFileSize[Index1]; + + if (BufferSize[Index1] == HeaderSize) { + // + // clear file attributes, zero-length file does not have any attributes + // + FileData[Index1].FileAttributes = 0; + } + + while ((BufferSize[Index1] & 0x07) != 0) { + BufferSize[Index1]++; + } + + FfsBuffer[Index1] = AllocateZeroPool (BufferSize[Index1]); + + // + // Copy File Data into FileBuffer + // + CopyMem ( + FfsBuffer[Index1] + HeaderSize, + FileData[Index1].Buffer, + FileData[Index1].BufferSize + ); + + if (FvDevice->ErasePolarity == 1) { + for (Index2 = 0; Index2 < HeaderSize; Index2++) { + FfsBuffer[Index1][Index2] = (UINT8)~FfsBuffer[Index1][Index2]; + } + } + + if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) { + RequiredAlignment[Index1] = GetRequiredAlignment (FileData[Index1].FileAttributes); + } + // + // If update file, mark the original file header to + // EFI_FILE_MARKED_FOR_UPDATE + // + IsCreateFile = FileOperation[Index1]; + if (!IsCreateFile) { + + Key = 0; + do { + OldFileType = 0; + Status = Fv->GetNextFile ( + Fv, + &Key, + &OldFileType, + &FileNameGuid, + &OldFileAttributes, + &OldFileSize + ); + if (EFI_ERROR (Status)) { + FreeFfsBuffer (NumOfFiles, FfsBuffer); + return Status; + } + } while (!CompareGuid (&FileNameGuid, FileData[Index1].NameGuid)); + + // + // Get FfsFileEntry from the search key + // + OldFfsFileEntry[Index1] = (FFS_FILE_LIST_ENTRY *) Key; + OldFileHeader[Index1] = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry[Index1]->FfsHeader; + Status = UpdateHeaderBit ( + FvDevice, + OldFileHeader[Index1], + EFI_FILE_MARKED_FOR_UPDATE + ); + if (EFI_ERROR (Status)) { + FreeFfsBuffer (NumOfFiles, FfsBuffer); + return Status; + } + } + } + // + // First to search a suitable pad file that can hold so + // many files + // + Status = FvSearchSuitablePadFile ( + FvDevice, + NumOfFiles, + BufferSize, + RequiredAlignment, + PadSize, + &TotalSizeNeeded, + &PadFileEntry + ); + + if (Status == EFI_NOT_FOUND) { + // + // Try to find a free space that can hold these files + // + Status = FvSearchSuitableFreeSpace ( + FvDevice, + NumOfFiles, + BufferSize, + RequiredAlignment, + PadSize, + &TotalSizeNeeded, + &FreeSpaceEntry + ); + if (EFI_ERROR (Status)) { + FreeFfsBuffer (NumOfFiles, FfsBuffer); + return EFI_OUT_OF_RESOURCES; + } + Status = FvCreateMultipleFilesInsideFreeSpace ( + FvDevice, + FreeSpaceEntry, + NumOfFiles, + BufferSize, + ActualFileSize, + PadSize, + FfsBuffer, + FileData + ); + + } else { + // + // Create multiple files inside such a pad file + // to achieve lock-step update + // + Status = FvCreateMultipleFilesInsidePadFile ( + FvDevice, + PadFileEntry, + NumOfFiles, + BufferSize, + ActualFileSize, + PadSize, + FfsBuffer, + FileData + ); + } + + FreeFfsBuffer (NumOfFiles, FfsBuffer); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Delete those updated files + // + for (Index1 = 0; Index1 < NumOfFiles; Index1++) { + IsCreateFile = FileOperation[Index1]; + if (!IsCreateFile && OldFfsFileEntry[Index1] != NULL) { + (OldFfsFileEntry[Index1]->Link.BackLink)->ForwardLink = OldFfsFileEntry[Index1]->Link.ForwardLink; + (OldFfsFileEntry[Index1]->Link.ForwardLink)->BackLink = OldFfsFileEntry[Index1]->Link.BackLink; + FreePool (OldFfsFileEntry[Index1]); + } + } + // + // Set those files' state to EFI_FILE_DELETED + // + for (Index1 = 0; Index1 < NumOfFiles; Index1++) { + IsCreateFile = FileOperation[Index1]; + if (!IsCreateFile && OldFileHeader[Index1] != NULL) { + Status = UpdateHeaderBit (FvDevice, OldFileHeader[Index1], EFI_FILE_DELETED); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c new file mode 100644 index 0000000000..2ba09c49b5 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c @@ -0,0 +1,798 @@ +/** @file + + Firmware File System driver that produce full Firmware Volume2 protocol. + Layers on top of Firmware Block protocol to produce a file abstraction + of FV based files. + + 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 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 "FwVolDriver.h" + +#define KEYSIZE sizeof (UINTN) + +/** + Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and + copy the real length volume header into it. + + @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to + read the volume header + @param FwVolHeader Pointer to pointer to allocated buffer in which + the volume header is returned. + + @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. + @retval EFI_SUCCESS Successfully read volume header to the allocated + buffer. + @retval EFI_ACCESS_DENIED Read status of FV is not enabled. + @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or + the file system could not be understood. +**/ +EFI_STATUS +GetFwVolHeader ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, + OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER TempFvh; + EFI_FVB_ATTRIBUTES_2 FvbAttributes; + UINTN FvhLength; + EFI_PHYSICAL_ADDRESS BaseAddress; + + // + // Determine the real length of FV header + // + Status = Fvb->GetAttributes ( + Fvb, + &FvbAttributes + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((FvbAttributes & EFI_FVB2_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + // + // Just avoid compiling warning + // + BaseAddress = 0; + FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER); + + // + // memory-mapped FV and non memory-mapped has different ways to read + // + if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { + Status = Fvb->GetPhysicalAddress ( + Fvb, + &BaseAddress + ); + if (EFI_ERROR (Status)) { + return Status; + } + CopyMem (&TempFvh, (VOID *) (UINTN) BaseAddress, FvhLength); + } else { + Status = Fvb->Read ( + Fvb, + 0, + 0, + &FvhLength, + (UINT8 *) &TempFvh + ); + } + + // + // Validate FV Header signature, if not as expected, continue. + // + if (TempFvh.Signature != EFI_FVH_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see that the file system is indeed formatted in a way we can + // understand it... + // + if ((!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) && + (!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) { + return EFI_INVALID_PARAMETER; + } + + *FwVolHeader = AllocatePool (TempFvh.HeaderLength); + if (*FwVolHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Read the whole header + // + if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { + CopyMem (*FwVolHeader, (VOID *) (UINTN) BaseAddress, TempFvh.HeaderLength); + } else { + // + // Assumed the first block is bigger than the length of Fv headder + // + FvhLength = TempFvh.HeaderLength; + Status = Fvb->Read ( + Fvb, + 0, + 0, + &FvhLength, + (UINT8 *) *FwVolHeader + ); + // + // Check whether Read successes. + // + if (EFI_ERROR (Status)) { + FreePool (*FwVolHeader); + *FwVolHeader = NULL; + return Status; + } + } + + return EFI_SUCCESS; +} + +/** + Free FvDevice resource when error happens. + + @param FvDevice Pointer to the FvDevice to be freed. +**/ +VOID +FreeFvDeviceResource ( + IN FV_DEVICE *FvDevice + ) +{ + LBA_ENTRY *LbaEntry; + FREE_SPACE_ENTRY *FreeSpaceEntry; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + LIST_ENTRY *NextEntry; + + // + // Free LAB Entry + // + LbaEntry = (LBA_ENTRY *) FvDevice->LbaHeader.ForwardLink; + while (&LbaEntry->Link != &FvDevice->LbaHeader) { + NextEntry = (&LbaEntry->Link)->ForwardLink; + FreePool (LbaEntry); + LbaEntry = (LBA_ENTRY *) NextEntry; + } + // + // Free File List Entry + // + FfsFileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink; + while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) { + NextEntry = (&FfsFileEntry->Link)->ForwardLink; + FreePool (FfsFileEntry); + FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry; + } + // + // Free Space Entry + // + FreeSpaceEntry = (FREE_SPACE_ENTRY *) FvDevice->FreeSpaceHeader.ForwardLink; + while (&FreeSpaceEntry->Link != &FvDevice->FreeSpaceHeader) { + NextEntry = (&FreeSpaceEntry->Link)->ForwardLink; + FreePool (FreeSpaceEntry); + FreeSpaceEntry = (FREE_SPACE_ENTRY *) NextEntry; + } + // + // Free the cache + // + FreePool ((UINT8 *) (UINTN) FvDevice->CachedFv); + + return ; +} + +/** + + Firmware volume inherits authentication status from the FV image file and section(in another firmware volume) + where it came from. + + @param FvDevice A pointer to the FvDevice. + +**/ +VOID +FwVolInheritAuthenticationStatus ( + IN FV_DEVICE *FvDevice + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *CachedFvHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *CachedFvExtHeader; + EFI_FIRMWARE_VOLUME2_PROTOCOL *ParentFvProtocol; + UINTN Key; + EFI_GUID FileNameGuid; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + UINTN FileSize; + EFI_SECTION_TYPE SectionType; + UINT32 AuthenticationStatus; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; + UINTN BufferSize; + + CachedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvDevice->CachedFv; + + if (FvDevice->Fv.ParentHandle != NULL) { + // + // By Parent Handle, find out the FV image file and section(in another firmware volume) where the firmware volume came from + // + Status = gBS->HandleProtocol (FvDevice->Fv.ParentHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &ParentFvProtocol); + if (!EFI_ERROR (Status) && (ParentFvProtocol != NULL)) { + Key = 0; + do { + FileType = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE; + Status = ParentFvProtocol->GetNextFile ( + ParentFvProtocol, + &Key, + &FileType, + &FileNameGuid, + &FileAttributes, + &FileSize + ); + if (EFI_ERROR (Status)) { + return; + } + + SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; + FvHeader = NULL; + BufferSize = 0; + Status = ParentFvProtocol->ReadSection ( + ParentFvProtocol, + &FileNameGuid, + SectionType, + 0, + (VOID **) &FvHeader, + &BufferSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + if ((FvHeader->FvLength == CachedFvHeader->FvLength) && + (FvHeader->ExtHeaderOffset == CachedFvHeader->ExtHeaderOffset)) { + if (FvHeader->ExtHeaderOffset !=0) { + // + // Both FVs contain extension header, then compare their FV Name GUID + // + FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) FvHeader + FvHeader->ExtHeaderOffset); + CachedFvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) CachedFvHeader + CachedFvHeader->ExtHeaderOffset); + if (CompareGuid (&FvExtHeader->FvName, &CachedFvExtHeader->FvName)) { + // + // Found the FV image section where the firmware volume came from, + // and then inherit authentication status from it. + // + FvDevice->AuthenticationStatus = AuthenticationStatus; + FreePool ((VOID *) FvHeader); + return; + } + } else { + // + // Both FVs don't contain extension header, then compare their whole FV Image. + // + if (CompareMem ((VOID *) FvHeader, (VOID *) CachedFvHeader, (UINTN) FvHeader->FvLength) == 0) { + // + // Found the FV image section where the firmware volume came from + // and then inherit authentication status from it. + // + FvDevice->AuthenticationStatus = AuthenticationStatus; + FreePool ((VOID *) FvHeader); + return; + } + } + } + FreePool ((VOID *) FvHeader); + } + } while (TRUE); + } + } +} + +/** + Check if an FV is consistent and allocate cache for it. + + @param FvDevice A pointer to the FvDevice to be checked. + + @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. + @retval EFI_VOLUME_CORRUPTED File system is corrupted. + @retval EFI_SUCCESS FV is consistent and cache is allocated. + +**/ +EFI_STATUS +FvCheck ( + IN FV_DEVICE *FvDevice + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FVB_ATTRIBUTES_2 FvbAttributes; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; + UINT8 *FwCache; + LBA_ENTRY *LbaEntry; + FREE_SPACE_ENTRY *FreeSpaceEntry; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + UINT8 *LbaStart; + UINTN Index; + EFI_LBA LbaIndex; + UINT8 *Ptr; + UINTN Size; + UINT8 *FreeStart; + UINTN FreeSize; + UINT8 ErasePolarity; + EFI_FFS_FILE_STATE FileState; + UINT8 *TopFvAddress; + UINTN TestLength; + EFI_PHYSICAL_ADDRESS BaseAddress; + + Fvb = FvDevice->Fvb; + + Status = Fvb->GetAttributes (Fvb, &FvbAttributes); + if (EFI_ERROR (Status)) { + return Status; + } + + InitializeListHead (&FvDevice->LbaHeader); + InitializeListHead (&FvDevice->FreeSpaceHeader); + InitializeListHead (&FvDevice->FfsFileListHeader); + + FwVolHeader = NULL; + Status = GetFwVolHeader (Fvb, &FwVolHeader); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (FwVolHeader != NULL); + + FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); + + // + // Double Check firmware volume header here + // + if (!VerifyFvHeaderChecksum (FwVolHeader)) { + FreePool (FwVolHeader); + return EFI_VOLUME_CORRUPTED; + } + + BlockMap = FwVolHeader->BlockMap; + + // + // FwVolHeader->FvLength is the whole FV length including FV header + // + FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength); + if (FwCache == NULL) { + FreePool (FwVolHeader); + return EFI_OUT_OF_RESOURCES; + } + + FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache; + + // + // Copy to memory + // + LbaStart = FwCache; + LbaIndex = 0; + Ptr = NULL; + + if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { + // + // Get volume base address + // + Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress); + if (EFI_ERROR (Status)) { + FreePool (FwVolHeader); + return Status; + } + + Ptr = (UINT8 *) ((UINTN) BaseAddress); + + DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress)); + } + // + // Copy whole FV into the memory + // + while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { + + for (Index = 0; Index < BlockMap->NumBlocks; Index++) { + LbaEntry = AllocatePool (sizeof (LBA_ENTRY)); + if (LbaEntry == NULL) { + FreePool (FwVolHeader); + FreeFvDeviceResource (FvDevice); + return EFI_OUT_OF_RESOURCES; + } + + LbaEntry->LbaIndex = LbaIndex; + LbaEntry->StartingAddress = LbaStart; + LbaEntry->BlockLength = BlockMap->Length; + + // + // Copy each LBA into memory + // + if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { + + CopyMem (LbaStart, Ptr, BlockMap->Length); + Ptr += BlockMap->Length; + + } else { + + Size = BlockMap->Length; + Status = Fvb->Read ( + Fvb, + LbaIndex, + 0, + &Size, + LbaStart + ); + // + // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length + // + if (EFI_ERROR (Status)) { + FreePool (FwVolHeader); + FreeFvDeviceResource (FvDevice); + return Status; + } + + } + + LbaIndex++; + LbaStart += BlockMap->Length; + + InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link); + } + + BlockMap++; + } + + FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache; + + // + // it is not used any more, so free FwVolHeader + // + FreePool (FwVolHeader); + + // + // Scan to check the free space & File list + // + if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + FvDevice->ErasePolarity = ErasePolarity; + + // + // go through the whole FV cache, check the consistence of the FV + // + if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) { + // + // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. + // + FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset); + Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize; + Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8); + } else { + Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength); + } + TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength); + + // + // Build FFS list & Free Space List here + // + while (Ptr < TopFvAddress) { + TestLength = TopFvAddress - Ptr; + + if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { + TestLength = sizeof (EFI_FFS_FILE_HEADER); + } + + if (IsBufferErased (ErasePolarity, Ptr, TestLength)) { + // + // We found free space + // + FreeStart = Ptr; + FreeSize = 0; + + do { + TestLength = TopFvAddress - Ptr; + + if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { + TestLength = sizeof (EFI_FFS_FILE_HEADER); + } + + if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) { + break; + } + + FreeSize += TestLength; + Ptr += TestLength; + } while (Ptr < TopFvAddress); + + FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY)); + if (FreeSpaceEntry == NULL) { + FreeFvDeviceResource (FvDevice); + return EFI_OUT_OF_RESOURCES; + } + // + // Create a Free space entry + // + FreeSpaceEntry->StartingAddress = FreeStart; + FreeSpaceEntry->Length = FreeSize; + InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link); + continue; + } + // + // double check boundry + // + if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) { + break; + } + + if (!IsValidFFSHeader ( + FvDevice->ErasePolarity, + (EFI_FFS_FILE_HEADER *) Ptr + )) { + FileState = GetFileState ( + FvDevice->ErasePolarity, + (EFI_FFS_FILE_HEADER *) Ptr + ); + if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { + if (IS_FFS_FILE2 (Ptr)) { + if (!FvDevice->IsFfs3Fv) { + DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name)); + } + Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2); + } else { + Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER); + } + + continue; + + } else { + // + // File system is corrputed, return + // + FreeFvDeviceResource (FvDevice); + return EFI_VOLUME_CORRUPTED; + } + } + + if (IS_FFS_FILE2 (Ptr)) { + ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF); + if (!FvDevice->IsFfs3Fv) { + DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name)); + Ptr = Ptr + FFS_FILE2_SIZE (Ptr); + // + // Adjust Ptr to the next 8-byte aligned boundry. + // + while (((UINTN) Ptr & 0x07) != 0) { + Ptr++; + } + continue; + } + } + + if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) { + FileState = GetFileState ( + FvDevice->ErasePolarity, + (EFI_FFS_FILE_HEADER *) Ptr + ); + + // + // check for non-deleted file + // + if (FileState != EFI_FILE_DELETED) { + // + // Create a FFS list entry for each non-deleted file + // + FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); + if (FfsFileEntry == NULL) { + FreeFvDeviceResource (FvDevice); + return EFI_OUT_OF_RESOURCES; + } + + FfsFileEntry->FfsHeader = Ptr; + InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); + } + + if (IS_FFS_FILE2 (Ptr)) { + Ptr = Ptr + FFS_FILE2_SIZE (Ptr); + } else { + Ptr = Ptr + FFS_FILE_SIZE (Ptr); + } + + // + // Adjust Ptr to the next 8-byte aligned boundry. + // + while (((UINTN) Ptr & 0x07) != 0) { + Ptr++; + } + } else { + // + // File system is corrupted, return + // + FreeFvDeviceResource (FvDevice); + return EFI_VOLUME_CORRUPTED; + } + } + + FvDevice->CurrentFfsFile = NULL; + + return EFI_SUCCESS; +} + +/** + Entry point function does install/reinstall FV2 protocol with full functionality. + + @param ImageHandle A handle for the image that is initializing this driver + @param SystemTable A pointer to the EFI system table + + @retval EFI_SUCCESS At least one Fv protocol install/reinstall successfully. + @retval EFI_NOT_FOUND No FV protocol install/reinstall successfully. +**/ +EFI_STATUS +EFIAPI +FwVolDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + FV_DEVICE *FvDevice; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + BOOLEAN Reinstall; + BOOLEAN InstallFlag; + + DEBUG ((EFI_D_INFO, "=========FwVol writable driver installed\n")); + InstallFlag = FALSE; + // + // Locate all handles of Fvb protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < HandleCount; Index += 1) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &Fvb + ); + if (EFI_ERROR (Status)) { + continue; + } + + FwVolHeader = NULL; + Status = GetFwVolHeader (Fvb, &FwVolHeader); + if (EFI_ERROR (Status)) { + continue; + } + ASSERT (FwVolHeader != NULL); + FreePool (FwVolHeader); + + Reinstall = FALSE; + // + // Check if there is an FV protocol already installed in that handle + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (!EFI_ERROR (Status)) { + Reinstall = TRUE; + } + // + // FwVol protocol on the handle so create a new one + // + FvDevice = AllocateZeroPool (sizeof (FV_DEVICE)); + if (FvDevice == NULL) { + goto Done; + } + + FvDevice->Signature = FV_DEVICE_SIGNATURE; + FvDevice->Fvb = Fvb; + + // + // Firmware Volume Protocol interface + // + FvDevice->Fv.GetVolumeAttributes = FvGetVolumeAttributes; + FvDevice->Fv.SetVolumeAttributes = FvSetVolumeAttributes; + FvDevice->Fv.ReadFile = FvReadFile; + FvDevice->Fv.ReadSection = FvReadFileSection; + FvDevice->Fv.WriteFile = FvWriteFile; + FvDevice->Fv.GetNextFile = FvGetNextFile; + FvDevice->Fv.KeySize = KEYSIZE; + FvDevice->Fv.GetInfo = FvGetVolumeInfo; + FvDevice->Fv.SetInfo = FvSetVolumeInfo; + FvDevice->Fv.ParentHandle = Fvb->ParentHandle; + + Status = FvCheck (FvDevice); + if (EFI_ERROR (Status)) { + // + // The file system is not consistence + // + FreePool (FvDevice); + continue; + } + + FwVolInheritAuthenticationStatus (FvDevice); + + if (Reinstall) { + // + // Reinstall an New FV protocol + // + // FvDevice = FV_DEVICE_FROM_THIS (Fv); + // FvDevice->Fvb = Fvb; + // FreeFvDeviceResource (FvDevice); + // + Status = gBS->ReinstallProtocolInterface ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + Fv, + &FvDevice->Fv + ); + if (!EFI_ERROR (Status)) { + InstallFlag = TRUE; + } else { + FreePool (FvDevice); + } + + DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status)); + ASSERT_EFI_ERROR (Status); + } else { + // + // Install an New FV protocol + // + Status = gBS->InstallProtocolInterface ( + &FvDevice->Handle, + &gEfiFirmwareVolume2ProtocolGuid, + EFI_NATIVE_INTERFACE, + &FvDevice->Fv + ); + if (!EFI_ERROR (Status)) { + InstallFlag = TRUE; + } else { + FreePool (FvDevice); + } + + DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status)); + ASSERT_EFI_ERROR (Status); + } + } + +Done: + // + // As long as one Fv protocol install/reinstall successfully, + // success should return to ensure this image will be not unloaded. + // Otherwise, new Fv protocols are corrupted by other loaded driver. + // + if (InstallFlag) { + return EFI_SUCCESS; + } + + // + // No FV protocol install/reinstall successfully. + // EFI_NOT_FOUND should return to ensure this image will be unloaded. + // + return EFI_NOT_FOUND; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolAttrib.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolAttrib.c new file mode 100644 index 0000000000..0e4ddf8bea --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolAttrib.c @@ -0,0 +1,220 @@ +/** @file + + Implements get/set firmware volume attributes. + + Copyright (c) 2006 - 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 "FwVolDriver.h" + +/** + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter. + + @param This Calling context + @param Attributes output buffer which contains attributes + + @retval EFI_SUCCESS Successfully got volume attributes + +**/ +EFI_STATUS +EFIAPI +FvGetVolumeAttributes ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + OUT EFI_FV_ATTRIBUTES *Attributes + ) +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FVB_ATTRIBUTES_2 FvbAttributes; + + FvDevice = FV_DEVICE_FROM_THIS (This); + Fvb = FvDevice->Fvb; + + // + // First get the Firmware Volume Block Attributes + // + Status = Fvb->GetAttributes (Fvb, &FvbAttributes); + FvbAttributes &= 0xfffff0ff; + + *Attributes = FvbAttributes; + *Attributes |= EFI_FV2_WRITE_POLICY_RELIABLE; + return Status; +} + +/** + Sets current attributes for volume. + + @param This Calling context + @param Attributes On input, FvAttributes is a pointer to + an EFI_FV_ATTRIBUTES containing the + desired firmware volume settings. On + successful return, it contains the new + settings of the firmware volume. On + unsuccessful return, FvAttributes is not + modified and the firmware volume + settings are not changed. + + @retval EFI_SUCCESS The requested firmware volume attributes + were set and the resulting + EFI_FV_ATTRIBUTES is returned in + FvAttributes. + @retval EFI_ACCESS_DENIED Atrribute is locked down. + @retval EFI_INVALID_PARAMETER Atrribute is not valid. + +**/ +EFI_STATUS +EFIAPI +FvSetVolumeAttributes ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN OUT EFI_FV_ATTRIBUTES *Attributes + ) +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FVB_ATTRIBUTES_2 OldFvbAttributes; + EFI_FVB_ATTRIBUTES_2 NewFvbAttributes; + UINT64 NewStatus; + UINT32 Capabilities; + + FvDevice = FV_DEVICE_FROM_THIS (This); + Fvb = FvDevice->Fvb; + + // + // First get the current Volume Attributes + // + Status = Fvb->GetAttributes ( + Fvb, + &OldFvbAttributes + ); + + if ((OldFvbAttributes & EFI_FVB2_LOCK_STATUS) != 0) { + return EFI_ACCESS_DENIED; + } + // + // Only status attributes can be updated. + // + Capabilities = OldFvbAttributes & EFI_FVB2_CAPABILITIES; + NewStatus = (*Attributes) & EFI_FVB2_STATUS; + + // + // 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) != 0) { + 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) != 0) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test lock + // + if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { + if ((NewStatus & EFI_FVB2_LOCK_STATUS) != 0) { + return EFI_INVALID_PARAMETER; + } + } + + NewFvbAttributes = OldFvbAttributes & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); + NewFvbAttributes |= NewStatus; + Status = Fvb->SetAttributes ( + Fvb, + &NewFvbAttributes + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + *Attributes = 0; + + This->GetVolumeAttributes ( + This, + Attributes + ); + + return EFI_SUCCESS; +} + +/** + Return information of type InformationType for the requested firmware + volume. + + @param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL. + @param InformationType InformationType for requested. + @param BufferSize On input, size of Buffer.On output, the amount of + data returned in Buffer. + @param Buffer A poniter to the data buffer to return. + + @return EFI_UNSUPPORTED Could not get. + +**/ +EFI_STATUS +EFIAPI +FvGetVolumeInfo ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Set information with InformationType into the requested firmware volume. + + @param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL. + @param InformationType InformationType for requested. + @param BufferSize Size of Buffer data. + @param Buffer A poniter to the data buffer to be set. + + @retval EFI_UNSUPPORTED Could not set. + +**/ +EFI_STATUS +EFIAPI +FvSetVolumeInfo ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *InformationType, + IN UINTN BufferSize, + IN CONST VOID *Buffer + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDriver.h b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDriver.h new file mode 100644 index 0000000000..b1646dd39e --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDriver.h @@ -0,0 +1,761 @@ +/** @file + Common defines and definitions for a FwVolDxe driver. + + Copyright (c) 2006 - 2015, Intel 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 _FWVOL_DRIVER_H_ +#define _FWVOL_DRIVER_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define FV_DEVICE_SIGNATURE SIGNATURE_32 ('_', 'F', 'V', '_') + +// +// 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) + +#define MAX_FILES 32 + +// +// Used to calculate from address -> Lba +// +typedef struct { + LIST_ENTRY Link; + EFI_LBA LbaIndex; + UINT8 *StartingAddress; + UINTN BlockLength; +} LBA_ENTRY; + +// +// Used to track free space in the Fv +// +typedef struct { + LIST_ENTRY Link; + UINT8 *StartingAddress; + UINTN Length; +} FREE_SPACE_ENTRY; + +// +// Used to track all non-deleted files +// +typedef struct { + LIST_ENTRY Link; + UINT8 *FfsHeader; +} FFS_FILE_LIST_ENTRY; + +typedef struct { + UINTN Signature; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME2_PROTOCOL Fv; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINT8 *Key; + EFI_HANDLE Handle; + + UINT8 ErasePolarity; + EFI_PHYSICAL_ADDRESS CachedFv; + LIST_ENTRY LbaHeader; + LIST_ENTRY FreeSpaceHeader; + LIST_ENTRY FfsFileListHeader; + + FFS_FILE_LIST_ENTRY *CurrentFfsFile; + BOOLEAN IsFfs3Fv; + UINT32 AuthenticationStatus; +} FV_DEVICE; + +#define FV_DEVICE_FROM_THIS(a) CR (a, FV_DEVICE, Fv, FV_DEVICE_SIGNATURE) + +/** + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter. + + @param This Calling context + @param Attributes output buffer which contains attributes + + @retval EFI_SUCCESS Successfully got volume attributes + +**/ +EFI_STATUS +EFIAPI +FvGetVolumeAttributes ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + OUT EFI_FV_ATTRIBUTES *Attributes + ); + +/** + Sets current attributes for volume. + + @param This Calling context + @param Attributes On input, FvAttributes is a pointer to + an EFI_FV_ATTRIBUTES containing the + desired firmware volume settings. On + successful return, it contains the new + settings of the firmware volume. On + unsuccessful return, FvAttributes is not + modified and the firmware volume + settings are not changed. + + @retval EFI_SUCCESS The requested firmware volume attributes + were set and the resulting + EFI_FV_ATTRIBUTES is returned in + FvAttributes. + @retval EFI_ACCESS_DENIED Atrribute is locked down. + @retval EFI_INVALID_PARAMETER Atrribute is not valid. + +**/ +EFI_STATUS +EFIAPI +FvSetVolumeAttributes ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN OUT EFI_FV_ATTRIBUTES *Attributes + ); + +/** + Given the input key, search for the next matching file in the volume. + + @param This Indicates the calling context. + @param Key Key is a pointer to a caller allocated + buffer that contains implementation specific + data that is used to track where to begin + the search for the next file. The size of + the buffer must be at least This->KeySize + bytes long. To reinitialize the search and + begin from the beginning of the firmware + volume, the entire buffer must be cleared to + zero. Other than clearing the buffer to + initiate a new search, the caller must not + modify the data in the buffer between calls + to GetNextFile(). + @param FileType FileType is a pointer to a caller allocated + EFI_FV_FILETYPE. The GetNextFile() API can + filter it's search for files based on the + value of *FileType input. A *FileType input + of 0 causes GetNextFile() to search for + files of all types. If a file is found, the + file's type is returned in *FileType. + *FileType is not modified if no file is + found. + @param NameGuid NameGuid is a pointer to a caller allocated + EFI_GUID. If a file is found, the file's + name is returned in *NameGuid. *NameGuid is + not modified if no file is found. + @param Attributes Attributes is a pointer to a caller + allocated EFI_FV_FILE_ATTRIBUTES. If a file + is found, the file's attributes are returned + in *Attributes. *Attributes is not modified + if no file is found. + @param Size Size is a pointer to a caller allocated + UINTN. If a file is found, the file's size + is returned in *Size. *Size is not modified + if no file is found. + + @retval EFI_SUCCESS Successfully find the file. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_ACCESS_DENIED Fv could not read. + @retval EFI_NOT_FOUND No matching file found. + @retval EFI_INVALID_PARAMETER Invalid parameter + +**/ +EFI_STATUS +EFIAPI +FvGetNextFile ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN OUT VOID *Key, + IN OUT EFI_FV_FILETYPE *FileType, + OUT EFI_GUID *NameGuid, + OUT EFI_FV_FILE_ATTRIBUTES *Attributes, + OUT UINTN *Size + ); + +/** + Locates a file in the firmware volume and + copies it to the supplied buffer. + + @param This Indicates the calling context. + @param NameGuid Pointer to an EFI_GUID, which is the + filename. + @param Buffer Buffer is a pointer to pointer to a buffer + in which the file or section contents or are + returned. + @param BufferSize BufferSize is a pointer to caller allocated + UINTN. On input *BufferSize indicates the + size in bytes of the memory region pointed + to by Buffer. On output, *BufferSize + contains the number of bytes required to + read the file. + @param FoundType FoundType is a pointer to a caller allocated + EFI_FV_FILETYPE that on successful return + from Read() contains the type of file read. + This output reflects the file type + irrespective of the value of the SectionType + input. + @param FileAttributes FileAttributes is a pointer to a caller + allocated EFI_FV_FILE_ATTRIBUTES. On + successful return from Read(), + *FileAttributes contains the attributes of + the file read. + @param AuthenticationStatus AuthenticationStatus is a pointer to a + caller allocated UINTN in which the + authentication status is returned. + + @retval EFI_SUCCESS Successfully read to memory buffer. + @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small. + @retval EFI_NOT_FOUND Not found. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_ACCESS_DENIED Could not read. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. + +**/ +EFI_STATUS +EFIAPI +FvReadFile ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT EFI_FV_FILETYPE *FoundType, + OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, + OUT UINT32 *AuthenticationStatus + ); + +/** + Locates a section in a given FFS File and + copies it to the supplied buffer (not including section header). + + @param This Indicates the calling context. + @param NameGuid Pointer to an EFI_GUID, which is the + filename. + @param SectionType Indicates the section type to return. + @param SectionInstance Indicates which instance of sections with a + type of SectionType to return. + @param Buffer Buffer is a pointer to pointer to a buffer + in which the file or section contents or are + returned. + @param BufferSize BufferSize is a pointer to caller allocated + UINTN. + @param AuthenticationStatus AuthenticationStatus is a pointer to a + caller allocated UINT32 in which the + authentication status is returned. + + @retval EFI_SUCCESS Successfully read the file section into + buffer. + @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small. + @retval EFI_NOT_FOUND Section not found. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_ACCESS_DENIED Could not read. + @retval EFI_INVALID_PARAMETER Invalid parameter. + +**/ +EFI_STATUS +EFIAPI +FvReadFileSection ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ); + +/** + Writes one or more files to the firmware volume. + + @param This Indicates the calling context. + @param NumberOfFiles Number of files. + @param WritePolicy WritePolicy indicates the level of reliability + for the write in the event of a power failure or + other system failure during the write operation. + @param FileData FileData is an pointer to an array of + EFI_FV_WRITE_DATA. Each element of array + FileData represents a file to be written. + + @retval EFI_SUCCESS Files successfully written to firmware volume + @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_WRITE_PROTECTED Write protected. + @retval EFI_NOT_FOUND Not found. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_UNSUPPORTED This function not supported. + +**/ +EFI_STATUS +EFIAPI +FvWriteFile ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN EFI_FV_WRITE_POLICY WritePolicy, + IN EFI_FV_WRITE_FILE_DATA *FileData + ); + +/** + Return information of type InformationType for the requested firmware + volume. + + @param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL. + @param InformationType InformationType for requested. + @param BufferSize On input, size of Buffer.On output, the amount of + data returned in Buffer. + @param Buffer A poniter to the data buffer to return. + + @return EFI_UNSUPPORTED Could not get. + +**/ +EFI_STATUS +EFIAPI +FvGetVolumeInfo ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + + +/** + Set information with InformationType into the requested firmware volume. + + @param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL. + @param InformationType InformationType for requested. + @param BufferSize Size of Buffer data. + @param Buffer A poniter to the data buffer to be set. + + @retval EFI_UNSUPPORTED Could not set. + +**/ +EFI_STATUS +EFIAPI +FvSetVolumeInfo ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *InformationType, + IN UINTN BufferSize, + IN CONST VOID *Buffer + ); + +/** + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when the firmware end is + reached. *NumBytes is updated to reflect the actual number of bytes + written. + + @param FvDevice Cached Firmware Volume + @param Offset Offset in the block at which to begin write + @param NumBytes At input, indicates the requested write size. + At output, indicates the actual number of bytes written. + @param Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS Data is successfully written into FV. + @return error Data is failed written. + +**/ +EFI_STATUS +FvcWrite ( + IN FV_DEVICE *FvDevice, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + + +/** + Check if a block of buffer is erased. + + @param ErasePolarity Erase polarity attribute of the firmware volume + @param Buffer The buffer to be checked + @param BufferSize Size of the buffer in bytes + + @retval TRUE The block of buffer is erased + @retval FALSE The block of buffer is not erased + +**/ +BOOLEAN +IsBufferErased ( + IN UINT8 ErasePolarity, + IN UINT8 *Buffer, + IN UINTN BufferSize + ); + +/** + Get the FFS file state by checking the highest bit set in the header's state field. + + @param ErasePolarity Erase polarity attribute of the firmware volume + @param FfsHeader Points to the FFS file header + + @return FFS File state + +**/ +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ); + +/** + Verify checksum of the firmware volume header. + + @param FvHeader Points to the firmware volume header to be checked + + @retval TRUE Checksum verification passed + @retval FALSE Checksum verification failed + +**/ +BOOLEAN +VerifyFvHeaderChecksum ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ); + +/** + Check if it's a valid FFS file header. + + @param ErasePolarity Erase polarity attribute of the firmware volume + @param FfsHeader Points to the FFS file header to be checked + + @retval TRUE Valid FFS file header + @retval FALSE Invalid FFS file header + +**/ +BOOLEAN +IsValidFFSHeader ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ); + +/** + Check if it's a valid FFS file. + Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first. + + @param FvDevice Cached FV image. + @param FfsHeader Points to the FFS file to be checked + + @retval TRUE Valid FFS file + @retval FALSE Invalid FFS file + +**/ +BOOLEAN +IsValidFFSFile ( + IN FV_DEVICE *FvDevice, + IN EFI_FFS_FILE_HEADER *FfsHeader + ); + +/** + Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and + copy the real length volume header into it. + + @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to + read the volume header + @param FwVolHeader Pointer to pointer to allocated buffer in which + the volume header is returned. + + @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. + @retval EFI_SUCCESS Successfully read volume header to the allocated + buffer. + @retval EFI_ACCESS_DENIED Read status of FV is not enabled. + @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or + the file system could not be understood. +**/ +EFI_STATUS +GetFwVolHeader ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, + OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ); + +/** + Convert the Buffer Address to LBA Entry Address. + + @param FvDevice Cached FvDevice + @param BufferAddress Address of Buffer + @param LbaListEntry Pointer to the got LBA entry that contains the address. + + @retval EFI_NOT_FOUND Buffer address is out of FvDevice. + @retval EFI_SUCCESS LBA entry is found for Buffer address. + +**/ +EFI_STATUS +Buffer2LbaEntry ( + IN FV_DEVICE *FvDevice, + IN EFI_PHYSICAL_ADDRESS BufferAddress, + OUT LBA_ENTRY **LbaListEntry + ); + +/** + Convert the Buffer Address to LBA Address & Offset. + + @param FvDevice Cached FvDevice + @param BufferAddress Address of Buffer + @param Lba Pointer to the gob Lba value + @param Offset Pointer to the got Offset + + @retval EFI_NOT_FOUND Buffer address is out of FvDevice. + @retval EFI_SUCCESS LBA and Offset is found for Buffer address. + +**/ +EFI_STATUS +Buffer2Lba ( + IN FV_DEVICE *FvDevice, + IN EFI_PHYSICAL_ADDRESS BufferAddress, + OUT EFI_LBA *Lba, + OUT UINTN *Offset + ); + +/** + Set File State in the FfsHeader. + + @param State File state to be set into FFS header. + @param FfsHeader Points to the FFS file header + +**/ +VOID +SetFileState ( + IN UINT8 State, + IN EFI_FFS_FILE_HEADER *FfsHeader + ); + +/** + Create a PAD File in the Free Space. + + @param FvDevice Firmware Volume Device. + @param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted. + @param Size Pad file Size, not include the header. + @param PadFileEntry The Ffs File Entry that points to this Pad File. + + @retval EFI_SUCCESS Successfully create a PAD file. + @retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file. + @retval EFI_INVALID_PARAMETER Size is not 8 byte alignment. + @retval EFI_DEVICE_ERROR Free space is not erased. +**/ +EFI_STATUS +FvCreatePadFileInFreeSpace ( + IN FV_DEVICE *FvDevice, + IN FREE_SPACE_ENTRY *FreeSpaceEntry, + IN UINTN Size, + OUT FFS_FILE_LIST_ENTRY **PadFileEntry + ); + +/** + Create a new file within a PAD file area. + + @param FvDevice Firmware Volume Device. + @param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state). + @param BufferSize The size of FfsFileBuffer. + @param ActualFileSize The actual file length, it may not be multiples of 8. + @param FileName The FFS File Name. + @param FileType The FFS File Type. + @param FileAttributes The Attributes of the FFS File to be created. + + @retval EFI_SUCCESS Successfully create a new file within the found PAD file area. + @retval EFI_OUT_OF_RESOURCES No suitable PAD file is found. + @retval other errors New file is created failed. + +**/ +EFI_STATUS +FvCreateNewFileInsidePadFile ( + IN FV_DEVICE *FvDevice, + IN UINT8 *FfsFileBuffer, + IN UINTN BufferSize, + IN UINTN ActualFileSize, + IN EFI_GUID *FileName, + IN EFI_FV_FILETYPE FileType, + IN EFI_FV_FILE_ATTRIBUTES FileAttributes + ); + +/** + Write multiple files into FV in reliable method. + + @param FvDevice Firmware Volume Device. + @param NumOfFiles Total File number to be written. + @param FileData The array of EFI_FV_WRITE_FILE_DATA structure, + used to get name, attributes, type, etc + @param FileOperation The array of operation for each file. + + @retval EFI_SUCCESS Files are added into FV. + @retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files. + @retval EFI_INVALID_PARAMETER File number is less than or equal to 1. + @retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files. + +**/ +EFI_STATUS +FvCreateMultipleFiles ( + IN FV_DEVICE *FvDevice, + IN UINTN NumOfFiles, + IN EFI_FV_WRITE_FILE_DATA *FileData, + IN BOOLEAN *FileOperation + ); + +/** + Calculate the checksum for the FFS header. + + @param FfsHeader FFS File Header which needs to calculate the checksum + +**/ +VOID +SetHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ); + +/** + Calculate the checksum for the FFS File. + + @param FfsHeader FFS File Header which needs to calculate the checksum + @param ActualFileSize The whole Ffs File Length. + +**/ +VOID +SetFileChecksum ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN UINTN ActualFileSize + ); + +/** + Get the alignment value from File Attributes. + + @param FfsAttributes FFS attribute + + @return Alignment value. + +**/ +UINTN +GetRequiredAlignment ( + IN EFI_FV_FILE_ATTRIBUTES FfsAttributes + ); + +/** + Locate Pad File for writing, this is got from FV Cache. + + @param FvDevice Cached Firmware Volume. + @param Size The required FFS file size. + @param RequiredAlignment FFS File Data alignment requirement. + @param PadSize Pointer to the size of leading Pad File. + @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. + + @retval EFI_SUCCESS The required pad file is found. + @retval EFI_NOT_FOUND The required pad file can't be found. + +**/ +EFI_STATUS +FvLocatePadFile ( + IN FV_DEVICE *FvDevice, + IN UINTN Size, + IN UINTN RequiredAlignment, + OUT UINTN *PadSize, + OUT FFS_FILE_LIST_ENTRY **PadFileEntry + ); + +/** + Locate a suitable pad file for multiple file writing. + + @param FvDevice Cached Firmware Volume. + @param NumOfFiles The number of Files that needed updating + @param BufferSize The array of each file size. + @param RequiredAlignment The array of of FFS File Data alignment requirement. + @param PadSize The array of size of each leading Pad File. + @param TotalSizeNeeded The totalsize that can hold these files. + @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. + + @retval EFI_SUCCESS The required pad file is found. + @retval EFI_NOT_FOUND The required pad file can't be found. + +**/ +EFI_STATUS +FvSearchSuitablePadFile ( + IN FV_DEVICE *FvDevice, + IN UINTN NumOfFiles, + IN UINTN *BufferSize, + IN UINTN *RequiredAlignment, + OUT UINTN *PadSize, + OUT UINTN *TotalSizeNeeded, + OUT FFS_FILE_LIST_ENTRY **PadFileEntry + ); + +/** + Locate a Free Space entry which can hold these files, including + meeting the alignment requirements. + + @param FvDevice Cached Firmware Volume. + @param NumOfFiles The number of Files that needed updating + @param BufferSize The array of each file size. + @param RequiredAlignment The array of of FFS File Data alignment requirement. + @param PadSize The array of size of each leading Pad File. + @param TotalSizeNeeded The got total size that can hold these files. + @param FreeSpaceEntry The Free Space Entry that can hold these files. + + @retval EFI_SUCCESS The free space entry is found. + @retval EFI_NOT_FOUND The free space entry can't be found. + +**/ +EFI_STATUS +FvSearchSuitableFreeSpace ( + IN FV_DEVICE *FvDevice, + IN UINTN NumOfFiles, + IN UINTN *BufferSize, + IN UINTN *RequiredAlignment, + OUT UINTN *PadSize, + OUT UINTN *TotalSizeNeeded, + OUT FREE_SPACE_ENTRY **FreeSpaceEntry + ); + +/** + Change FFS file header state and write to FV. + + @param FvDevice Cached FV image. + @param FfsHeader Points to the FFS file header to be updated. + @param State FFS file state to be set. + + @retval EFI_SUCCESS File state is writen into FV. + @retval others File state can't be writen into FV. + +**/ +EFI_STATUS +UpdateHeaderBit ( + IN FV_DEVICE *FvDevice, + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_FFS_FILE_STATE State + ); + +/** + Convert EFI_FV_FILE_ATTRIBUTES to FFS_FILE_ATTRIBUTES. + + @param FvFileAttrib The value of EFI_FV_FILE_ATTRIBUTES + @param FfsFileAttrib Pointer to the got FFS_FILE_ATTRIBUTES value. + +**/ +VOID +FvFileAttrib2FfsFileAttrib ( + IN EFI_FV_FILE_ATTRIBUTES FvFileAttrib, + OUT UINT8 *FfsFileAttrib + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf new file mode 100644 index 0000000000..057266bb2b --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf @@ -0,0 +1,74 @@ +## @file +# FwVolDxe Driver. +# +# This driver produces Firmware Volume2 protocol with full services +# (read/write, get/set) based on Firmware Volume Block 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 +# 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 = FwVolDxe + MODULE_UNI_FILE = FwVolDxe.uni + FILE_GUID = 233C2592-1CEC-494a-A097-15DC96379777 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = FwVolDriverInit + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + FwVolDriver.h + FwPadFile.c + Ffs.c + FwVolWrite.c + FwVolRead.c + FwVolAttrib.c + FwVol.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + + +[Guids] + gEfiFirmwareVolumeTopFileGuid ## CONSUMES ## File # VTF file + gEfiFirmwareFileSystem2Guid ## CONSUMES ## GUID # File System Guid + gEfiFirmwareFileSystem3Guid ## CONSUMES ## GUID # File System Guid + +[Protocols] + gEfiSectionExtractionProtocolGuid ## CONSUMES + gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES + gEfiFirmwareVolume2ProtocolGuid ## PRODUCES + +[Depex] + gEfiFirmwareVolumeBlockProtocolGuid AND gEfiSectionExtractionProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + FwVolDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni new file mode 100644 index 0000000000..89e44a4471 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni new file mode 100644 index 0000000000..b008de7a93 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolRead.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolRead.c new file mode 100644 index 0000000000..8e2706bb8a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolRead.c @@ -0,0 +1,629 @@ +/** @file + Implements functions to read firmware file. + + 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 "FwVolDriver.h" + +/** +Required Alignment Alignment Value in FFS Alignment Value in +(bytes) Attributes Field Firmware Volume Interfaces +1 0 0 +16 1 4 +128 2 7 +512 3 9 +1 KB 4 10 +4 KB 5 12 +32 KB 6 15 +64 KB 7 16 +**/ +UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16}; + +/** + Convert the FFS File Attributes to FV File Attributes. + + @param FfsAttributes The attributes of UINT8 type. + + @return The attributes of EFI_FV_FILE_ATTRIBUTES + +**/ +EFI_FV_FILE_ATTRIBUTES +FfsAttributes2FvFileAttributes ( + IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes + ) +{ + UINT8 DataAlignment; + EFI_FV_FILE_ATTRIBUTES FileAttribute; + + DataAlignment = (UINT8) ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3); + ASSERT (DataAlignment < 8); + + FileAttribute = (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[DataAlignment]; + + if ((FfsAttributes & FFS_ATTRIB_FIXED) == FFS_ATTRIB_FIXED) { + FileAttribute |= EFI_FV_FILE_ATTRIB_FIXED; + } + + return FileAttribute; +} + +/** + Given the input key, search for the next matching file in the volume. + + @param This Indicates the calling context. + @param Key Key is a pointer to a caller allocated + buffer that contains implementation specific + data that is used to track where to begin + the search for the next file. The size of + the buffer must be at least This->KeySize + bytes long. To reinitialize the search and + begin from the beginning of the firmware + volume, the entire buffer must be cleared to + zero. Other than clearing the buffer to + initiate a new search, the caller must not + modify the data in the buffer between calls + to GetNextFile(). + @param FileType FileType is a pointer to a caller allocated + EFI_FV_FILETYPE. The GetNextFile() API can + filter it's search for files based on the + value of *FileType input. A *FileType input + of 0 causes GetNextFile() to search for + files of all types. If a file is found, the + file's type is returned in *FileType. + *FileType is not modified if no file is + found. + @param NameGuid NameGuid is a pointer to a caller allocated + EFI_GUID. If a file is found, the file's + name is returned in *NameGuid. *NameGuid is + not modified if no file is found. + @param Attributes Attributes is a pointer to a caller + allocated EFI_FV_FILE_ATTRIBUTES. If a file + is found, the file's attributes are returned + in *Attributes. *Attributes is not modified + if no file is found. + @param Size Size is a pointer to a caller allocated + UINTN. If a file is found, the file's size + is returned in *Size. *Size is not modified + if no file is found. + + @retval EFI_SUCCESS Successfully find the file. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_ACCESS_DENIED Fv could not read. + @retval EFI_NOT_FOUND No matching file found. + @retval EFI_INVALID_PARAMETER Invalid parameter + +**/ +EFI_STATUS +EFIAPI +FvGetNextFile ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN OUT VOID *Key, + IN OUT EFI_FV_FILETYPE *FileType, + OUT EFI_GUID *NameGuid, + OUT EFI_FV_FILE_ATTRIBUTES *Attributes, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FV_ATTRIBUTES FvAttributes; + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINTN *KeyValue; + LIST_ENTRY *Link; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + + FvDevice = FV_DEVICE_FROM_THIS (This); + + Status = This->GetVolumeAttributes (This, &FvAttributes); + if (EFI_ERROR (Status)) { + return Status; + } + + KeyValue = (UINTN *) Key; + FfsFileHeader = NULL; + + // + // Check if read operation is enabled + // + if ((FvAttributes & EFI_FV2_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + if (*FileType > EFI_FV_FILETYPE_SMM_CORE) { + // + // File type needs to be in 0 - 0x0D + // + return EFI_NOT_FOUND; + } + + do { + if (*KeyValue == 0) { + // + // Search for 1st matching file + // + Link = &FvDevice->FfsFileListHeader; + if (Link->ForwardLink == &FvDevice->FfsFileListHeader) { + return EFI_NOT_FOUND; + } + + FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Link->ForwardLink; + FfsFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; + + // + // remember the key + // + *KeyValue = (UINTN) FfsFileEntry; + + // + // we ignore pad files + // + if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { + continue; + } + + if (*FileType == 0) { + break; + } + + if (*FileType == FfsFileHeader->Type) { + break; + } + + } else { + // + // Getting link from last Ffs + // + Link = (LIST_ENTRY *) (*KeyValue); + if (Link->ForwardLink == &FvDevice->FfsFileListHeader) { + return EFI_NOT_FOUND; + } + + FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Link->ForwardLink; + FfsFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; + + // + // remember the key + // + *KeyValue = (UINTN) FfsFileEntry; + + // + // we ignore pad files + // + if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { + continue; + } + + if (*FileType == EFI_FV_FILETYPE_ALL) { + break; + } + + if (*FileType == FfsFileHeader->Type) { + break; + } + } + } while (Link->ForwardLink != &FvDevice->FfsFileListHeader); + + // + // Cache this file entry + // + FvDevice->CurrentFfsFile = FfsFileEntry; + + *FileType = FfsFileHeader->Type; + CopyGuid (NameGuid, &FfsFileHeader->Name); + *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes); + if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) { + *Attributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED; + } + + // + // we need to substract the header size + // + if (IS_FFS_FILE2 (FfsFileHeader)) { + *Size = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2); + } else { + *Size = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER); + } + + if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid, NameGuid)) { + // + // specially deal with VTF file + // + UINT8 *SrcPtr; + UINT32 Tmp; + + if (IS_FFS_FILE2 (FfsFileHeader)) { + SrcPtr = ((UINT8 *) FfsFileHeader) + sizeof (EFI_FFS_FILE_HEADER2); + } else { + SrcPtr = ((UINT8 *) FfsFileHeader) + sizeof (EFI_FFS_FILE_HEADER); + } + + while (*Size >= 4) { + Tmp = *(UINT32 *) SrcPtr; + if (Tmp == 0) { + SrcPtr += 4; + (*Size) -= 4; + } else { + break; + } + } + } + + return EFI_SUCCESS; +} + +/** + Locates a file in the firmware volume and + copies it to the supplied buffer. + + @param This Indicates the calling context. + @param NameGuid Pointer to an EFI_GUID, which is the + filename. + @param Buffer Buffer is a pointer to pointer to a buffer + in which the file or section contents or are + returned. + @param BufferSize BufferSize is a pointer to caller allocated + UINTN. On input *BufferSize indicates the + size in bytes of the memory region pointed + to by Buffer. On output, *BufferSize + contains the number of bytes required to + read the file. + @param FoundType FoundType is a pointer to a caller allocated + EFI_FV_FILETYPE that on successful return + from Read() contains the type of file read. + This output reflects the file type + irrespective of the value of the SectionType + input. + @param FileAttributes FileAttributes is a pointer to a caller + allocated EFI_FV_FILE_ATTRIBUTES. On + successful return from Read(), + *FileAttributes contains the attributes of + the file read. + @param AuthenticationStatus AuthenticationStatus is a pointer to a + caller allocated UINTN in which the + authentication status is returned. + + @retval EFI_SUCCESS Successfully read to memory buffer. + @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small. + @retval EFI_NOT_FOUND Not found. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_ACCESS_DENIED Could not read. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. + +**/ +EFI_STATUS +EFIAPI +FvReadFile ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT EFI_FV_FILETYPE *FoundType, + OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, + OUT UINT32 *AuthenticationStatus + ) +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + UINTN Key; + EFI_GUID SearchNameGuid; + EFI_FV_ATTRIBUTES FvAttributes; + EFI_FV_FILETYPE LocalFoundType; + EFI_FV_FILE_ATTRIBUTES LocalAttributes; + UINTN FileSize; + UINT8 *SrcPtr; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + EFI_FFS_FILE_HEADER *FfsHeader; + UINT8 *FileBuffer; + + if (NULL == This || NULL == NameGuid) { + return EFI_INVALID_PARAMETER; + } + + FvDevice = FV_DEVICE_FROM_THIS (This); + + Status = This->GetVolumeAttributes (This, &FvAttributes); + if (EFI_ERROR (Status)) { + return Status; + } + // + // First check to see that FV is enabled for reads... + // + if (0 == (FvAttributes & EFI_FV2_READ_STATUS)) { + return EFI_ACCESS_DENIED; + } + + FfsHeader = NULL; + + // + // Check if the file was read last time. + // + FfsFileEntry = FvDevice->CurrentFfsFile; + + if (FfsFileEntry != NULL) { + FfsHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; + } + + if ((FfsFileEntry == NULL) || (!CompareGuid (&FfsHeader->Name, NameGuid))) { + // + // If not match or no file cached, search this file + // + Key = 0; + do { + LocalFoundType = 0; + Status = This->GetNextFile ( + This, + &Key, + &LocalFoundType, + &SearchNameGuid, + &LocalAttributes, + &FileSize + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } while (!CompareGuid (&SearchNameGuid, NameGuid)); + + // + // Get file entry + // + FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key; + + // + // Update the cache + // + FvDevice->CurrentFfsFile = FfsFileEntry; + + FfsHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; + + } else { + // + // Get File Size of the cached file + // + if (IS_FFS_FILE2 (FfsHeader)) { + FileSize = FFS_FILE2_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER2); + } else { + FileSize = FFS_FILE_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER); + } + } + // + // Get file info + // + *FoundType = FfsHeader->Type; + *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes); + if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) { + *FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED; + } + *AuthenticationStatus = 0; + + // + // If Buffer is NULL, we only want to get some information + // + if (Buffer == NULL) { + *BufferSize = FileSize; + return EFI_SUCCESS; + } + + if (IS_FFS_FILE2 (FfsHeader)) { + SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2); + } else { + SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER); + } + + if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid, NameGuid)) { + // + // specially deal with VTF file + // + UINT32 Tmp; + + while (FileSize >= 4) { + Tmp = *(UINT32 *) SrcPtr; + if (Tmp == 0) { + SrcPtr += 4; + FileSize -= 4; + } else { + break; + } + } + } + // + // If we drop out of the above loop, we've found the correct file header... + // + if (*Buffer == NULL) { + FileBuffer = AllocateCopyPool (FileSize, SrcPtr); + if (FileBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *BufferSize = FileSize; + *Buffer = FileBuffer; + + return EFI_SUCCESS; + } + // + // If the user's buffer is smaller than the file size, then copy as much + // as we can and return an appropriate status. + // + if (FileSize > *BufferSize) { + CopyMem (*Buffer, SrcPtr, *BufferSize); + *BufferSize = FileSize; + return EFI_WARN_BUFFER_TOO_SMALL; + } + // + // User's buffer size is ok, so copy the entire file to their buffer. + // + *BufferSize = FileSize; + CopyMem (*Buffer, SrcPtr, *BufferSize); + + return EFI_SUCCESS; +} + +/** + Locates a section in a given FFS File and + copies it to the supplied buffer (not including section header). + + @param This Indicates the calling context. + @param NameGuid Pointer to an EFI_GUID, which is the + filename. + @param SectionType Indicates the section type to return. + @param SectionInstance Indicates which instance of sections with a + type of SectionType to return. + @param Buffer Buffer is a pointer to pointer to a buffer + in which the file or section contents or are + returned. + @param BufferSize BufferSize is a pointer to caller allocated + UINTN. + @param AuthenticationStatus AuthenticationStatus is a pointer to a + caller allocated UINT32 in which the + authentication status is returned. + + @retval EFI_SUCCESS Successfully read the file section into + buffer. + @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small. + @retval EFI_NOT_FOUND Section not found. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_ACCESS_DENIED Could not read. + @retval EFI_INVALID_PARAMETER Invalid parameter. + +**/ +EFI_STATUS +EFIAPI +FvReadFileSection ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ) +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FV_ATTRIBUTES FvAttributes; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + UINTN FileSize; + UINT8 *FileBuffer; + EFI_SECTION_EXTRACTION_PROTOCOL *Sep; + UINTN StreamHandle; + + if (NULL == This || NULL == NameGuid || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + FvDevice = FV_DEVICE_FROM_THIS (This); + + Status = This->GetVolumeAttributes (This, &FvAttributes); + if (EFI_ERROR (Status)) { + return Status; + } + // + // First check to see that FV is enabled for reads... + // + if (0 == (FvAttributes & EFI_FV2_READ_STATUS)) { + return EFI_ACCESS_DENIED; + } + // + // Read the whole file into buffer + // + FileBuffer = NULL; + Status = This->ReadFile ( + This, + NameGuid, + (VOID **) &FileBuffer, + &FileSize, + &FileType, + &FileAttributes, + AuthenticationStatus + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check to see that the file actually HAS sections before we go any further. + // + if (FileType == EFI_FV_FILETYPE_RAW) { + FreePool (FileBuffer); + return EFI_NOT_FOUND; + } + // + // Located the protocol + // + Status = gBS->LocateProtocol ( + &gEfiSectionExtractionProtocolGuid, + NULL, + (VOID **) &Sep + ); + if (EFI_ERROR (Status)) { + FreePool (FileBuffer); + return Status; + } + + Status = Sep->OpenSectionStream ( + Sep, + FileSize, + FileBuffer, + &StreamHandle + ); + + if (EFI_ERROR (Status)) { + FreePool (FileBuffer); + return Status; + } + + if (SectionType == 0) { + // + // We need the whole section stream + // + Status = Sep->GetSection ( + Sep, + StreamHandle, + NULL, + NULL, + 0, + Buffer, + BufferSize, + AuthenticationStatus + ); + } else { + Status = Sep->GetSection ( + Sep, + StreamHandle, + &SectionType, + NULL, + SectionInstance, + Buffer, + BufferSize, + AuthenticationStatus + ); + } + + if (!EFI_ERROR (Status)) { + // + // Inherit the authentication status. + // + *AuthenticationStatus |= FvDevice->AuthenticationStatus; + } + + // + // Handle AuthenticationStatus if necessary + // + Sep->CloseSectionStream (Sep, StreamHandle); + + FreePool (FileBuffer); + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c new file mode 100644 index 0000000000..7f23b51d83 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c @@ -0,0 +1,1586 @@ +/** @file + Implements write firmware file. + + Copyright (c) 2006 - 2015, Intel 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 "FwVolDriver.h" + +/** + Calculate the checksum for the FFS header. + + @param FfsHeader FFS File Header which needs to calculate the checksum + +**/ +VOID +SetHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + EFI_FFS_FILE_STATE State; + UINT8 FileChecksum; + + // + // The state and the File checksum are not included + // + State = FfsHeader->State; + FfsHeader->State = 0; + + FileChecksum = FfsHeader->IntegrityCheck.Checksum.File; + FfsHeader->IntegrityCheck.Checksum.File = 0; + + FfsHeader->IntegrityCheck.Checksum.Header = 0; + + if (IS_FFS_FILE2 (FfsHeader)) { + FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 ( + (UINT8 *) FfsHeader, + sizeof (EFI_FFS_FILE_HEADER2) + ); + } else { + FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 ( + (UINT8 *) FfsHeader, + sizeof (EFI_FFS_FILE_HEADER) + ); + } + + FfsHeader->State = State; + FfsHeader->IntegrityCheck.Checksum.File = FileChecksum; + + return ; +} + +/** + Calculate the checksum for the FFS File. + + @param FfsHeader FFS File Header which needs to calculate the checksum + @param ActualFileSize The whole Ffs File Length. + +**/ +VOID +SetFileChecksum ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN UINTN ActualFileSize + ) +{ + if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) { + + FfsHeader->IntegrityCheck.Checksum.File = 0; + + if (IS_FFS_FILE2 (FfsHeader)) { + FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 ( + (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), + ActualFileSize - sizeof (EFI_FFS_FILE_HEADER2) + ); + } else { + FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 ( + (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), + ActualFileSize - sizeof (EFI_FFS_FILE_HEADER) + ); + } + + } else { + + FfsHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + + } + + return ; +} + +/** + Get the alignment value from File Attributes. + + @param FfsAttributes FFS attribute + + @return Alignment value. + +**/ +UINTN +GetRequiredAlignment ( + IN EFI_FV_FILE_ATTRIBUTES FfsAttributes + ) +{ + UINTN AlignmentValue; + + AlignmentValue = FfsAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT; + + if (AlignmentValue <= 3) { + return 0x08; + } + + if (AlignmentValue > 16) { + // + // Anyway, we won't reach this code + // + return 0x08; + } + + return (UINTN)1 << AlignmentValue; + +} + +/** + Calculate the leading Pad file size to meet the alignment requirement. + + @param FvDevice Cached Firmware Volume. + @param StartAddress The starting address to write the FFS File. + @param BufferSize The FFS File Buffer Size. + @param RequiredAlignment FFS File Data alignment requirement. + + @return The required Pad File Size. + +**/ +UINTN +CalculatePadFileSize ( + IN FV_DEVICE *FvDevice, + IN EFI_PHYSICAL_ADDRESS StartAddress, + IN UINTN BufferSize, + IN UINTN RequiredAlignment + ) +{ + UINTN DataStartPos; + UINTN RelativePos; + UINTN PadSize; + + if (BufferSize > 0x00FFFFFF) { + DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER2); + } else { + DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER); + } + RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv; + + PadSize = 0; + + while ((RelativePos & (RequiredAlignment - 1)) != 0) { + RelativePos++; + PadSize++; + } + // + // If padsize is 0, no pad file needed; + // If padsize is great than 24, then pad file can be created + // + if ((PadSize == 0) || (PadSize >= sizeof (EFI_FFS_FILE_HEADER))) { + return PadSize; + } + + // + // Perhaps following method can save space + // + RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv + sizeof (EFI_FFS_FILE_HEADER); + PadSize = sizeof (EFI_FFS_FILE_HEADER); + + while ((RelativePos & (RequiredAlignment - 1)) != 0) { + RelativePos++; + PadSize++; + } + + return PadSize; +} + +/** + Convert EFI_FV_FILE_ATTRIBUTES to FFS_FILE_ATTRIBUTES. + + @param FvFileAttrib The value of EFI_FV_FILE_ATTRIBUTES + @param FfsFileAttrib Pointer to the got FFS_FILE_ATTRIBUTES value. + +**/ +VOID +FvFileAttrib2FfsFileAttrib ( + IN EFI_FV_FILE_ATTRIBUTES FvFileAttrib, + OUT UINT8 *FfsFileAttrib + ) +{ + UINT8 FvFileAlignment; + UINT8 FfsFileAlignment; + + FvFileAlignment = (UINT8) (FvFileAttrib & EFI_FV_FILE_ATTRIB_ALIGNMENT); + FfsFileAlignment = 0; + + switch (FvFileAlignment) { + case 0: + // + // fall through + // + case 1: + // + // fall through + // + case 2: + // + // fall through + // + case 3: + // + // fall through + // + FfsFileAlignment = 0; + break; + + case 4: + // + // fall through + // + case 5: + // + // fall through + // + case 6: + // + // fall through + // + FfsFileAlignment = 1; + break; + + case 7: + // + // fall through + // + case 8: + // + // fall through + // + FfsFileAlignment = 2; + break; + + case 9: + FfsFileAlignment = 3; + break; + + case 10: + // + // fall through + // + case 11: + // + // fall through + // + FfsFileAlignment = 4; + break; + + case 12: + // + // fall through + // + case 13: + // + // fall through + // + case 14: + // + // fall through + // + FfsFileAlignment = 5; + break; + + case 15: + FfsFileAlignment = 6; + break; + + case 16: + FfsFileAlignment = 7; + break; + } + + *FfsFileAttrib = (UINT8) (FfsFileAlignment << 3); + + return ; +} + +/** + Locate a free space entry that can hold this FFS file. + + @param FvDevice Cached Firmware Volume. + @param Size The FFS file size. + @param RequiredAlignment FFS File Data alignment requirement. + @param PadSize Pointer to the size of leading Pad File. + @param FreeSpaceEntry Pointer to the Free Space Entry that meets the requirement. + + @retval EFI_SUCCESS The free space entry is found. + @retval EFI_NOT_FOUND The free space entry can't be found. + +**/ +EFI_STATUS +FvLocateFreeSpaceEntry ( + IN FV_DEVICE *FvDevice, + IN UINTN Size, + IN UINTN RequiredAlignment, + OUT UINTN *PadSize, + OUT FREE_SPACE_ENTRY **FreeSpaceEntry + ) +{ + FREE_SPACE_ENTRY *FreeSpaceListEntry; + LIST_ENTRY *Link; + UINTN PadFileSize; + + Link = FvDevice->FreeSpaceHeader.ForwardLink; + FreeSpaceListEntry = (FREE_SPACE_ENTRY *) Link; + + // + // Loop the free space entry list to find one that can hold the + // required the file size + // + while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) { + PadFileSize = CalculatePadFileSize ( + FvDevice, + (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceListEntry->StartingAddress, + Size, + RequiredAlignment + ); + if (FreeSpaceListEntry->Length >= Size + PadFileSize) { + *FreeSpaceEntry = FreeSpaceListEntry; + *PadSize = PadFileSize; + return EFI_SUCCESS; + } + + FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink; + } + + return EFI_NOT_FOUND; + +} + +/** + Locate Pad File for writing, this is got from FV Cache. + + @param FvDevice Cached Firmware Volume. + @param Size The required FFS file size. + @param RequiredAlignment FFS File Data alignment requirement. + @param PadSize Pointer to the size of leading Pad File. + @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. + + @retval EFI_SUCCESS The required pad file is found. + @retval EFI_NOT_FOUND The required pad file can't be found. + +**/ +EFI_STATUS +FvLocatePadFile ( + IN FV_DEVICE *FvDevice, + IN UINTN Size, + IN UINTN RequiredAlignment, + OUT UINTN *PadSize, + OUT FFS_FILE_LIST_ENTRY **PadFileEntry + ) +{ + FFS_FILE_LIST_ENTRY *FileEntry; + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_HEADER *FileHeader; + UINTN PadAreaLength; + UINTN PadFileSize; + UINTN HeaderSize; + + FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink; + + // + // travel through the whole file list to get the pad file entry + // + while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) { + + FileHeader = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader; + FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); + + if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) { + // + // we find one valid pad file, check its free area length + // + if (IS_FFS_FILE2 (FileHeader)) { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize; + } else { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER); + PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize; + } + + PadFileSize = CalculatePadFileSize ( + FvDevice, + (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize, + Size, + RequiredAlignment + ); + if (PadAreaLength >= (Size + PadFileSize)) { + *PadSize = PadFileSize; + *PadFileEntry = FileEntry; + return EFI_SUCCESS; + } + } + + FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink); + } + + return EFI_NOT_FOUND; +} + +/** + Locate a suitable pad file for multiple file writing. + + @param FvDevice Cached Firmware Volume. + @param NumOfFiles The number of Files that needed updating + @param BufferSize The array of each file size. + @param RequiredAlignment The array of of FFS File Data alignment requirement. + @param PadSize The array of size of each leading Pad File. + @param TotalSizeNeeded The totalsize that can hold these files. + @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. + + @retval EFI_SUCCESS The required pad file is found. + @retval EFI_NOT_FOUND The required pad file can't be found. + +**/ +EFI_STATUS +FvSearchSuitablePadFile ( + IN FV_DEVICE *FvDevice, + IN UINTN NumOfFiles, + IN UINTN *BufferSize, + IN UINTN *RequiredAlignment, + OUT UINTN *PadSize, + OUT UINTN *TotalSizeNeeded, + OUT FFS_FILE_LIST_ENTRY **PadFileEntry + ) +{ + FFS_FILE_LIST_ENTRY *FileEntry; + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_HEADER *FileHeader; + UINTN PadAreaLength; + UINTN TotalSize; + UINTN Index; + UINTN HeaderSize; + + FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink; + + // + // travel through the whole file list to get the pad file entry + // + while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) { + + FileHeader = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader; + FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); + + if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) { + // + // we find one valid pad file, check its length + // + if (IS_FFS_FILE2 (FileHeader)) { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize; + } else { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER); + PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize; + } + TotalSize = 0; + + for (Index = 0; Index < NumOfFiles; Index++) { + PadSize[Index] = CalculatePadFileSize ( + FvDevice, + (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize + TotalSize, + BufferSize[Index], + RequiredAlignment[Index] + ); + TotalSize += PadSize[Index]; + TotalSize += BufferSize[Index]; + + if (TotalSize > PadAreaLength) { + break; + } + } + + if (PadAreaLength >= TotalSize) { + *PadFileEntry = FileEntry; + *TotalSizeNeeded = TotalSize; + return EFI_SUCCESS; + } + } + + FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink); + } + + return EFI_NOT_FOUND; +} + +/** + Locate a Free Space entry which can hold these files, including + meeting the alignment requirements. + + @param FvDevice Cached Firmware Volume. + @param NumOfFiles The number of Files that needed updating + @param BufferSize The array of each file size. + @param RequiredAlignment The array of of FFS File Data alignment requirement. + @param PadSize The array of size of each leading Pad File. + @param TotalSizeNeeded The got total size that can hold these files. + @param FreeSpaceEntry The Free Space Entry that can hold these files. + + @retval EFI_SUCCESS The free space entry is found. + @retval EFI_NOT_FOUND The free space entry can't be found. + +**/ +EFI_STATUS +FvSearchSuitableFreeSpace ( + IN FV_DEVICE *FvDevice, + IN UINTN NumOfFiles, + IN UINTN *BufferSize, + IN UINTN *RequiredAlignment, + OUT UINTN *PadSize, + OUT UINTN *TotalSizeNeeded, + OUT FREE_SPACE_ENTRY **FreeSpaceEntry + ) +{ + FREE_SPACE_ENTRY *FreeSpaceListEntry; + LIST_ENTRY *Link; + UINTN TotalSize; + UINTN Index; + UINT8 *StartAddr; + + Link = FvDevice->FreeSpaceHeader.ForwardLink; + + FreeSpaceListEntry = (FREE_SPACE_ENTRY *) Link; + + while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) { + TotalSize = 0; + StartAddr = FreeSpaceListEntry->StartingAddress; + + // + // Calculate the totalsize we need + // + for (Index = 0; Index < NumOfFiles; Index++) { + // + // Perhaps we don't need an EFI_FFS_FILE_HEADER, the first file + // have had its leading pad file. + // + PadSize[Index] = CalculatePadFileSize ( + FvDevice, + (EFI_PHYSICAL_ADDRESS) (UINTN) StartAddr + TotalSize, + BufferSize[Index], + RequiredAlignment[Index] + ); + + TotalSize += PadSize[Index]; + TotalSize += BufferSize[Index]; + + if (TotalSize > FreeSpaceListEntry->Length) { + break; + } + } + + if (FreeSpaceListEntry->Length >= TotalSize) { + *FreeSpaceEntry = FreeSpaceListEntry; + *TotalSizeNeeded = TotalSize; + return EFI_SUCCESS; + } + + FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink; + } + + return EFI_NOT_FOUND; +} + +/** + Calculate the length of the remaining space in FV. + + @param FvDevice Cached Firmware Volume + @param Offset Current offset to FV base address. + @param Lba LBA number for the current offset. + @param LOffset Offset in block for the current offset. + + @return the length of remaining space. + +**/ +UINTN +CalculateRemainingLength ( + IN FV_DEVICE *FvDevice, + IN UINTN Offset, + OUT EFI_LBA *Lba, + OUT UINTN *LOffset + ) +{ + LIST_ENTRY *Link; + LBA_ENTRY *LbaEntry; + UINTN Count; + + Count = 0; + *Lba = 0; + Link = FvDevice->LbaHeader.ForwardLink; + LbaEntry = (LBA_ENTRY *) Link; + + while (&LbaEntry->Link != &FvDevice->LbaHeader) { + if (Count > Offset) { + break; + } + + Count += LbaEntry->BlockLength; + (*Lba)++; + Link = LbaEntry->Link.ForwardLink; + LbaEntry = (LBA_ENTRY *) Link; + } + + if (Count <= Offset) { + return 0; + } + + Link = LbaEntry->Link.BackLink; + LbaEntry = (LBA_ENTRY *) Link; + + (*Lba)--; + *LOffset = (UINTN) (LbaEntry->BlockLength - (Count - Offset)); + + Count = 0; + while (&LbaEntry->Link != &FvDevice->LbaHeader) { + + Count += LbaEntry->BlockLength; + + Link = LbaEntry->Link.ForwardLink; + LbaEntry = (LBA_ENTRY *) Link; + } + + Count -= *LOffset; + + return Count; +} + +/** + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when the firmware end is + reached. *NumBytes is updated to reflect the actual number of bytes + written. + + @param FvDevice Cached Firmware Volume + @param Offset Offset in the block at which to begin write + @param NumBytes At input, indicates the requested write size. + At output, indicates the actual number of bytes written. + @param Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS Data is successfully written into FV. + @return error Data is failed written. + +**/ +EFI_STATUS +FvcWrite ( + IN FV_DEVICE *FvDevice, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_LBA Lba; + UINTN LOffset; + EFI_FVB_ATTRIBUTES_2 FvbAttributes; + UINTN RemainingLength; + UINTN WriteLength; + UINT8 *TmpBuffer; + + LOffset = 0; + RemainingLength = CalculateRemainingLength (FvDevice, Offset, &Lba, &LOffset); + if ((UINTN) (*NumBytes) > RemainingLength) { + *NumBytes = (UINTN) RemainingLength; + return EFI_INVALID_PARAMETER; + } + + Fvb = FvDevice->Fvb; + + Status = Fvb->GetAttributes ( + Fvb, + &FvbAttributes + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((FvbAttributes & EFI_FV2_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + RemainingLength = *NumBytes; + WriteLength = RemainingLength; + TmpBuffer = Buffer; + + do { + Status = Fvb->Write ( + Fvb, + Lba, + LOffset, + &WriteLength, + TmpBuffer + ); + if (!EFI_ERROR (Status)) { + goto Done; + } + + if (Status == EFI_BAD_BUFFER_SIZE) { + Lba++; + LOffset = 0; + TmpBuffer += WriteLength; + RemainingLength -= WriteLength; + WriteLength = (UINTN) RemainingLength; + + continue; + } else { + return Status; + } + } while (1); + +Done: + return EFI_SUCCESS; +} + +/** + Create a new FFS file into Firmware Volume device. + + @param FvDevice Cached Firmware Volume. + @param FfsFileBuffer A buffer that holds an FFS file,(it contains + a File Header which is in init state). + @param BufferSize The size of FfsFileBuffer. + @param ActualFileSize The actual file length, it may not be multiples of 8. + @param FileName The FFS File Name. + @param FileType The FFS File Type. + @param FileAttributes The Attributes of the FFS File to be created. + + @retval EFI_SUCCESS FFS fle is added into FV. + @retval EFI_INVALID_PARAMETER File type is not valid. + @retval EFI_DEVICE_ERROR FV doesn't set writable attribute. + @retval EFI_NOT_FOUND FV has no enough space for the added file. + +**/ +EFI_STATUS +FvCreateNewFile ( + IN FV_DEVICE *FvDevice, + IN UINT8 *FfsFileBuffer, + IN UINTN BufferSize, + IN UINTN ActualFileSize, + IN EFI_GUID *FileName, + IN EFI_FV_FILETYPE FileType, + IN EFI_FV_FILE_ATTRIBUTES FileAttributes + ) +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *FileHeader; + EFI_PHYSICAL_ADDRESS BufferPtr; + UINTN Offset; + UINTN NumBytesWritten; + UINTN StateOffset; + FREE_SPACE_ENTRY *FreeSpaceEntry; + UINTN RequiredAlignment; + UINTN PadFileSize; + FFS_FILE_LIST_ENTRY *PadFileEntry; + EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + UINTN HeaderSize; + + // + // File Type: 0x0E~0xE0 are reserved + // + if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) { + return EFI_INVALID_PARAMETER; + } + + // + // First find a free space that can hold this image. + // Check alignment, FFS at least must be aligned at 8-byte boundry + // + RequiredAlignment = GetRequiredAlignment (FileAttributes); + + Status = FvLocateFreeSpaceEntry ( + FvDevice, + BufferSize, + RequiredAlignment, + &PadFileSize, + &FreeSpaceEntry + ); + if (EFI_ERROR (Status)) { + // + // Maybe we need to find a PAD file that can hold this image + // + Status = FvCreateNewFileInsidePadFile ( + FvDevice, + FfsFileBuffer, + BufferSize, + ActualFileSize, + FileName, + FileType, + FileAttributes + ); + + return Status; + } + + BufferPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress; + + // + // If we need a leading PAD File, create it first. + // + if (PadFileSize != 0) { + Status = FvCreatePadFileInFreeSpace ( + FvDevice, + FreeSpaceEntry, + PadFileSize - sizeof (EFI_FFS_FILE_HEADER), + &PadFileEntry + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // Maybe we create a pad file, so re-get the free space starting address + // and length + // + BufferPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress; + + // + // File creation step 1: Allocate File Header, + // Mark EFI_FILE_HEADER_CONSTRUCTION bit to TRUE, + // Write Name, IntegrityCheck.Header, Type, Attributes, and Size + // + FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer; + if (ActualFileSize > 0x00FFFFFF) { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + } else { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER); + } + SetFileState (EFI_FILE_HEADER_CONSTRUCTION, FileHeader); + + Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); + StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + StateOffset, + &NumBytesWritten, + &FileHeader->State + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // update header 2 cache + // + CopyMem ( + (UINT8 *) (UINTN) BufferPtr, + FileHeader, + HeaderSize + ); + + // + // update Free Space Entry, now need to substract the file header length + // + FreeSpaceEntry->StartingAddress += HeaderSize; + FreeSpaceEntry->Length -= HeaderSize; + + CopyGuid (&FileHeader->Name, FileName); + FileHeader->Type = FileType; + + // + // Convert FvFileAttribute to FfsFileAttributes + // + FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute); + + FileHeader->Attributes = TmpFileAttribute; + + // + // File size is including the FFS File Header. + // + if (ActualFileSize > 0x00FFFFFF) { + ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize; + *(UINT32 *) FileHeader->Size &= 0xFF000000; + FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; + } else { + *(UINT32 *) FileHeader->Size &= 0xFF000000; + *(UINT32 *) FileHeader->Size |= ActualFileSize; + } + + SetHeaderChecksum (FileHeader); + + Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); + + NumBytesWritten = HeaderSize; + Status = FvcWrite ( + FvDevice, + Offset, + &NumBytesWritten, + (UINT8 *) FileHeader + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // update header 2 cache + // + CopyMem ( + (UINT8 *) (UINTN) BufferPtr, + FileHeader, + HeaderSize + ); + + // + // end of step 1 + // + // File creation step 2: + // MARK EFI_FILE_HEADER_VALID bit to TRUE, + // Write IntegrityCheck.File, File Data + // + SetFileState (EFI_FILE_HEADER_VALID, FileHeader); + + Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); + StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + StateOffset, + &NumBytesWritten, + &FileHeader->State + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // update header 2 cache + // + CopyMem ( + (UINT8 *) (UINTN) BufferPtr, + FileHeader, + HeaderSize + ); + + // + // update Free Space Entry, now need to substract the file data length + // + FreeSpaceEntry->StartingAddress += (BufferSize - HeaderSize); + FreeSpaceEntry->Length -= (BufferSize - HeaderSize); + + // + // Calculate File Checksum + // + SetFileChecksum (FileHeader, ActualFileSize); + + Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); + + NumBytesWritten = BufferSize; + Status = FvcWrite ( + FvDevice, + Offset, + &NumBytesWritten, + FfsFileBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // each time write block successfully, write also to cache + // + CopyMem ( + (UINT8 *) (UINTN) BufferPtr, + FfsFileBuffer, + NumBytesWritten + ); + + // + // Step 3: Mark EFI_FILE_DATA_VALID to TRUE + // + SetFileState (EFI_FILE_DATA_VALID, FileHeader); + + Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); + StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + StateOffset, + &NumBytesWritten, + &FileHeader->State + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // update header 2 cache + // + CopyMem ( + (UINT8 *) (UINTN) BufferPtr, + FileHeader, + HeaderSize + ); + + // + // If successfully, insert an FfsFileEntry at the end of ffs file list + // + + FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); + ASSERT (FfsFileEntry != NULL); + FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) BufferPtr; + InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); + + // + // Set cache file to this file + // + FvDevice->CurrentFfsFile = FfsFileEntry; + + return EFI_SUCCESS; +} + +/** + Update a File, so after successful update, there are 2 files existing + in FV, one is marked for deleted, and another one is valid. + + @param FvDevice Cached Firmware Volume. + @param FfsFileBuffer A buffer that holds an FFS file,(it contains + a File Header which is in init state). + @param BufferSize The size of FfsFileBuffer. + @param ActualFileSize The actual file length, it may not be multiples of 8. + @param FileName The FFS File Name. + @param NewFileType The FFS File Type. + @param NewFileAttributes The Attributes of the FFS File to be created. + + @retval EFI_SUCCESS FFS fle is updated into FV. + @retval EFI_INVALID_PARAMETER File type is not valid. + @retval EFI_DEVICE_ERROR FV doesn't set writable attribute. + @retval EFI_NOT_FOUND FV has no enough space for the added file. + FFS with same file name is not found in FV. + +**/ +EFI_STATUS +FvUpdateFile ( + IN FV_DEVICE *FvDevice, + IN UINT8 *FfsFileBuffer, + IN UINTN BufferSize, + IN UINTN ActualFileSize, + IN EFI_GUID *FileName, + IN EFI_FV_FILETYPE NewFileType, + IN EFI_FV_FILE_ATTRIBUTES NewFileAttributes + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN NumBytesWritten; + EFI_FV_FILETYPE OldFileType; + EFI_FV_FILE_ATTRIBUTES OldFileAttributes; + UINTN OldFileSize; + EFI_FFS_FILE_HEADER *OldFileHeader; + UINTN OldOffset; + UINTN OldStateOffset; + FFS_FILE_LIST_ENTRY *OldFfsFileEntry; + UINTN Key; + EFI_GUID FileNameGuid; + + Fv = &FvDevice->Fv; + + // + // Step 1, find old file, + // Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE in the older header + // + + // + // Check if the file was read last time. + // + OldFileHeader = NULL; + OldFfsFileEntry = FvDevice->CurrentFfsFile; + + if (OldFfsFileEntry != NULL) { + OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader; + } + + if ((OldFfsFileEntry == NULL) || (!CompareGuid (&OldFileHeader->Name, FileName))) { + Key = 0; + do { + OldFileType = 0; + Status = Fv->GetNextFile ( + Fv, + &Key, + &OldFileType, + &FileNameGuid, + &OldFileAttributes, + &OldFileSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + } while (!CompareGuid (&FileNameGuid, FileName)); + + // + // Get FfsFileEntry from the search key + // + OldFfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key; + + // + // Double check file state before being ready to be removed + // + OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader; + } else { + // + // Mark the cache file to invalid + // + FvDevice->CurrentFfsFile = NULL; + } + // + // Update File: Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE + // + SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader); + + OldOffset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv); + OldStateOffset = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + OldStateOffset, + &NumBytesWritten, + &OldFileHeader->State + ); + if (EFI_ERROR (Status)) { + // + // if failed, write the bit back in the cache, its XOR operation. + // + SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader); + + return Status; + } + + // + // Step 2, Create New Files + // + Status = FvCreateNewFile ( + FvDevice, + FfsFileBuffer, + BufferSize, + ActualFileSize, + FileName, + NewFileType, + NewFileAttributes + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If successfully, remove this file entry, + // although delete file may fail. + // + (OldFfsFileEntry->Link.BackLink)->ForwardLink = OldFfsFileEntry->Link.ForwardLink; + (OldFfsFileEntry->Link.ForwardLink)->BackLink = OldFfsFileEntry->Link.BackLink; + FreePool (OldFfsFileEntry); + + // + // Step 3: Delete old files, + // by marking EFI_FILE_DELETED to TRUE + // + SetFileState (EFI_FILE_DELETED, OldFileHeader); + + OldOffset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv); + OldStateOffset = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + OldStateOffset, + &NumBytesWritten, + &OldFileHeader->State + ); + if (EFI_ERROR (Status)) { + // + // if failed, write the bit back in the cache, its XOR operation. + // + SetFileState (EFI_FILE_DELETED, OldFileHeader); + + return Status; + } + + return EFI_SUCCESS; +} + +/** + Deleted a given file from FV device. + + @param FvDevice Cached Firmware Volume. + @param NameGuid The FFS File Name. + + @retval EFI_SUCCESS FFS file with the specified FFS name is removed. + @retval EFI_NOT_FOUND FFS file with the specified FFS name is not found. + +**/ +EFI_STATUS +FvDeleteFile ( + IN FV_DEVICE *FvDevice, + IN EFI_GUID *NameGuid + ) +{ + EFI_STATUS Status; + UINTN Key; + EFI_GUID FileNameGuid; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + UINTN FileSize; + EFI_FFS_FILE_HEADER *FileHeader; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + EFI_FFS_FILE_STATE FileState; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN Offset; + UINTN StateOffset; + UINTN NumBytesWritten; + + Fv = &FvDevice->Fv; + + // + // Check if the file was read last time. + // + FileHeader = NULL; + FfsFileEntry = FvDevice->CurrentFfsFile; + + if (FfsFileEntry != NULL) { + FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; + } + + if ((FfsFileEntry == NULL) || (!CompareGuid (&FileHeader->Name, NameGuid))) { + // + // Next search for the file using GetNextFile + // + Key = 0; + do { + FileType = 0; + Status = Fv->GetNextFile ( + Fv, + &Key, + &FileType, + &FileNameGuid, + &FileAttributes, + &FileSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + } while (!CompareGuid (&FileNameGuid, NameGuid)); + + // + // Get FfsFileEntry from the search key + // + FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key; + + // + // Double check file state before being ready to be removed + // + FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; + } else { + // + // Mark the cache file to NULL + // + FvDevice->CurrentFfsFile = NULL; + } + + FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); + + if (FileState == EFI_FILE_HEADER_INVALID) { + return EFI_NOT_FOUND; + } + + if (FileState == EFI_FILE_DELETED) { + return EFI_NOT_FOUND; + } + // + // Delete File: Mark EFI_FILE_DELETED to TRUE + // + SetFileState (EFI_FILE_DELETED, FileHeader); + + Offset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader - FvDevice->CachedFv); + StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; + + NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); + Status = FvcWrite ( + FvDevice, + StateOffset, + &NumBytesWritten, + &FileHeader->State + ); + if (EFI_ERROR (Status)) { + // + // if failed, write the bit back in the cache, its XOR operation. + // + SetFileState (EFI_FILE_DELETED, FileHeader); + + return Status; + } + // + // If successfully, remove this file entry + // + FvDevice->CurrentFfsFile = NULL; + + (FfsFileEntry->Link.BackLink)->ForwardLink = FfsFileEntry->Link.ForwardLink; + (FfsFileEntry->Link.ForwardLink)->BackLink = FfsFileEntry->Link.BackLink; + FreePool (FfsFileEntry); + + return EFI_SUCCESS; +} + +/** + Writes one or more files to the firmware volume. + + @param This Indicates the calling context. + @param NumberOfFiles Number of files. + @param WritePolicy WritePolicy indicates the level of reliability + for the write in the event of a power failure or + other system failure during the write operation. + @param FileData FileData is an pointer to an array of + EFI_FV_WRITE_DATA. Each element of array + FileData represents a file to be written. + + @retval EFI_SUCCESS Files successfully written to firmware volume + @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_WRITE_PROTECTED Write protected. + @retval EFI_NOT_FOUND Not found. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_UNSUPPORTED This function not supported. + +**/ +EFI_STATUS +EFIAPI +FvWriteFile ( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN EFI_FV_WRITE_POLICY WritePolicy, + IN EFI_FV_WRITE_FILE_DATA *FileData + ) +{ + EFI_STATUS Status; + UINTN Index1; + UINTN Index2; + UINT8 *FileBuffer; + UINTN BufferSize; + UINTN ActualSize; + UINT8 ErasePolarity; + FV_DEVICE *FvDevice; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + UINTN Size; + BOOLEAN CreateNewFile[MAX_FILES]; + UINTN NumDelete; + EFI_FV_ATTRIBUTES FvAttributes; + UINT32 AuthenticationStatus; + UINTN HeaderSize; + + if (NumberOfFiles > MAX_FILES) { + return EFI_UNSUPPORTED; + } + + Status = EFI_SUCCESS; + + SetMem (CreateNewFile, NumberOfFiles, TRUE); + + FvDevice = FV_DEVICE_FROM_THIS (This); + + // + // First check the volume attributes. + // + Status = This->GetVolumeAttributes ( + This, + &FvAttributes + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Can we have write right? + // + if ((FvAttributes & EFI_FV2_WRITE_STATUS) == 0) { + return EFI_WRITE_PROTECTED; + } + + ErasePolarity = FvDevice->ErasePolarity; + + // + // Loop for all files + // + NumDelete = 0; + for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { + + if ((FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER) > 0x00FFFFFF) && !FvDevice->IsFfs3Fv) { + // + // Found a file needs a FFS3 formatted file to store it, but it is in a non-FFS3 formatted FV. + // + DEBUG ((EFI_D_ERROR, "FFS3 formatted file can't be written in a non-FFS3 formatted FV.\n")); + return EFI_INVALID_PARAMETER; + } + + if (FileData[Index1].BufferSize == 0) { + // + // Here we will delete this file + // + Status = This->ReadFile ( + This, + FileData[Index1].NameGuid, + NULL, + &Size, + &FileType, + &FileAttributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + NumDelete++; + } else { + return Status; + } + } + + if (FileData[Index1].Type == EFI_FV_FILETYPE_FFS_PAD) { + // + // According to PI spec, on EFI_FV_FILETYPE_FFS_PAD: + // "Standard firmware file system services will not return the handle of any pad files, + // nor will they permit explicit creation of such files." + // + return EFI_INVALID_PARAMETER; + } + } + + if ((NumDelete != NumberOfFiles) && (NumDelete != 0)) { + // + // A delete was request with a multiple file write + // + return EFI_INVALID_PARAMETER; + } + + if (NumDelete == NumberOfFiles) { + for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { + // + // Delete Files + // + Status = FvDeleteFile (FvDevice, FileData[Index1].NameGuid); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; + } + + for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { + Status = This->ReadFile ( + This, + FileData[Index1].NameGuid, + NULL, + &Size, + &FileType, + &FileAttributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + CreateNewFile[Index1] = FALSE; + } else if (Status == EFI_NOT_FOUND) { + CreateNewFile[Index1] = TRUE; + } else { + return Status; + } + // + // Checking alignment + // + if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) { + UINT8 FFSAlignmentValue; + UINT8 FvAlignmentValue; + + FFSAlignmentValue = (UINT8) (FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT); + FvAlignmentValue = (UINT8) (((UINT32) (FvAttributes & EFI_FV2_ALIGNMENT)) >> 16); + + if (FFSAlignmentValue > FvAlignmentValue) { + return EFI_INVALID_PARAMETER; + } + } + } + + if ((WritePolicy != EFI_FV_RELIABLE_WRITE) && (WritePolicy != EFI_FV_UNRELIABLE_WRITE)) { + return EFI_INVALID_PARAMETER; + } + // + // Checking the reliable write is supported by FV + // + + if ((WritePolicy == EFI_FV_RELIABLE_WRITE) && (NumberOfFiles > 1)) { + // + // Only for multiple files, reliable write is meaningful + // + Status = FvCreateMultipleFiles ( + FvDevice, + NumberOfFiles, + FileData, + CreateNewFile + ); + + return Status; + } + + for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { + // + // Making Buffersize QWORD boundry, and add file tail. + // + HeaderSize = sizeof (EFI_FFS_FILE_HEADER); + ActualSize = FileData[Index1].BufferSize + HeaderSize; + if (ActualSize > 0x00FFFFFF) { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + ActualSize = FileData[Index1].BufferSize + HeaderSize; + } + BufferSize = ActualSize; + + while ((BufferSize & 0x07) != 0) { + BufferSize++; + } + + FileBuffer = AllocateZeroPool (BufferSize); + if (FileBuffer == NULL) { + return Status; + } + // + // Copy File Data into FileBuffer + // + CopyMem ( + FileBuffer + HeaderSize, + FileData[Index1].Buffer, + FileData[Index1].BufferSize + ); + + if (ErasePolarity == 1) { + // + // Fill the file header and padding byte with Erase Byte + // + for (Index2 = 0; Index2 < HeaderSize; Index2++) { + FileBuffer[Index2] = (UINT8)~FileBuffer[Index2]; + } + + for (Index2 = ActualSize; Index2 < BufferSize; Index2++) { + FileBuffer[Index2] = (UINT8)~FileBuffer[Index2]; + } + } + + if (CreateNewFile[Index1]) { + Status = FvCreateNewFile ( + FvDevice, + FileBuffer, + BufferSize, + ActualSize, + FileData[Index1].NameGuid, + FileData[Index1].Type, + FileData[Index1].FileAttributes + ); + } else { + Status = FvUpdateFile ( + FvDevice, + FileBuffer, + BufferSize, + ActualSize, + FileData[Index1].NameGuid, + FileData[Index1].Type, + FileData[Index1].FileAttributes + ); + } + + FreePool (FileBuffer); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/FlashUpdate.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/FlashUpdate.c new file mode 100644 index 0000000000..56514c9855 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/FlashUpdate.c @@ -0,0 +1,1218 @@ +/** @file + Functions in this file will program the image into flash area. + + Copyright (c) 2002 - 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 "UpdateDriver.h" + +/** + Write a block size data into flash. + + @param FvbProtocol Pointer to FVB protocol. + @param Lba Logic block index to be updated. + @param BlockSize Block size + @param Buffer Buffer data to be written. + + @retval EFI_SUCCESS Write data successfully. + @retval other errors Write data failed. + +**/ +EFI_STATUS +UpdateOneBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN EFI_LBA Lba, + IN UINTN BlockSize, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINTN Size; + + // + // First erase the block + // + Status = FvbProtocol->EraseBlocks ( + FvbProtocol, + Lba, // Lba + 1, // NumOfBlocks + EFI_LBA_LIST_TERMINATOR + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Write the block + // + Size = BlockSize; + Status = FvbProtocol->Write ( + FvbProtocol, + Lba, // Lba + 0, // Offset + &Size, // Size + Buffer // Buffer + ); + if ((EFI_ERROR (Status)) || (Size != BlockSize)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Write buffer data in a flash block. + + @param FvbProtocol Pointer to FVB protocol. + @param Lba Logic block index to be updated. + @param Offset The offset within the block. + @param Length Size of buffer to be updated. + @param BlockSize Block size. + @param Buffer Buffer data to be updated. + + @retval EFI_SUCCESS Write data successfully. + @retval other errors Write data failed. + +**/ +EFI_STATUS +UpdateBufferInOneBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN Length, + IN UINTN BlockSize, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINTN Size; + UINT8 *ReservedBuffer; + + // + // If we are going to update a whole block + // + if ((Offset == 0) && (Length == BlockSize)) { + Status = UpdateOneBlock ( + FvbProtocol, + Lba, + BlockSize, + Buffer + ); + return Status; + } + + // + // If it is not a full block update, we need to coalesce data in + // the block that is not going to be updated and new data together. + // + + // + // Allocate a reserved buffer to make up the final buffer for update + // + ReservedBuffer = NULL; + ReservedBuffer = AllocatePool (BlockSize); + if (ReservedBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // First get the original content of the block + // + Size = BlockSize; + Status = FvbProtocol->Read ( + FvbProtocol, + Lba, + 0, + &Size, + ReservedBuffer + ); + if ((EFI_ERROR (Status)) || (Size != BlockSize)) { + FreePool (ReservedBuffer); + return Status; + } + + // + // Overwrite the reserved buffer with new content + // + CopyMem (ReservedBuffer + Offset, Buffer, Length); + + Status = UpdateOneBlock ( + FvbProtocol, + Lba, + BlockSize, + ReservedBuffer + ); + + FreePool (ReservedBuffer); + + return Status; +} + +/** + Get the last write log, and check the status of last write. + If not complete, restart will be taken. + + @param FvbHandle Handle of FVB protocol. + @param FtwProtocol FTW protocol instance. + @param ConfigData Config data on updating driver. + @param PrivateDataSize bytes from the private data + stored for this write. + @param PrivateData A pointer to a buffer. The function will copy. + @param Lba The logical block address of the last write. + @param Offset The offset within the block of the last write. + @param Length The length of the last write. + @param Pending A Boolean value with TRUE indicating + that the write was completed. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_ABORTED The FTW work space is damaged. + @retval EFI_NOT_FOUND The last write is not done by this driver. + @retval EFI_SUCCESS Last write log is got. + +**/ +EFI_STATUS +RetrieveLastWrite ( + IN EFI_HANDLE FvbHandle, + IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol, + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINTN PrivateDataSize, + IN OUT UPDATE_PRIVATE_DATA *PrivateData, + IN OUT EFI_LBA *Lba, + IN OUT UINTN *Offset, + IN OUT UINTN *Length, + IN OUT BOOLEAN *Pending + ) +{ + EFI_STATUS Status; + EFI_GUID CallerId; + UINTN PrivateBufferSize; + BOOLEAN Complete; + VOID *PrivateDataBuffer; + + // + // Get the last write + // + *Pending = FALSE; + PrivateBufferSize = PrivateDataSize; + PrivateDataBuffer = NULL; + Status = FtwProtocol->GetLastWrite ( + FtwProtocol, + &CallerId, + Lba, + Offset, + Length, + &PrivateBufferSize, + PrivateData, + &Complete + ); + if (EFI_ERROR (Status)) { + // + // If there is no incompleted record, return success. + // + if ((Status == EFI_NOT_FOUND) && Complete) { + return EFI_SUCCESS; + } else if (Status == EFI_BUFFER_TOO_SMALL) { + // + // If buffer too small, reallocate buffer and call getlastwrite again + // + PrivateDataBuffer = AllocatePool (PrivateBufferSize); + + if (PrivateDataBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = FtwProtocol->GetLastWrite ( + FtwProtocol, + &CallerId, + Lba, + Offset, + Length, + &PrivateBufferSize, + PrivateDataBuffer, + &Complete + ); + if (EFI_ERROR (Status)) { + FreePool ( PrivateDataBuffer); + return EFI_ABORTED; + } else { + CopyMem (PrivateData, PrivateDataBuffer, PrivateDataSize); + FreePool (PrivateDataBuffer); + PrivateDataBuffer = NULL; + } + } else { + return EFI_ABORTED; + } + } + + *Pending = TRUE; + + // + // If the caller is not the update driver, then return. + // The update driver cannot continue to perform the update + // + if (CompareMem (&CallerId, &gEfiCallerIdGuid, sizeof (EFI_GUID)) != 0) { + return EFI_NOT_FOUND; + } + + // + // Check the private data and see if it is the one I need. + // + if (CompareMem (&(PrivateData->FileGuid), &(ConfigData->FileGuid), sizeof(EFI_GUID)) != 0) { + return EFI_NOT_FOUND; + } + + // + // If the caller is the update driver and complete is not true, then restart(). + // + if (!Complete) { + // + // Re-start the update + // + Status = FtwProtocol->Restart ( + FtwProtocol, + FvbHandle + ); + // + // If restart() error, then abort(). + // + if (EFI_ERROR (Status)) { + FtwProtocol->Abort (FtwProtocol); + // + // Now set Pending as FALSE as this record has been cleared + // + *Pending = FALSE; + return EFI_SUCCESS; + } + + } + + return Status; +} + +/** + Update the whole FV image in fault tolerant write method. + + @param FvbHandle Handle of FVB protocol for the updated flash range. + @param FvbProtocol FVB protocol. + @param BlockMap Block array to specify flash area. + @param ConfigData Config data on updating driver. + @param ImageBuffer Image buffer to be updated. + @param ImageSize Image size. + + @retval EFI_SUCCESS FV image is writed into flash. + @retval EFI_INVALID_PARAMETER Config data is not valid. + @retval EFI_NOT_FOUND FTW protocol doesn't exist. + @retval EFI_OUT_OF_RESOURCES No enough backup space. + @retval EFI_ABORTED Error happen when update FV. + +**/ +EFI_STATUS +FaultTolerantUpdateOnWholeFv ( + IN EFI_HANDLE FvbHandle, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN EFI_FV_BLOCK_MAP_ENTRY *BlockMap, + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINT8 *ImageBuffer, + IN UINTN ImageSize + ) +{ + EFI_STATUS Status; + EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; + UINTN MaxBlockSize; + UINTN FtwMaxBlockSize; + BOOLEAN Pending; + UPDATE_PRIVATE_DATA PrivateData; + EFI_LBA PendingLba; + EFI_LBA Lba; + UINTN PendingOffset; + UINTN Offset; + UINTN PendingLength; + UINTN Length; + EFI_FV_BLOCK_MAP_ENTRY *PtrMap; + UINTN NumOfBlocks; + UINTN Index; + UINT8 *UpdateBuffer; + + if ((ConfigData->UpdateType != UpdateWholeFV) + || (!ConfigData->FaultTolerant)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get the FTW protocol + // + Status = gBS->LocateProtocol ( + &gEfiFaultTolerantWriteProtocolGuid, + NULL, + (VOID **) &FtwProtocol + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Get the maximum block size of the FV, and number of blocks + // NumOfBlocks will be the NumOfUdpates. + // + MaxBlockSize = 0; + NumOfBlocks = 0; + PtrMap = BlockMap; + while (TRUE) { + if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { + break; + } + if (MaxBlockSize < PtrMap->Length) { + MaxBlockSize = PtrMap->Length; + } + NumOfBlocks = NumOfBlocks + PtrMap->NumBlocks; + PtrMap++; + } + + FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize); + // + // Not enough backup space. return directly + // + if (FtwMaxBlockSize < MaxBlockSize) { + return EFI_OUT_OF_RESOURCES; + } + + PendingLba = 0; + PendingOffset = 0; + PendingLength = 0; + Pending = FALSE; + + // + // Fault Tolerant Write can only support actual fault tolerance if the write + // is a reclaim operation, which means the data buffer (new and old) are + // acutally both stored in flash. But for component update write, the data + // are now in memory. So we cannot actually recover the data after power + // failure. + // + Status = RetrieveLastWrite ( + FvbHandle, + FtwProtocol, + ConfigData, + sizeof (UPDATE_PRIVATE_DATA), + &PrivateData, + &PendingLba, + &PendingOffset, + &PendingLength, + &Pending + ); + + if (Pending && (Status == EFI_NOT_FOUND)) { + // + // Cannot continue with the write operation + // + return EFI_ABORTED; + } + + if (EFI_ERROR(Status)) { + return EFI_ABORTED; + } + + // + // Currently we start from the pending write if there is any. But as we + // are going to update a whole FV, we can just abort last write and start + // from the very begining. + // + if (!Pending) { + // + // Now allocte the update private data in FTW. If there is pending + // write, it has already been allocated and no need to allocate here. + // + Status = FtwProtocol->Allocate ( + FtwProtocol, + &gEfiCallerIdGuid, + sizeof (UPDATE_PRIVATE_DATA), + NumOfBlocks + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Perform the update now. If there are pending writes, we need to + // start from the pending write instead of the very beginning. + // + PtrMap = BlockMap; + Lba = 0; + Offset = 0; + UpdateBuffer = ImageBuffer; + CopyMem ( + (VOID *) &PrivateData.FileGuid, + (VOID *) &ConfigData->FileGuid, + sizeof (EFI_GUID) + ); + + while (TRUE) { + if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { + break; + } + Length = (UINTN)PtrMap->Length; + for (Index = 0; Index < PtrMap->NumBlocks; Index++) { + + // + // Add an extra check here to see if the pending record is correct + // + if (Pending && (Lba == PendingLba)) { + if ((PendingOffset != Offset) || (PendingLength != Length)) { + // + // Error. + // + Status = EFI_ABORTED; + break; + } + } + + if ((!Pending) || (Lba >= PendingLba)) { + Status = FtwProtocol->Write ( + FtwProtocol, + Lba, // Lba + Offset, // Offset + Length, // Size + &PrivateData, // Private Data + FvbHandle, // FVB handle + UpdateBuffer // Buffer + ); + } + + if (EFI_ERROR (Status)) { + break; + } + Lba++; + UpdateBuffer = (UINT8 *) ((UINTN)UpdateBuffer + Length); + } + + if (EFI_ERROR (Status)) { + break; + } + PtrMap++; + } + + return Status; + +} + +/** + Directly update the whole FV image without fault tolerant write method. + + @param FvbHandle Handle of FVB protocol for the updated flash range. + @param FvbProtocol FVB protocol. + @param BlockMap Block array to specify flash area. + @param ConfigData Config data on updating driver. + @param ImageBuffer Image buffer to be updated. + @param ImageSize Image size. + + @retval EFI_SUCCESS FV image is writed into flash. + @retval EFI_INVALID_PARAMETER Config data is not valid. + @retval EFI_ABORTED Error happen when update FV. + +**/ +EFI_STATUS +NonFaultTolerantUpdateOnWholeFv ( + IN EFI_HANDLE FvbHandle, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN EFI_FV_BLOCK_MAP_ENTRY *BlockMap, + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINT8 *ImageBuffer, + IN UINTN ImageSize + ) +{ + EFI_STATUS Status; + EFI_FV_BLOCK_MAP_ENTRY *PtrMap; + UINTN Index; + EFI_LBA UpdateLba; + UINT8 *UpdateBuffer; + UINTN UpdateSize; + + if ((ConfigData->UpdateType != UpdateWholeFV ) + || (ConfigData->FaultTolerant)) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + PtrMap = BlockMap; + UpdateLba = 0; + UpdateBuffer = ImageBuffer; + + // + // Perform the update now + // + while (TRUE) { + if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { + break; + } + UpdateSize = (UINTN)PtrMap->Length; + for (Index = 0; Index < PtrMap->NumBlocks; Index++) { + Status = UpdateOneBlock ( + FvbProtocol, + UpdateLba, + UpdateSize, + UpdateBuffer + ); + if (EFI_ERROR (Status)) { + break; + } + + UpdateLba++; + UpdateBuffer = (UINT8 *) ((UINTN)UpdateBuffer + UpdateSize); + } + + if (EFI_ERROR (Status)) { + break; + } + PtrMap++; + } + + return Status; +} + +/** + Update the whole FV image, and reinsall FVB protocol for the updated FV image. + + @param FvbHandle Handle of FVB protocol for the updated flash range. + @param FvbProtocol FVB protocol. + @param ConfigData Config data on updating driver. + @param ImageBuffer Image buffer to be updated. + @param ImageSize Image size. + + @retval EFI_INVALID_PARAMETER Update type is not UpdateWholeFV. + Or Image size is not same to the size of whole FV. + @retval EFI_OUT_OF_RESOURCES No enoug memory is allocated. + @retval EFI_SUCCESS FV image is updated, and its FVB protocol is reinstalled. + +**/ +EFI_STATUS +PerformUpdateOnWholeFv ( + IN EFI_HANDLE FvbHandle, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINT8 *ImageBuffer, + IN UINTN ImageSize +) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + CHAR16 *TmpStr; + + if (ConfigData->UpdateType != UpdateWholeFV) { + return EFI_INVALID_PARAMETER; + } + + // + // Get the header of the firmware volume + // + FwVolHeader = NULL; + FwVolHeader = AllocatePool (((EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (ConfigData->BaseAddress)))->HeaderLength); + if (FwVolHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem ( + FwVolHeader, + (VOID *) ((UINTN) (ConfigData->BaseAddress)), + ((EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (ConfigData->BaseAddress)))->HeaderLength + ); + + // + // Check if ImageSize is the same as the size of the whole FV + // + if ((UINT64)ImageSize != FwVolHeader->FvLength) { + FreePool (FwVolHeader); + return EFI_INVALID_PARAMETER; + } + + // + // Print on screen + // + TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME), NULL); + if (TmpStr != NULL) { + Print (TmpStr, ConfigData->BaseAddress, (FwVolHeader->FvLength + ConfigData->BaseAddress)); + FreePool (TmpStr); + } + + DEBUG ((EFI_D_UPDATE, "UpdateDriver: updating whole FV from %08LX to %08LX\n", + ConfigData->BaseAddress, (FwVolHeader->FvLength + ConfigData->BaseAddress))); + + // + // Get the block map of the firmware volume + // + BlockMap = &(FwVolHeader->BlockMap[0]); + + // + // It is about the same if we are going to fault tolerantly update + // a certain FV in our current design. But we divide non-fault tolerant + // and fault tolerant udpate here for better maintenance as fault + // tolerance may change and may be done more wisely if we have space. + // + if (ConfigData->FaultTolerant) { + Status = FaultTolerantUpdateOnWholeFv ( + FvbHandle, + FvbProtocol, + BlockMap, + ConfigData, + ImageBuffer, + ImageSize + ); + } else { + Status = NonFaultTolerantUpdateOnWholeFv ( + FvbHandle, + FvbProtocol, + BlockMap, + ConfigData, + ImageBuffer, + ImageSize + ); + } + + FreePool (FwVolHeader); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // As the whole FV has been replaced, the FV driver shall re-parse the + // firmware volume. So re-install FVB protocol here + // + Status = gBS->ReinstallProtocolInterface ( + FvbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + FvbProtocol, + FvbProtocol + ); + + return Status; +} + +/** + Update certain file in the FV. + + @param FvbHandle Handle of FVB protocol for the updated flash range. + @param FvbProtocol FVB protocol. + @param ConfigData Config data on updating driver. + @param ImageBuffer Image buffer to be updated. + @param ImageSize Image size. + @param FileType FFS file type. + @param FileAttributes FFS file attribute + + @retval EFI_INVALID_PARAMETER Update type is not UpdateFvFile. + Or Image size is not same to the size of whole FV. + @retval EFI_UNSUPPORTED PEIM FFS is unsupported to be updated. + @retval EFI_SUCCESS The FFS file is added into FV. + +**/ +EFI_STATUS +PerformUpdateOnFvFile ( + IN EFI_HANDLE FvbHandle, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINT8 *ImageBuffer, + IN UINTN ImageSize, + IN EFI_FV_FILETYPE FileType, + IN EFI_FV_FILE_ATTRIBUTES FileAttributes + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol; + EFI_FV_WRITE_FILE_DATA FileData; + CHAR16 *TmpStr; + + if (ConfigData->UpdateType != UpdateFvFile) { + return EFI_INVALID_PARAMETER; + } + + // + // Print on screen + // + TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME_FILE), NULL); + if (TmpStr != NULL) { + Print (TmpStr, &(ConfigData->FileGuid)); + FreePool (TmpStr); + } + + DEBUG ((EFI_D_UPDATE, "UpdateDriver: updating file: %g\n", + &(ConfigData->FileGuid))); + + // + // Get Firmware volume protocol on this FVB protocol + // + Status = gBS->HandleProtocol ( + FvbHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &FwVolProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If it is a PEIM, we need first to rebase it before committing + // the write to target + // + if ((FileType == EFI_FV_FILETYPE_PEI_CORE) || (FileType == EFI_FV_FILETYPE_PEIM ) + || (FileType == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { + return EFI_UNSUPPORTED; + } + + FileData.NameGuid = &(ConfigData->FileGuid); + FileData.Type = FileType; + FileData.FileAttributes = FileAttributes; + FileData.Buffer = ImageBuffer; + FileData.BufferSize = (UINT32) ImageSize; + + Status = FwVolProtocol->WriteFile ( + FwVolProtocol, + 1, // NumberOfFiles + (EFI_FV_WRITE_POLICY)ConfigData->FaultTolerant, + &FileData + ); + return Status; +} + +/** + Update the buffer into flash area in fault tolerant write method. + + @param ImageBuffer Image buffer to be updated. + @param SizeLeft Size of the image buffer. + @param UpdatedSize Size of the updated buffer. + @param ConfigData Config data on updating driver. + @param FlashAddress Flash address to be updated as start address. + @param FvbProtocol FVB protocol. + @param FvbHandle Handle of FVB protocol for the updated flash range. + + @retval EFI_SUCCESS Buffer data is updated into flash. + @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area. + @retval EFI_NOT_FOUND FTW protocol doesn't exist. + @retval EFI_OUT_OF_RESOURCES No enough backup space. + @retval EFI_ABORTED Error happen when update flash area. + +**/ +EFI_STATUS +FaultTolerantUpdateOnPartFv ( + IN UINT8 *ImageBuffer, + IN UINTN SizeLeft, + IN OUT UINTN *UpdatedSize, + IN UPDATE_CONFIG_DATA *ConfigData, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN EFI_HANDLE FvbHandle + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeaderTmp; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_PHYSICAL_ADDRESS FvBase; + EFI_PHYSICAL_ADDRESS NextBlock; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_FV_BLOCK_MAP_ENTRY *PtrMap; + UINTN NumOfUpdates; + UINTN TotalSize; + EFI_PHYSICAL_ADDRESS StartAddress; + EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; + UINTN MaxBlockSize; + UINTN FtwMaxBlockSize; + BOOLEAN Pending; + UPDATE_PRIVATE_DATA PrivateData; + EFI_LBA PendingLba; + EFI_LBA Lba; + UINTN BlockSize; + UINTN PendingOffset; + UINTN Offset; + UINTN PendingLength; + UINTN Length; + UINTN Index; + UINT8 *Image; + + // + // Get the block map to update the block one by one + // + Status = FvbProtocol->GetPhysicalAddress ( + FvbProtocol, + &FvBase + ); + if (EFI_ERROR (Status)) { + return Status; + } + + FwVolHeaderTmp = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase; + if ((FlashAddress < FvBase) || (FlashAddress > (FvBase + FwVolHeaderTmp->FvLength))) { + return EFI_INVALID_PARAMETER; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AllocateCopyPool ( + FwVolHeaderTmp->HeaderLength, + FwVolHeaderTmp + ); + if (FwVolHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // For fault tolerant write, we have to know how many blocks we need to + // update. So we will calculate number of updates and max block size first + // + NumOfUpdates = 0; + MaxBlockSize = 0; + TotalSize = SizeLeft; + StartAddress = FlashAddress; + BaseAddress = FvBase; + BlockMap = &(FwVolHeader->BlockMap[0]); + PtrMap = BlockMap; + + while (TotalSize > 0) { + if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { + break; + } + + BlockSize = PtrMap->Length; + for (Index = 0; Index < PtrMap->NumBlocks; Index++) { + NextBlock = BaseAddress + BlockSize; + // + // Check if this block need to be updated + // + if ((StartAddress >= BaseAddress) && (StartAddress < NextBlock)) { + // + // Get the maximum block size + // + if (MaxBlockSize < BlockSize) { + MaxBlockSize = BlockSize; + } + + // + // This block shall be udpated. So increment number of updates + // + NumOfUpdates++; + Offset = (UINTN) (StartAddress - BaseAddress); + Length = TotalSize; + if ((Length + Offset ) > BlockSize) { + Length = BlockSize - Offset; + } + + StartAddress = StartAddress + Length; + TotalSize = TotalSize - Length; + if (TotalSize <= 0) { + break; + } + } + BaseAddress = NextBlock; + } + PtrMap++; + } + + // + // Get the FTW protocol + // + Status = gBS->LocateProtocol ( + &gEfiFaultTolerantWriteProtocolGuid, + NULL, + (VOID **) &FtwProtocol + ); + if (EFI_ERROR (Status)) { + FreePool (FwVolHeader); + return EFI_NOT_FOUND; + } + + FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize); + + // + // Not enough backup space. return directly + // + if (FtwMaxBlockSize < MaxBlockSize) { + FreePool (FwVolHeader); + return EFI_OUT_OF_RESOURCES; + } + + PendingLba = 0; + PendingOffset = 0; + PendingLength = 0; + Pending = FALSE; + + // + // Fault Tolerant Write can only support actual fault tolerance if the write + // is a reclaim operation, which means the data buffer (new and old) are + // acutally both stored in flash. But for component update write, the data + // are now in memory. So we cannot actually recover the data after power + // failure. + // + Status = RetrieveLastWrite ( + FvbHandle, + FtwProtocol, + ConfigData, + sizeof (UPDATE_PRIVATE_DATA), + &PrivateData, + &PendingLba, + &PendingOffset, + &PendingLength, + &Pending + ); + if (Pending && (Status == EFI_NOT_FOUND)) { + // + // I'm not the owner of the pending fault tolerant write record + // Cannot continue with the write operation + // + FreePool (FwVolHeader); + return EFI_ABORTED; + } + + if (EFI_ERROR(Status)) { + FreePool (FwVolHeader); + return EFI_ABORTED; + } + + // + // Currently we start from the pending write if there is any. But if the + // caller is exactly the same, and the new data is already a in memory, (it + // cannot be stored in flash in last write,) we can just abort last write + // and start from the very begining. + // + if (!Pending) { + // + // Now allocte the update private data in FTW. If there is pending + // write, it has already been allocated and no need to allocate here. + // + Status = FtwProtocol->Allocate ( + FtwProtocol, + &gEfiCallerIdGuid, + sizeof (UPDATE_PRIVATE_DATA), + NumOfUpdates + ); + if (EFI_ERROR (Status)) { + FreePool (FwVolHeader); + return Status; + } + } + + // + // Perform the update now. If there are pending writes, we need to + // start from the pending write instead of the very beginning. + // + TotalSize = SizeLeft; + Lba = 0; + StartAddress = FlashAddress; + BaseAddress = FvBase; + PtrMap = BlockMap; + Image = ImageBuffer; + CopyMem ( + (VOID *) &PrivateData.FileGuid, + (VOID *) &ConfigData->FileGuid, + sizeof (EFI_GUID) + ); + + while (TotalSize > 0) { + if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { + break; + } + + BlockSize = (UINTN)PtrMap->Length; + for (Index = 0; Index < PtrMap->NumBlocks; Index++) { + NextBlock = BaseAddress + BlockSize; + if ((StartAddress >= BaseAddress) && (StartAddress < NextBlock)) { + // + // So we need to update this block + // + Offset = (UINTN) (StartAddress - BaseAddress); + Length = TotalSize; + if ((Length + Offset ) > BlockSize) { + Length = BlockSize - Offset; + } + + // + // Add an extra check here to see if the pending record is correct + // + if (Pending && (Lba == PendingLba)) { + if ((PendingOffset != Offset) || (PendingLength != Length)) { + // + // Error. + // + Status = EFI_ABORTED; + break; + } + } + + if ((!Pending) || (Lba >= PendingLba)) { + DEBUG ((EFI_D_UPDATE, "Update Flash area from %08LX to %08LX\n", StartAddress, (UINT64)StartAddress + Length)); + Status = FtwProtocol->Write ( + FtwProtocol, + Lba, // Lba + Offset, // Offset + Length, // Size + &PrivateData, // Private Data + FvbHandle, // FVB handle + Image // Buffer + ); + if (EFI_ERROR (Status)) { + break; + } + } + + // + // Now increment StartAddress, ImageBuffer and decrease the + // left size to prepare for the next block update. + // + StartAddress = StartAddress + Length; + Image = Image + Length; + TotalSize = TotalSize - Length; + if (TotalSize <= 0) { + break; + } + } + BaseAddress = NextBlock; + Lba++; + } + + if (EFI_ERROR (Status)) { + break; + } + PtrMap++; + } + + FreePool (FwVolHeader); + + *UpdatedSize = SizeLeft - TotalSize; + + return EFI_SUCCESS; +} + +/** + Directly update the buffer into flash area without fault tolerant write method. + + @param ImageBuffer Image buffer to be updated. + @param SizeLeft Size of the image buffer. + @param UpdatedSize Size of the updated buffer. + @param FlashAddress Flash address to be updated as start address. + @param FvbProtocol FVB protocol. + @param FvbHandle Handle of FVB protocol for the updated flash range. + + @retval EFI_SUCCESS Buffer data is updated into flash. + @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area. + @retval EFI_OUT_OF_RESOURCES No enough backup space. + +**/ +EFI_STATUS +NonFaultTolerantUpdateOnPartFv ( + IN UINT8 *ImageBuffer, + IN UINTN SizeLeft, + IN OUT UINTN *UpdatedSize, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN EFI_HANDLE FvbHandle + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeaderTmp; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_PHYSICAL_ADDRESS NextBlock; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + UINTN Index; + UINTN TotalSize; + UINTN BlockSize; + EFI_LBA Lba; + UINTN Offset; + UINTN Length; + UINT8 *Image; + + // + // Get the block map to update the block one by one + // + Status = FvbProtocol->GetPhysicalAddress ( + FvbProtocol, + &BaseAddress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + FwVolHeaderTmp = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress; + if ((FlashAddress < BaseAddress) || (FlashAddress > ( BaseAddress + FwVolHeaderTmp->FvLength ))) { + return EFI_INVALID_PARAMETER; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AllocateCopyPool ( + FwVolHeaderTmp->HeaderLength, + FwVolHeaderTmp + ); + if (FwVolHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Image = ImageBuffer; + TotalSize = SizeLeft; + BlockMap = &(FwVolHeader->BlockMap[0]); + Lba = 0; + + while (TotalSize > 0) { + if ((BlockMap->NumBlocks == 0) || (BlockMap->Length == 0)) { + break; + } + + BlockSize = BlockMap->Length; + for (Index = 0 ; Index < BlockMap->NumBlocks ; Index++) { + NextBlock = BaseAddress + BlockSize; + if ((FlashAddress >= BaseAddress) && (FlashAddress < NextBlock)) { + // + // So we need to update this block + // + Offset = (UINTN) FlashAddress - (UINTN) BaseAddress; + Length = TotalSize; + if ((Length + Offset ) > BlockSize) { + Length = BlockSize - Offset; + } + + DEBUG ((EFI_D_UPDATE, "Update Flash area from %08LX to %08LX\n", FlashAddress, (UINT64)FlashAddress + Length)); + // + // Update the block + // + Status = UpdateBufferInOneBlock ( + FvbProtocol, + Lba, + Offset, + Length, + BlockSize, + Image + ); + if (EFI_ERROR (Status)) { + FreePool (FwVolHeader); + return Status; + } + + // + // Now increment FlashAddress, ImageBuffer and decrease the + // left size to prepare for the next block update. + // + FlashAddress = FlashAddress + Length; + Image = Image + Length; + TotalSize = TotalSize - Length; + if (TotalSize <= 0) { + break; + } + } + BaseAddress = NextBlock; + Lba++; + } + + if (EFI_ERROR (Status)) { + break; + } + BlockMap++; + } + + FreePool (FwVolHeader); + + *UpdatedSize = SizeLeft - TotalSize; + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c new file mode 100644 index 0000000000..023506e6ee --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c @@ -0,0 +1,1133 @@ +/** @file + Source file for the component update driver. It parse the update + configuration file and pass the information to the update driver + so that the driver can perform updates accordingly. + + Copyright (c) 2002 - 2015, Intel 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 "UpdateDriver.h" + +/** + Copy one line data from buffer data to the line buffer. + + @param Buffer Buffer data. + @param BufferSize Buffer Size. + @param LineBuffer Line buffer to store the found line data. + @param LineSize On input, size of the input line buffer. + On output, size of the actual line buffer. + + @retval EFI_BUFFER_TOO_SMALL The size of input line buffer is not enough. + @retval EFI_SUCCESS Copy line data into the line buffer. + +**/ +EFI_STATUS +ProfileGetLine ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + IN OUT UINT8 *LineBuffer, + IN OUT UINTN *LineSize + ) +{ + UINTN Length; + UINT8 *PtrBuf; + UINTN PtrEnd; + + PtrBuf = Buffer; + PtrEnd = (UINTN)Buffer + BufferSize; + + // + // 0x0D indicates a line break. Otherwise there is no line break + // + while ((UINTN)PtrBuf < PtrEnd) { + if (*PtrBuf == 0x0D) { + break; + } + PtrBuf++; + } + + if ((UINTN)PtrBuf >= (PtrEnd - 1)) { + // + // The buffer ends without any line break + // or it is the last character of the buffer + // + Length = BufferSize; + } else if (*(PtrBuf + 1) == 0x0A) { + // + // Further check if a 0x0A follows. If yes, count 0xA + // + Length = (UINTN) PtrBuf - (UINTN) Buffer + 2; + } else { + Length = (UINTN) PtrBuf - (UINTN) Buffer + 1; + } + + if (Length > (*LineSize)) { + *LineSize = Length; + return EFI_BUFFER_TOO_SMALL; + } + + SetMem (LineBuffer, *LineSize, 0x0); + *LineSize = Length; + CopyMem (LineBuffer, Buffer, Length); + + return EFI_SUCCESS; +} + +/** + Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail. + + @param Buffer On input, buffer data to be trimed. + On output, the trimmed buffer. + @param BufferSize On input, size of original buffer data. + On output, size of the trimmed buffer. + +**/ +VOID +ProfileTrim ( + IN OUT UINT8 *Buffer, + IN OUT UINTN *BufferSize + ) +{ + UINTN Length; + UINT8 *PtrBuf; + UINT8 *PtrEnd; + + if (*BufferSize == 0) { + return; + } + + // + // Trim the tail first, include CR, LF, TAB, and SPACE. + // + Length = *BufferSize; + PtrBuf = (UINT8 *) ((UINTN) Buffer + Length - 1); + while (PtrBuf >= Buffer) { + if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A ) + && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) { + break; + } + PtrBuf --; + } + + // + // all spaces, a blank line, return directly; + // + if (PtrBuf < Buffer) { + *BufferSize = 0; + return; + } + + Length = (UINTN)PtrBuf - (UINTN)Buffer + 1; + PtrEnd = PtrBuf; + PtrBuf = Buffer; + + // + // Now skip the heading CR, LF, TAB and SPACE + // + while (PtrBuf <= PtrEnd) { + if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A ) + && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) { + break; + } + PtrBuf++; + } + + // + // If no heading CR, LF, TAB or SPACE, directly return + // + if (PtrBuf == Buffer) { + *BufferSize = Length; + return; + } + + *BufferSize = (UINTN)PtrEnd - (UINTN)PtrBuf + 1; + + // + // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE. + // Now move out all these characters. + // + while (PtrBuf <= PtrEnd) { + *Buffer = *PtrBuf; + Buffer++; + PtrBuf++; + } + + return; +} + +/** + Insert new comment item into comment head. + + @param Buffer Comment buffer to be added. + @param BufferSize Size of comment buffer. + @param CommentHead Comment Item head entry. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS New comment item is inserted. + +**/ +EFI_STATUS +ProfileGetComments ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + IN OUT COMMENT_LINE **CommentHead + ) +{ + COMMENT_LINE *CommentItem; + + CommentItem = NULL; + CommentItem = AllocatePool (sizeof (COMMENT_LINE)); + if (CommentItem == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CommentItem->ptrNext = *CommentHead; + *CommentHead = CommentItem; + + // + // Add a trailing '\0' + // + CommentItem->ptrComment = AllocatePool (BufferSize + 1); + if (CommentItem->ptrComment == NULL) { + FreePool (CommentItem); + return EFI_OUT_OF_RESOURCES; + } + CopyMem (CommentItem->ptrComment, Buffer, BufferSize); + *(CommentItem->ptrComment + BufferSize) = '\0'; + + return EFI_SUCCESS; +} + +/** + Add new section item into Section head. + + @param Buffer Section item data buffer. + @param BufferSize Size of section item. + @param SectionHead Section item head entry. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Section item is NULL or Section item is added. + +**/ +EFI_STATUS +ProfileGetSection ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + IN OUT SECTION_ITEM **SectionHead + ) +{ + EFI_STATUS Status; + SECTION_ITEM *SectionItem; + UINTN Length; + UINT8 *PtrBuf; + + Status = EFI_SUCCESS; + // + // The first character of Buffer is '[', now we want for ']' + // + PtrBuf = (UINT8 *)((UINTN)Buffer + BufferSize - 1); + while (PtrBuf > Buffer) { + if (*PtrBuf == ']') { + break; + } + PtrBuf --; + } + if (PtrBuf <= Buffer) { + // + // Not found. Omit this line + // + return Status; + } + + // + // excluding the heading '[' and tailing ']' + // + Length = PtrBuf - Buffer - 1; + ProfileTrim ( + Buffer + 1, + &Length + ); + + // + // omit this line if the section name is null + // + if (Length == 0) { + return Status; + } + + SectionItem = AllocatePool (sizeof (SECTION_ITEM)); + if (SectionItem == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SectionItem->ptrSection = NULL; + SectionItem->SecNameLen = Length; + SectionItem->ptrEntry = NULL; + SectionItem->ptrValue = NULL; + SectionItem->ptrNext = *SectionHead; + *SectionHead = SectionItem; + + // + // Add a trailing '\0' + // + SectionItem->ptrSection = AllocatePool (Length + 1); + if (SectionItem->ptrSection == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // excluding the heading '[' + // + CopyMem (SectionItem->ptrSection, Buffer + 1, Length); + *(SectionItem->ptrSection + Length) = '\0'; + + return EFI_SUCCESS; +} + +/** + Add new section entry and entry value into Section head. + + @param Buffer Section entry data buffer. + @param BufferSize Size of section entry. + @param SectionHead Section item head entry. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Section entry is NULL or Section entry is added. + +**/ +EFI_STATUS +ProfileGetEntry ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + IN OUT SECTION_ITEM **SectionHead + ) +{ + EFI_STATUS Status; + SECTION_ITEM *SectionItem; + SECTION_ITEM *PtrSection; + UINTN Length; + UINT8 *PtrBuf; + UINT8 *PtrEnd; + + Status = EFI_SUCCESS; + PtrBuf = Buffer; + PtrEnd = (UINT8 *) ((UINTN)Buffer + BufferSize - 1); + + // + // First search for '=' + // + while (PtrBuf <= PtrEnd) { + if (*PtrBuf == '=') { + break; + } + PtrBuf++; + } + if (PtrBuf > PtrEnd) { + // + // Not found. Omit this line + // + return Status; + } + + // + // excluding the tailing '=' + // + Length = PtrBuf - Buffer; + ProfileTrim ( + Buffer, + &Length + ); + + // + // Omit this line if the entry name is null + // + if (Length == 0) { + return Status; + } + + // + // Omit this line if no section header has been found before + // + if (*SectionHead == NULL) { + return Status; + } + PtrSection = *SectionHead; + + SectionItem = AllocatePool (sizeof (SECTION_ITEM)); + if (SectionItem == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SectionItem->ptrSection = NULL; + SectionItem->ptrEntry = NULL; + SectionItem->ptrValue = NULL; + SectionItem->SecNameLen = PtrSection->SecNameLen; + SectionItem->ptrNext = *SectionHead; + *SectionHead = SectionItem; + + // + // SectionName, add a trailing '\0' + // + SectionItem->ptrSection = AllocatePool (PtrSection->SecNameLen + 1); + if (SectionItem->ptrSection == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (SectionItem->ptrSection, PtrSection->ptrSection, PtrSection->SecNameLen + 1); + + // + // EntryName, add a trailing '\0' + // + SectionItem->ptrEntry = AllocatePool (Length + 1); + if (SectionItem->ptrEntry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (SectionItem->ptrEntry, Buffer, Length); + *(SectionItem->ptrEntry + Length) = '\0'; + + // + // Next search for '#' + // + PtrBuf = PtrBuf + 1; + Buffer = PtrBuf; + while (PtrBuf <= PtrEnd) { + if (*PtrBuf == '#') { + break; + } + PtrBuf++; + } + Length = PtrBuf - Buffer; + ProfileTrim ( + Buffer, + &Length + ); + + if (Length > 0) { + // + // EntryValue, add a trailing '\0' + // + SectionItem->ptrValue = AllocatePool (Length + 1); + if (SectionItem->ptrValue == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (SectionItem->ptrValue, Buffer, Length); + *(SectionItem->ptrValue + Length) = '\0'; + } + + return EFI_SUCCESS; +} + +/** + Free all comment entry and section entry. + + @param Section Section entry list. + @param Comment Comment entry list. + +**/ +VOID +FreeAllList ( + IN SECTION_ITEM *Section, + IN COMMENT_LINE *Comment + ) +{ + SECTION_ITEM *PtrSection; + COMMENT_LINE *PtrComment; + + while (Section != NULL) { + PtrSection = Section; + Section = Section->ptrNext; + if (PtrSection->ptrEntry != NULL) { + FreePool (PtrSection->ptrEntry); + } + if (PtrSection->ptrSection != NULL) { + FreePool (PtrSection->ptrSection); + } + if (PtrSection->ptrValue != NULL) { + FreePool (PtrSection->ptrValue); + } + FreePool (PtrSection); + } + + while (Comment != NULL) { + PtrComment = Comment; + Comment = Comment->ptrNext; + if (PtrComment->ptrComment != NULL) { + FreePool (PtrComment->ptrComment); + } + FreePool (PtrComment); + } + + return; +} + +/** + Get section entry value. + + @param Section Section entry list. + @param SectionName Section name. + @param EntryName Section entry name. + @param EntryValue Point to the got entry value. + + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_SUCCESS Section entry value is got. + +**/ +EFI_STATUS +UpdateGetProfileString ( + IN SECTION_ITEM *Section, + IN UINT8 *SectionName, + IN UINT8 *EntryName, + OUT UINT8 **EntryValue + ) +{ + *EntryValue = NULL; + + while (Section != NULL) { + if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrSection, (CONST CHAR8 *) SectionName) == 0) { + if (Section->ptrEntry != NULL) { + if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrEntry, (CONST CHAR8 *) EntryName) == 0) { + break; + } + } + } + Section = Section->ptrNext; + } + + if (Section == NULL) { + return EFI_NOT_FOUND; + } + + *EntryValue = (UINT8 *) Section->ptrValue; + + return EFI_SUCCESS; +} + +/** + Convert the dec or hex ascii string to value. + + @param Str ascii string to be converted. + + @return the converted value. + +**/ +UINTN +UpdateAtoi ( + IN UINT8 *Str + ) +{ + UINTN Number; + + Number = 0; + + // + // Skip preceeding while spaces + // + while (*Str != '\0') { + if (*Str != 0x20) { + break; + } + Str++; + } + + if (*Str == '\0') { + return Number; + } + + // + // Find whether the string is prefixed by 0x. + // That is, it should be xtoi or atoi. + // + if (*Str == '0') { + if ((*(Str+1) == 'x' ) || ( *(Str+1) == 'X')) { + return AsciiStrHexToUintn ((CONST CHAR8 *) Str); + } + } + + while (*Str != '\0') { + if ((*Str >= '0') && (*Str <= '9')) { + Number = Number * 10 + *Str - '0'; + } else { + break; + } + Str++; + } + + return Number; +} + +/** + Converts a decimal value to a Null-terminated ascii string. + + @param Buffer Pointer to the output buffer for the produced Null-terminated + ASCII string. + @param Value The 64-bit sgned value to convert to a string. + + @return The number of ASCII characters in Buffer not including the Null-terminator. + +**/ +UINTN +UpdateValueToString ( + IN OUT UINT8 *Buffer, + IN INT64 Value + ) +{ + UINT8 TempBuffer[30]; + UINT8 *TempStr; + UINT8 *BufferPtr; + UINTN Count; + UINT32 Remainder; + + TempStr = TempBuffer; + BufferPtr = Buffer; + Count = 0; + + if (Value < 0) { + *BufferPtr = '-'; + BufferPtr++; + Value = -Value; + Count++; + } + + do { + Value = (INT64) DivU64x32Remainder ((UINT64)Value, 10, &Remainder); + // + // The first item of TempStr is not occupied. It's kind of flag + // + TempStr++; + Count++; + *TempStr = (UINT8) ((UINT8)Remainder + '0'); + } while (Value != 0); + + // + // Reverse temp string into Buffer. + // + while (TempStr != TempBuffer) { + *BufferPtr = *TempStr; + BufferPtr++; + TempStr --; + } + + *BufferPtr = 0; + + return Count; +} + +/** + Convert the input value to a ascii string, + and concatenates this string to the input string. + + @param Str Pointer to a Null-terminated ASCII string. + @param Number The unsgned value to convert to a string. + +**/ +VOID +UpdateStrCatNumber ( + IN OUT UINT8 *Str, + IN UINTN Number + ) +{ + UINTN Count; + + while (*Str != '\0') { + Str++; + } + + Count = UpdateValueToString (Str, (INT64)Number); + + *(Str + Count) = '\0'; + + return; +} + +/** + Convert the input ascii string into GUID value. + + @param Str Ascii GUID string to be converted. + @param Guid Pointer to the converted GUID value. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_NOT_FOUND The input ascii string is not a valid GUID format string. + @retval EFI_SUCCESS GUID value is got. + +**/ +EFI_STATUS +UpdateStringToGuid ( + IN UINT8 *Str, + IN OUT EFI_GUID *Guid + ) +{ + UINT8 *PtrBuffer; + UINT8 *PtrPosition; + UINT8 *Buffer; + UINTN Data; + UINTN StrLen; + UINTN Index; + UINT8 Digits[3]; + + StrLen = AsciiStrLen ((CONST CHAR8 *) Str); + Buffer = AllocateCopyPool (StrLen + 1, Str); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Data1 + // + PtrBuffer = Buffer; + PtrPosition = PtrBuffer; + while (*PtrBuffer != '\0') { + if (*PtrBuffer == '-') { + break; + } + PtrBuffer++; + } + if (*PtrBuffer == '\0') { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + + *PtrBuffer = '\0'; + Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition); + Guid->Data1 = (UINT32)Data; + + // + // Data2 + // + PtrBuffer++; + PtrPosition = PtrBuffer; + while (*PtrBuffer != '\0') { + if (*PtrBuffer == '-') { + break; + } + PtrBuffer++; + } + if (*PtrBuffer == '\0') { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + *PtrBuffer = '\0'; + Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition); + Guid->Data2 = (UINT16)Data; + + // + // Data3 + // + PtrBuffer++; + PtrPosition = PtrBuffer; + while (*PtrBuffer != '\0') { + if (*PtrBuffer == '-') { + break; + } + PtrBuffer++; + } + if (*PtrBuffer == '\0') { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + *PtrBuffer = '\0'; + Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition); + Guid->Data3 = (UINT16)Data; + + // + // Data4[0..1] + // + for ( Index = 0 ; Index < 2 ; Index++) { + PtrBuffer++; + if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + Digits[0] = *PtrBuffer; + PtrBuffer++; + Digits[1] = *PtrBuffer; + Digits[2] = '\0'; + Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits); + Guid->Data4[Index] = (UINT8)Data; + } + + // + // skip the '-' + // + PtrBuffer++; + if ((*PtrBuffer != '-' ) || ( *PtrBuffer == '\0')) { + return EFI_NOT_FOUND; + } + + // + // Data4[2..7] + // + for ( ; Index < 8; Index++) { + PtrBuffer++; + if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + Digits[0] = *PtrBuffer; + PtrBuffer++; + Digits[1] = *PtrBuffer; + Digits[2] = '\0'; + Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits); + Guid->Data4[Index] = (UINT8)Data; + } + + FreePool (Buffer); + + return EFI_SUCCESS; +} + +/** + Pre process config data buffer into Section entry list and Comment entry list. + + @param DataBuffer Config raw file buffer. + @param BufferSize Size of raw buffer. + @param SectionHead Pointer to the section entry list. + @param CommentHead Pointer to the comment entry list. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Config data buffer is preprocessed. + +**/ +EFI_STATUS +PreProcessDataFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize, + IN OUT SECTION_ITEM **SectionHead, + IN OUT COMMENT_LINE **CommentHead + ) +{ + EFI_STATUS Status; + CHAR8 *Source; + CHAR8 *CurrentPtr; + CHAR8 *BufferEnd; + CHAR8 *PtrLine; + UINTN LineLength; + UINTN SourceLength; + UINTN MaxLineLength; + + *SectionHead = NULL; + *CommentHead = NULL; + BufferEnd = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize); + CurrentPtr = (CHAR8 *) DataBuffer; + MaxLineLength = MAX_LINE_LENGTH; + Status = EFI_SUCCESS; + + PtrLine = AllocatePool (MaxLineLength); + if (PtrLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + while (CurrentPtr < BufferEnd) { + Source = CurrentPtr; + SourceLength = (UINTN)BufferEnd - (UINTN)CurrentPtr; + LineLength = MaxLineLength; + // + // With the assumption that line length is less than 512 + // characters. Otherwise BUFFER_TOO_SMALL will be returned. + // + Status = ProfileGetLine ( + (UINT8 *) Source, + SourceLength, + (UINT8 *) PtrLine, + &LineLength + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // If buffer too small, re-allocate the buffer according + // to the returned LineLength and try again. + // + FreePool (PtrLine); + PtrLine = NULL; + PtrLine = AllocatePool (LineLength); + if (PtrLine == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + SourceLength = LineLength; + Status = ProfileGetLine ( + (UINT8 *) Source, + SourceLength, + (UINT8 *) PtrLine, + &LineLength + ); + if (EFI_ERROR (Status)) { + break; + } + MaxLineLength = LineLength; + } else { + break; + } + } + CurrentPtr = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength); + + // + // Line got. Trim the line before processing it. + // + ProfileTrim ( + (UINT8 *) PtrLine, + &LineLength + ); + + // + // Blank line + // + if (LineLength == 0) { + continue; + } + + if (PtrLine[0] == '#') { + Status = ProfileGetComments ( + (UINT8 *) PtrLine, + LineLength, + CommentHead + ); + } else if (PtrLine[0] == '[') { + Status = ProfileGetSection ( + (UINT8 *) PtrLine, + LineLength, + SectionHead + ); + } else { + Status = ProfileGetEntry ( + (UINT8 *) PtrLine, + LineLength, + SectionHead + ); + } + + if (EFI_ERROR (Status)) { + break; + } + } + + // + // Free buffer + // + FreePool (PtrLine); + + return Status; +} + +/** + Parse Config data file to get the updated data array. + + @param DataBuffer Config raw file buffer. + @param BufferSize Size of raw buffer. + @param NumOfUpdates Pointer to the number of update data. + @param UpdateArray Pointer to the config of update data. + + @retval EFI_NOT_FOUND No config data is found. + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Parse the config file successfully. + +**/ +EFI_STATUS +ParseUpdateDataFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize, + IN OUT UINTN *NumOfUpdates, + IN OUT UPDATE_CONFIG_DATA **UpdateArray + ) +{ + EFI_STATUS Status; + CHAR8 *Value; + CHAR8 *SectionName; + CHAR8 Entry[MAX_LINE_LENGTH]; + SECTION_ITEM *SectionHead; + COMMENT_LINE *CommentHead; + UINTN Num; + UINTN Index; + EFI_GUID FileGuid; + + SectionHead = NULL; + CommentHead = NULL; + + // + // First process the data buffer and get all sections and entries + // + Status = PreProcessDataFile ( + DataBuffer, + BufferSize, + &SectionHead, + &CommentHead + ); + if (EFI_ERROR (Status)) { + FreeAllList (SectionHead, CommentHead); + return Status; + } + + // + // Now get NumOfUpdate + // + Value = NULL; + Status = UpdateGetProfileString ( + SectionHead, + (UINT8 *) "Head", + (UINT8 *) "NumOfUpdate", + (UINT8 **) &Value + ); + if (Value == NULL) { + FreeAllList (SectionHead, CommentHead); + return EFI_NOT_FOUND; + } + Num = UpdateAtoi((UINT8 *) Value); + if (Num <= 0) { + FreeAllList (SectionHead, CommentHead); + return EFI_NOT_FOUND; + } + + *NumOfUpdates = Num; + *UpdateArray = AllocatePool ((sizeof (UPDATE_CONFIG_DATA) * Num)); + if (*UpdateArray == NULL) { + FreeAllList (SectionHead, CommentHead); + return EFI_OUT_OF_RESOURCES; + } + + for ( Index = 0 ; Index < *NumOfUpdates ; Index++) { + // + // Get the section name of each update + // + AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update"); + UpdateStrCatNumber ((UINT8 *) Entry, Index); + Value = NULL; + Status = UpdateGetProfileString ( + SectionHead, + (UINT8 *) "Head", + (UINT8 *) Entry, + (UINT8 **) &Value + ); + if (Value == NULL) { + FreeAllList (SectionHead, CommentHead); + return EFI_NOT_FOUND; + } + + // + // The section name of this update has been found. + // Now looks for all the config data of this update + // + SectionName = Value; + + // + // UpdateType + // + Value = NULL; + Status = UpdateGetProfileString ( + SectionHead, + (UINT8 *) SectionName, + (UINT8 *) "UpdateType", + (UINT8 **) &Value + ); + if (Value == NULL) { + FreeAllList (SectionHead, CommentHead); + return EFI_NOT_FOUND; + } + + Num = UpdateAtoi((UINT8 *) Value); + if (( Num >= (UINTN) UpdateOperationMaximum)) { + FreeAllList (SectionHead, CommentHead); + return Status; + } + (*UpdateArray)[Index].Index = Index; + (*UpdateArray)[Index].UpdateType = (UPDATE_OPERATION_TYPE) Num; + + // + // FvBaseAddress + // + Value = NULL; + Status = UpdateGetProfileString ( + SectionHead, + (UINT8 *) SectionName, + (UINT8 *) "FvBaseAddress", + (UINT8 **) &Value + ); + if (Value == NULL) { + FreeAllList (SectionHead, CommentHead); + return EFI_NOT_FOUND; + } + + Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value); + (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num; + + // + // FileBuid + // + Value = NULL; + Status = UpdateGetProfileString ( + SectionHead, + (UINT8 *) SectionName, + (UINT8 *) "FileGuid", + (UINT8 **) &Value + ); + if (Value == NULL) { + FreeAllList (SectionHead, CommentHead); + return EFI_NOT_FOUND; + } + + Status = UpdateStringToGuid ((UINT8 *) Value, &FileGuid); + if (EFI_ERROR (Status)) { + FreeAllList (SectionHead, CommentHead); + return Status; + } + CopyMem (&((*UpdateArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID)); + + // + // FaultTolerant + // Default value is FALSE + // + Value = NULL; + (*UpdateArray)[Index].FaultTolerant = FALSE; + Status = UpdateGetProfileString ( + SectionHead, + (UINT8 *) SectionName, + (UINT8 *) "FaultTolerant", + (UINT8 **) &Value + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + FreeAllList (SectionHead, CommentHead); + return Status; + } else if (Value != NULL) { + if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "TRUE") == 0) { + (*UpdateArray)[Index].FaultTolerant = TRUE; + } else if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "FALSE") == 0) { + (*UpdateArray)[Index].FaultTolerant = FALSE; + } + } + + if ((*UpdateArray)[Index].UpdateType == UpdateFvRange) { + // + // Length + // + Value = NULL; + Status = UpdateGetProfileString ( + SectionHead, + (UINT8 *) SectionName, + (UINT8 *) "Length", + (UINT8 **) &Value + ); + if (Value == NULL) { + FreeAllList (SectionHead, CommentHead); + return EFI_NOT_FOUND; + } + + Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value); + (*UpdateArray)[Index].Length = (UINTN) Num; + } + } + + // + // Now all configuration data got. Free those temporary buffers + // + FreeAllList (SectionHead, CommentHead); + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c new file mode 100644 index 0000000000..e1f1b023dc --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c @@ -0,0 +1,846 @@ +/** @file + Functions in this file will mainly focus on looking through the capsule + for the image to be programmed, and the flash area that is going to be + programed. + + Copyright (c) 2002 - 2014, Intel 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 "UpdateDriver.h" + +EFI_HII_HANDLE gHiiHandle; + +/** + Update the whole FV, or certain files in the FV. + + @param ConfigData Pointer to the config data on updating file. + @param ImageBuffer Image buffer to be updated. + @param ImageSize Image size. + @param FileType FFS file type. + @param FileAttributes FFS file attribute. + + @retval EFI_NOT_FOUND The matched FVB protocol is not found. + @retval EFI_SUCCESS The image buffer is updated into FV. + +**/ +EFI_STATUS +PerformUpdateOnFirmwareVolume ( + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINT8 *ImageBuffer, + IN UINTN ImageSize, + IN EFI_FV_FILETYPE FileType, + IN EFI_FV_FILE_ATTRIBUTES FileAttributes + ) +{ + EFI_STATUS Status; + BOOLEAN Found; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; + UINTN Index; + UINTN NumOfHandles; + EFI_HANDLE *HandleBuffer; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_FVB_ATTRIBUTES_2 Attributes; + + // + // Locate all Fvb protocol + // + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, + NULL, + &NumOfHandles, + &HandleBuffer + ); + if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) { + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + return EFI_NOT_FOUND; + } + + // + // Check the FVB protocol one by one + // + Found = FALSE; + FvbProtocol = NULL; + for (Index = 0; Index < NumOfHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &FvbProtocol + ); + if (EFI_ERROR (Status)) { + break; + } + + // + // Ensure this FVB protocol supported Write operation. + // + Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes); + if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) { + continue; + } + + Status = FvbProtocol->GetPhysicalAddress ( + FvbProtocol, + &BaseAddress + ); + if (EFI_ERROR (Status)) { + break; + } + if (BaseAddress == ConfigData->BaseAddress) { + Found = TRUE; + break; + } + } + + if (!Found) { + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + HandleBuffer = NULL; + } + return EFI_NOT_FOUND; + } + + // + // Now we have got the corresponding FVB protocol. Use the FVB protocol + // to update the whole FV, or certain files in the FV. + // + if (ConfigData->UpdateType == UpdateWholeFV) { + if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + Status = EFI_INVALID_PARAMETER; + } else { + Status = PerformUpdateOnWholeFv ( + HandleBuffer[Index], + FvbProtocol, + ConfigData, + ImageBuffer, + ImageSize + ); + } + } else if (ConfigData->UpdateType == UpdateFvFile) { + Status = PerformUpdateOnFvFile ( + HandleBuffer[Index], + FvbProtocol, + ConfigData, + ImageBuffer, + ImageSize, + FileType, + FileAttributes + ); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + HandleBuffer = NULL; + } + + return Status; +} + +/** + Update the file directly into flash area. + + @param ConfigData Pointer to the config data on updating file. + @param ImageBuffer Image buffer to be updated. + @param ImageSize Image size. + + @retval EFI_SUCCESS The file is updated into flash area. + @retval EFI_NOT_FOUND The FVB protocol for the updated flash area is not found. + +**/ +EFI_STATUS +PerformUpdateOnFlashArea ( + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINT8 *ImageBuffer, + IN UINTN ImageSize + ) +{ + EFI_STATUS Status; + UINTN SizeLeft; + EFI_PHYSICAL_ADDRESS FlashAddress; + UINT8 *PtrImage; + BOOLEAN Found; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; + UINTN Index; + UINTN NumOfHandles; + EFI_HANDLE *HandleBuffer; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_HANDLE FvbHandle; + UINTN SizeUpdated; + CHAR16 *TmpStr; + EFI_FVB_ATTRIBUTES_2 Attributes; + + SizeLeft = ImageSize; + PtrImage = ImageBuffer; + FlashAddress = ConfigData->BaseAddress; + Status = EFI_SUCCESS; + HandleBuffer = NULL; + + // + // Print on screen + // + TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FLASH_RANGE), NULL); + if (TmpStr != NULL) { + Print (TmpStr, FlashAddress, ((UINT64)SizeLeft + FlashAddress)); + FreePool (TmpStr); + } + + // + // Locate all Fvb protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, + NULL, + &NumOfHandles, + &HandleBuffer + ); + if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) { + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + return EFI_NOT_FOUND; + } + + while (SizeLeft > 0) { + // + // First get the FVB protocols. If the flash area is a FV, or sub FV, + // we can directly locate all the FVB protocol. Otherwise we should use + // implementation specific method to get the alternate FVB protocol + // + Found = FALSE; + FvbProtocol = NULL; + + // + // Check the FVB protocol one by one + // + for (Index = 0; Index < NumOfHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &FvbProtocol + ); + if (EFI_ERROR (Status)) { + break; + } + + // + // Ensure this FVB protocol supported Write operation. + // + Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes); + if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) { + continue; + } + + Status = FvbProtocol->GetPhysicalAddress ( + FvbProtocol, + &BaseAddress + ); + if (EFI_ERROR (Status)) { + break; + } + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress; + + // + // This sub area entry falls in the range of the FV + // + if ((FlashAddress >= BaseAddress) && (FlashAddress < (BaseAddress + FwVolHeader->FvLength))) { + Found = TRUE; + break; + } + } + + if (!Found) { + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + HandleBuffer = NULL; + } + return EFI_NOT_FOUND; + } + + FvbHandle = HandleBuffer[Index]; + SizeUpdated = 0; + + // + // If the flash area is boot required, the update must be fault tolerant + // + if (ConfigData->FaultTolerant) { + // + // Finally we are here. We have got the corresponding FVB protocol. Now + // we need to convert the physical address to LBA and offset and call + // FTW write. Also check if the flash range is larger than the FV. + // + Status = FaultTolerantUpdateOnPartFv ( + PtrImage, + SizeLeft, + &SizeUpdated, + ConfigData, + FlashAddress, + FvbProtocol, + FvbHandle + ); + } else { + // + // Finally we are here. We have got the corresponding FVB protocol. Now + // we need to convert the physical address to LBA and offset and call + // FVB write. Also check if the flash range is larger than the FV. + // + Status = NonFaultTolerantUpdateOnPartFv ( + PtrImage, + SizeLeft, + &SizeUpdated, + FlashAddress, + FvbProtocol, + FvbHandle + ); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // As part of the FV has been replaced, the FV driver shall re-parse + // the firmware volume. So re-install FVB protocol here + // + Status = gBS->ReinstallProtocolInterface ( + FvbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + FvbProtocol, + FvbProtocol + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check if we are done with the update + // + SizeLeft = SizeLeft - SizeUpdated; + FlashAddress = FlashAddress + SizeUpdated; + PtrImage = PtrImage + SizeUpdated; + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + HandleBuffer = NULL; + } + + return Status; +} + +/** + Find the updated file, and program it into the flash area based on the config data. + + @param FwVolProtocol Pointer to FV protocol that contains the updated file. + @param ConfigData Pointer to the Config Data on updating file. + + @retval EFI_INVALID_PARAMETER The update operation is not valid. + @retval EFI_NOT_FOUND The updated file is not found. + @retval EFI_SUCCESS The file is updated into the flash area. + +**/ +EFI_STATUS +PerformUpdate ( + IN EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol, + IN UPDATE_CONFIG_DATA *ConfigData + ) +{ + EFI_STATUS Status; + UINT8 *FileBuffer; + UINTN FileBufferSize; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES Attrib; + EFI_SECTION_TYPE SectionType; + UINT32 AuthenticationStatus; + CHAR16 *TmpStr; + BOOLEAN StartToUpdate; + + Status = EFI_SUCCESS; + FileBuffer = NULL; + FileBufferSize = 0; + Status = FwVolProtocol->ReadFile ( + FwVolProtocol, + &(ConfigData->FileGuid), + (VOID **) &FileBuffer, + &FileBufferSize, + &FileType, + &Attrib, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + return Status; + } + + StartToUpdate = FALSE; + + // + // Check if the update image is the one we require + // and then perform the update + // + switch (ConfigData->UpdateType) { + + case UpdateWholeFV: + + // + // For UpdateWholeFv, the update file shall be a firmware volume + // image file. + // + if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be of TYPE EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n")); + Status = EFI_INVALID_PARAMETER; + } else { + if (FileBuffer != NULL) { + FreePool (FileBuffer); + } + SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; + FileBuffer = NULL; + FileBufferSize = 0; + Status = FwVolProtocol->ReadSection ( + FwVolProtocol, + &(ConfigData->FileGuid), + SectionType, + 0, + (VOID **) &FileBuffer, + &FileBufferSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + // + // Execute the update. For UpdateWholeFv, the update + // will always execute on a whole FV + // + StartToUpdate = TRUE; + Status = PerformUpdateOnFirmwareVolume ( + ConfigData, + FileBuffer, + FileBufferSize, + FileType, + Attrib + ); + + } else { + DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be sectioned with TYPE EFI_SECTION_FIRMWARE_VOLUME_IMAGE\n")); + } + } + break; + + case UpdateFvRange: + + // + // For UpdateFvRange, the update file shall be a raw file + // which does not contain any sections. The contents of the file + // will be directly programmed. + // + if (FileType != EFI_FV_FILETYPE_RAW) { + DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should of TYPE EFI_FV_FILETYPE_RAW\n")); + Status = EFI_INVALID_PARAMETER; + } else { + // + // For UpdateFvRange, the update may be performed on a sub area + // of a certain FV, or a flash area that is not FV, or part of FV. + // The update may also go across more than one FVs. + // + StartToUpdate = TRUE; + Status = PerformUpdateOnFlashArea ( + ConfigData, + FileBuffer, + FileBufferSize + ); + } + break; + + case UpdateFvFile: + + // + // No check will be done the the file got. The contents of the file + // will be directly programmed. + // Though UpdateFvFile will only update a single file, but the update + // will always execute on a FV + // + StartToUpdate = TRUE; + Status = PerformUpdateOnFirmwareVolume ( + ConfigData, + FileBuffer, + FileBufferSize, + FileType, + Attrib + ); + break; + + default: + Status = EFI_INVALID_PARAMETER; + } + + if (StartToUpdate) { + if (EFI_ERROR (Status)) { + TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_ABORTED), NULL); + } else { + TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_DONE), NULL); + } + if (TmpStr != NULL) { + Print (TmpStr); + FreePool (TmpStr); + } + } + + if (FileBuffer != NULL) { + FreePool(FileBuffer); + FileBuffer = NULL; + } + + return Status; +} + +/** + Process the input firmware volume by using DXE service ProcessFirmwareVolume. + + @param DataBuffer Point to the FV image to be processed. + @param BufferSize Size of the FV image buffer. + @param FwVolProtocol Point to the installed FV protocol for the input FV image. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_VOLUME_CORRUPTED FV image is corrupted. + @retval EFI_SUCCESS FV image is processed and FV protocol is installed. + +**/ +EFI_STATUS +ProcessUpdateImage ( + UINT8 *DataBuffer, + UINTN BufferSize, + EFI_FIRMWARE_VOLUME2_PROTOCOL **FwVolProtocol + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_HANDLE FwVolHandle; + EFI_STATUS Status; + UINT8 *ProcessedDataBuffer; + UINT32 FvAlignment; + + ProcessedDataBuffer = NULL; + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DataBuffer; + if (FwVolHeader->FvLength != BufferSize) { + return EFI_VOLUME_CORRUPTED; + } + + FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); + // + // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value. + // + if (FvAlignment < 8) { + FvAlignment = 8; + } + // + // Check FvImage Align is required. + // + if (((UINTN) FwVolHeader % FvAlignment) == 0) { + ProcessedDataBuffer = DataBuffer; + } else { + // + // Allocate new aligned buffer to store DataBuffer. + // + ProcessedDataBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment); + if (ProcessedDataBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (ProcessedDataBuffer, DataBuffer, BufferSize); + } + // + // Process the firmware volume + // + gDS->ProcessFirmwareVolume ( + ProcessedDataBuffer, + BufferSize, + &FwVolHandle + ); + + // + // Get the FwVol protocol + // + Status = gBS->HandleProtocol ( + FwVolHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) FwVolProtocol + ); + + return Status; +} + +/** + Find the image in the same FV and program it in a target Firmware Volume device. + After update image, it will reset system and no return. + + @param ImageHandle A handle for the image that is initializing this driver + @param SystemTable A pointer to the EFI system table + + @retval EFI_ABORTED System reset failed. + @retval EFI_NOT_FOUND The updated image is not found in the same FV. + +**/ +EFI_STATUS +EFIAPI +InitializeUpdateDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol; + EFI_FIRMWARE_VOLUME2_PROTOCOL *DataFwVolProtocol; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *AlignedDevPathNode; + EFI_DEVICE_PATH_PROTOCOL *FilePathNode; + EFI_SECTION_TYPE SectionType; + UINT8 *FileBuffer; + UINTN FileBufferSize; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES Attrib; + UINT32 AuthenticationStatus; + UPDATE_CONFIG_DATA *ConfigData; + UPDATE_CONFIG_DATA *UpdateConfigData; + UINTN NumOfUpdates; + UINTN Index; + CHAR16 *TmpStr; + + // + // Clear screen + // + if (gST->ConOut != NULL) { + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT); + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + } + + gHiiHandle = HiiAddPackages ( + &gEfiCallerIdGuid, + NULL, + UpdateDriverDxeStrings, + NULL + ); + ASSERT (gHiiHandle != NULL); + + // + // In order to look for the update data file and programmed image file + // from the same volume which this driver is dispatched from, we need + // to get the device path of this driver image. It is done by first + // locate the LoadedImageProtocol and then get its device path + // + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImageProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the firmware volume protocol where this file resides + // + Status = gBS->HandleProtocol ( + LoadedImageProtocol->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &FwVolProtocol + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Shall do some extra check to see if it is really contained in the FV? + // Should be able to find the section of this driver in the the FV. + // + FilePathNode = LoadedImageProtocol->FilePath; + FwVolFilePathNode = NULL; + while (!IsDevicePathEnd (FilePathNode)) { + if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePathNode)!= NULL) { + FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePathNode; + break; + } + FilePathNode = NextDevicePathNode (FilePathNode); + } + + if (FwVolFilePathNode != NULL) { + AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength (FwVolFilePathNode), FwVolFilePathNode); + + SectionType = EFI_SECTION_PE32; + FileBuffer = NULL; + FileBufferSize = 0; + Status = FwVolProtocol->ReadSection ( + FwVolProtocol, + &(AlignedDevPathNode->FvFileName), + SectionType, + 0, + (VOID **) &FileBuffer, + &FileBufferSize, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + FreePool (AlignedDevPathNode); + return Status; + } + + if (FileBuffer != NULL) { + FreePool(FileBuffer); + FileBuffer = NULL; + } + + // + // Check the NameGuid of the udpate driver so that it can be + // used as the CallerId in fault tolerant write protocol + // + if (!CompareGuid (&gEfiCallerIdGuid, &(AlignedDevPathNode->FvFileName))) { + FreePool (AlignedDevPathNode); + return EFI_NOT_FOUND; + } + FreePool (AlignedDevPathNode); + } else { + return EFI_NOT_FOUND; + } + + // + // Now try to find the script file. The script file is usually + // a raw data file which does not contain any sections. + // + FileBuffer = NULL; + FileBufferSize = 0; + Status = FwVolProtocol->ReadFile ( + FwVolProtocol, + &gEfiConfigFileNameGuid, + (VOID **) &FileBuffer, + &FileBufferSize, + &FileType, + &Attrib, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + return Status; + } + if (FileType != EFI_FV_FILETYPE_RAW) { + return EFI_NOT_FOUND; + } + + // + // Parse the configuration file. + // + ConfigData = NULL; + NumOfUpdates = 0; + Status = ParseUpdateDataFile ( + FileBuffer, + FileBufferSize, + &NumOfUpdates, + &ConfigData + ); + if (FileBuffer != NULL) { + FreePool (FileBuffer); + FileBuffer = NULL; + } + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (ConfigData != NULL); + + // + // Now find the update image. The update image should be put in a FV, and then + // encapsulated as a raw FFS file. This is to prevent the update image from + // being dispatched. So the raw data we get here should be an FV. We need to + // process this FV and read the files that is going to be updated. + // + FileBuffer = NULL; + FileBufferSize = 0; + Status = FwVolProtocol->ReadFile ( + FwVolProtocol, + &gEfiUpdateDataFileGuid, + (VOID **) &FileBuffer, + &FileBufferSize, + &FileType, + &Attrib, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + return Status; + } + if (FileType != EFI_FV_FILETYPE_RAW) { + return EFI_NOT_FOUND; + } + + // + // FileBuffer should be an FV. Process the FV + // + DataFwVolProtocol = NULL; + Status = ProcessUpdateImage ( + FileBuffer, + FileBufferSize, + &DataFwVolProtocol + ); + if (EFI_ERROR (Status)) { + FreePool (FileBuffer); + return Status; + } + + // + // Print on screen + // + TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_PROCESS_DATA), NULL); + if (TmpStr != NULL) { + Print (TmpStr); + FreePool(TmpStr); + } + + // + // Execute the update + // + Index = 0; + UpdateConfigData = ConfigData; + while (Index < NumOfUpdates) { + Status = PerformUpdate ( + DataFwVolProtocol, + UpdateConfigData + ); + // + // Shall updates be serialized so that if an update is not successfully completed, + // the remaining updates won't be performed. + // + if (EFI_ERROR (Status)) { + break; + } + + Index++; + UpdateConfigData++; + } + + if (EFI_ERROR (Status)) { + if (ConfigData != NULL) { + FreePool(ConfigData); + ConfigData = NULL; + } + return Status; + } + + // + // Call system reset + // + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + + // + // Hopefully it won't be reached + // + return EFI_ABORTED; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriver.h b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriver.h new file mode 100644 index 0000000000..e1f22a9d5a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriver.h @@ -0,0 +1,213 @@ +/** @file + Common defines and definitions for a component update driver. + + Copyright (c) 2002 - 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 _EFI_UPDATE_DRIVER_H_ +#define _EFI_UPDATE_DRIVER_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HII_HANDLE gHiiHandle; + +typedef enum { + UpdateWholeFV = 0, // 0, update whole FV + UpdateFvFile, // 1, update a set of FV files asynchronously + UpdateFvRange, // 2, update part of FV or flash + UpdateOperationMaximum // 3 +} UPDATE_OPERATION_TYPE; + +typedef struct { + UINTN Index; + UPDATE_OPERATION_TYPE UpdateType; + EFI_DEVICE_PATH_PROTOCOL DevicePath; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_GUID FileGuid; + UINTN Length; + BOOLEAN FaultTolerant; +} UPDATE_CONFIG_DATA; + +typedef struct _SECTION_ITEM SECTION_ITEM; +struct _SECTION_ITEM { + CHAR8 *ptrSection; + UINTN SecNameLen; + CHAR8 *ptrEntry; + CHAR8 *ptrValue; + SECTION_ITEM *ptrNext; +}; + +typedef struct _COMMENT_LINE COMMENT_LINE; +struct _COMMENT_LINE { + CHAR8 *ptrComment; + COMMENT_LINE *ptrNext; +}; + +typedef struct { + EFI_GUID FileGuid; +} UPDATE_PRIVATE_DATA; + +#define MAX_LINE_LENGTH 512 +#define EFI_D_UPDATE EFI_D_ERROR + +#define MIN_ALIGNMENT_SIZE 4 +#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0) + +/** + Parse Config data file to get the updated data array. + + @param DataBuffer Config raw file buffer. + @param BufferSize Size of raw buffer. + @param NumOfUpdates Pointer to the number of update data. + @param UpdateArray Pointer to the config of update data. + + @retval EFI_NOT_FOUND No config data is found. + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Parse the config file successfully. + +**/ +EFI_STATUS +ParseUpdateDataFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize, + IN OUT UINTN *NumOfUpdates, + IN OUT UPDATE_CONFIG_DATA **UpdateArray + ); + +/** + Update the whole FV image, and reinsall FVB protocol for the updated FV image. + + @param FvbHandle Handle of FVB protocol for the updated flash range. + @param FvbProtocol FVB protocol. + @param ConfigData Config data on updating driver. + @param ImageBuffer Image buffer to be updated. + @param ImageSize Image size. + + @retval EFI_INVALID_PARAMETER Update type is not UpdateWholeFV. + Or Image size is not same to the size of whole FV. + @retval EFI_OUT_OF_RESOURCES No enoug memory is allocated. + @retval EFI_SUCCESS FV image is updated, and its FVB protocol is reinstalled. + +**/ +EFI_STATUS +PerformUpdateOnWholeFv ( + IN EFI_HANDLE FvbHandle, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINT8 *ImageBuffer, + IN UINTN ImageSize + ); + +/** + Update certain file in the FV. + + @param FvbHandle Handle of FVB protocol for the updated flash range. + @param FvbProtocol FVB protocol. + @param ConfigData Config data on updating driver. + @param ImageBuffer Image buffer to be updated. + @param ImageSize Image size. + @param FileType FFS file type. + @param FileAttributes FFS file attribute + + @retval EFI_INVALID_PARAMETER Update type is not UpdateFvFile. + Or Image size is not same to the size of whole FV. + @retval EFI_UNSUPPORTED PEIM FFS is unsupported to be updated. + @retval EFI_SUCCESS The FFS file is added into FV. + +**/ +EFI_STATUS +PerformUpdateOnFvFile ( + IN EFI_HANDLE FvbHandle, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN UPDATE_CONFIG_DATA *ConfigData, + IN UINT8 *ImageBuffer, + IN UINTN ImageSize, + IN EFI_FV_FILETYPE FileType, + IN EFI_FV_FILE_ATTRIBUTES FileAttributes + ); + +/** + Update the buffer into flash area in fault tolerant write method. + + @param ImageBuffer Image buffer to be updated. + @param SizeLeft Size of the image buffer. + @param UpdatedSize Size of the updated buffer. + @param ConfigData Config data on updating driver. + @param FlashAddress Flash address to be updated as start address. + @param FvbProtocol FVB protocol. + @param FvbHandle Handle of FVB protocol for the updated flash range. + + @retval EFI_SUCCESS Buffer data is updated into flash. + @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area. + @retval EFI_NOT_FOUND FTW protocol doesn't exist. + @retval EFI_OUT_OF_RESOURCES No enough backup space. + @retval EFI_ABORTED Error happen when update flash area. + +**/ +EFI_STATUS +FaultTolerantUpdateOnPartFv ( + IN UINT8 *ImageBuffer, + IN UINTN SizeLeft, + IN OUT UINTN *UpdatedSize, + IN UPDATE_CONFIG_DATA *ConfigData, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN EFI_HANDLE FvbHandle + ); + +/** + Directly update the buffer into flash area without fault tolerant write method. + + @param ImageBuffer Image buffer to be updated. + @param SizeLeft Size of the image buffer. + @param UpdatedSize Size of the updated buffer. + @param FlashAddress Flash address to be updated as start address. + @param FvbProtocol FVB protocol. + @param FvbHandle Handle of FVB protocol for the updated flash range. + + @retval EFI_SUCCESS Buffer data is updated into flash. + @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area. + @retval EFI_OUT_OF_RESOURCES No enough backup space. + +**/ +EFI_STATUS +NonFaultTolerantUpdateOnPartFv ( + IN UINT8 *ImageBuffer, + IN UINTN SizeLeft, + IN OUT UINTN *UpdatedSize, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, + IN EFI_HANDLE FvbHandle + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf new file mode 100644 index 0000000000..d83a1ecb57 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf @@ -0,0 +1,76 @@ +## @file +# Update Driver for Capulse update. +# +# This driver is intended to be put in a capsule (FV). If all goes well, +# then it should be dispatched from the capsule FV, then find the image +# in the same FV and program it in a target Firmware Volume device. +# +# 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 +# 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 = UpdateDriverDxe + MODULE_UNI_FILE = UpdateDriverDxe.uni + FILE_GUID = 0E84FC69-29CC-4C6D-92AC-6D476921850F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeUpdateDriver + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + UpdateDriver.h + UpdateStrings.uni + UpdateDispatcher.c + ParseUpdateProfile.c + FlashUpdate.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + PrintLib + HiiLib + DxeServicesTableLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + DevicePathLib + +[Guids] + gEfiConfigFileNameGuid ## CONSUMES ## File # FileName to store ConfigFile + gEfiUpdateDataFileGuid ## CONSUMES ## File # FileName to store Capsule Data. + +[Protocols] + gEfiFaultTolerantWriteProtocolGuid ## CONSUMES + gEfiFirmwareVolume2ProtocolGuid ## CONSUMES + gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES + gEfiLoadedImageProtocolGuid ## CONSUMES + +[Depex] + gEfiFirmwareVolumeBlockProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + UpdateDriverDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.uni b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.uni new file mode 100644 index 0000000000..dd37abe216 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxeExtra.uni new file mode 100644 index 0000000000..a01d23de84 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateStrings.uni b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateStrings.uni new file mode 100644 index 0000000000..16455937e5 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateStrings.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegion.c b/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegion.c new file mode 100644 index 0000000000..e432cf4403 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegion.c @@ -0,0 +1,170 @@ +/** @file + Produces the Legacy Region Protocol. + + This generic implementation of the Legacy Region Protocol does not actually + perform any lock/unlock operations. This module may be used on platforms + that do not provide HW locking of the legacy memory regions. It can also + be used as a template driver for implementing the Legacy Region Protocol on + a platform that does support HW locking of the legacy memory regions. + +Copyright (c) 2009, Intel 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 + +/** + Sets hardware to decode or not decode a region. + + @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance + @param Start Start of region to decode. + @param Length Size in bytes of the region. + @param On Decode/nondecode flag. + + @retval EFI_SUCCESS Decode range successfully changed. + +**/ +EFI_STATUS +EFIAPI +LegacyRegionDecode ( + IN EFI_LEGACY_REGION_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + IN BOOLEAN *On + ) +{ + return EFI_SUCCESS; +} + +/** + Sets a region to read only. + + @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance + @param Start Start of region to lock. + @param Length Size in bytes of the region. + @param Granularity Lock attribute affects this granularity in bytes. + + @retval EFI_SUCCESS The region was made read only. + +**/ +EFI_STATUS +EFIAPI +LegacyRegionLock ( + IN EFI_LEGACY_REGION_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity OPTIONAL + ) +{ + return EFI_SUCCESS; +} + +/** + Sets a region to read only and ensures that flash is locked from being + inadvertently modified. + + @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance + @param Start Start of region to lock. + @param Length Size in bytes of the region. + @param Granularity Lock attribute affects this granularity in bytes. + + @retval EFI_SUCCESS The region was made read only and flash is locked. + +**/ +EFI_STATUS +EFIAPI +LegacyRegionBootLock ( + IN EFI_LEGACY_REGION_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity OPTIONAL + ) +{ + return EFI_SUCCESS; +} + +/** + Sets a region to read-write. + + @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance + @param Start Start of region to lock. + @param Length Size in bytes of the region. + @param Granularity Lock attribute affects this granularity in bytes. + + @retval EFI_SUCCESS The region was successfully made read-write. + +**/ +EFI_STATUS +EFIAPI +LegacyRegionUnlock ( + IN EFI_LEGACY_REGION_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity OPTIONAL + ) +{ + return EFI_SUCCESS; +} + +// +// Module global for the handle the Legacy Region Protocol is installed +// +EFI_HANDLE mLegacyRegionHandle = NULL; + +// +// Module global for the Legacy Region Protocol instance that is installed onto +// mLegacyRegionHandle +// +EFI_LEGACY_REGION_PROTOCOL mLegacyRegion = { + LegacyRegionDecode, + LegacyRegionLock, + LegacyRegionBootLock, + LegacyRegionUnlock +}; + +/** + The user Entry Point for module LegacyRegionDxe. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +LegacyRegionInstall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Make sure the Legacy Region Protocol is not already installed in the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiLegacyRegionProtocolGuid); + + // + // Install the protocol on a new handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mLegacyRegionHandle, + &gEfiLegacyRegionProtocolGuid, &mLegacyRegion, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf b/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf new file mode 100644 index 0000000000..f8e5639dec --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf @@ -0,0 +1,55 @@ +## @file +# Produces Framework Legacy Region Protocol. +# +# This generic implementation of the Legacy Region Protocol does not actually +# perform any lock/unlock operations. This module may be used on platforms +# that do not provide HW locking of the legacy memory regions. It can also +# be used as a template driver for implementing the Legacy Region Protocol on +# a platform that does support HW locking of the legacy memory regions. +# +# 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 +# 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 = LegacyRegionDxe + MODULE_UNI_FILE = LegacyRegionDxe.uni + FILE_GUID = 8C439043-85CA-467a-96F1-CB14F4D0DCDA + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = LegacyRegionInstall + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + LegacyRegion.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + UefiBootServicesTableLib + +[Protocols] + gEfiLegacyRegionProtocolGuid ## PRODUCES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + LegacyRegionDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.uni b/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.uni new file mode 100644 index 0000000000..a0746e961a Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxeExtra.uni new file mode 100644 index 0000000000..b04851c0d2 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c b/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c new file mode 100644 index 0000000000..76aec0ac2c --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c @@ -0,0 +1,1456 @@ +/** @file + Section Extraction Protocol implementation. + + Stream database is implemented as a linked list of section streams, + where each stream contains a linked list of children, which may be leaves or + encapsulations. + + Children that are encapsulations generate new stream entries + when they are created. Streams can also be created by calls to + SEP->OpenSectionStream(). + + The database is only created far enough to return the requested data from + any given stream, or to determine that the requested data is not found. + + If a GUIDed encapsulation is encountered, there are three possiblilites. + + 1) A support protocol is found, in which the stream is simply processed with + the support protocol. + + 2) A support protocol is not found, but the data is available to be read + without processing. In this case, the database is built up through the + recursions to return the data, and a RPN event is set that will enable + the stream in question to be refreshed if and when the required section + extraction protocol is published.This insures the AuthenticationStatus + does not become stale in the cache. + + 3) A support protocol is not found, and the data is not available to be read + without it. This results in EFI_PROTOCOL_ERROR. + +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 +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 + +// +// Local defines and typedefs +// +#define FRAMEWORK_SECTION_CHILD_SIGNATURE SIGNATURE_32('S','X','F','S') +#define CHILD_SECTION_NODE_FROM_LINK(Node) \ + CR (Node, FRAMEWORK_SECTION_CHILD_NODE, Link, FRAMEWORK_SECTION_CHILD_SIGNATURE) + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + UINT32 Type; + UINT32 Size; + // + // StreamBase + OffsetInStream == pointer to section header in stream. The + // stream base is always known when walking the sections within. + // + UINT32 OffsetInStream; + // + // Then EncapsulatedStreamHandle below is always 0 if the section is NOT an + // encapsulating section. Otherwise, it contains the stream handle + // of the encapsulated stream. This handle is ALWAYS produced any time an + // encapsulating child is encountered, irrespective of whether the + // encapsulated stream is processed further. + // + UINTN EncapsulatedStreamHandle; + EFI_GUID *EncapsulationGuid; + // + // If the section REQUIRES an extraction protocol, register for RPN + // when the required GUIDed extraction protocol becomes available. + // + EFI_EVENT Event; +} FRAMEWORK_SECTION_CHILD_NODE; + +#define FRAMEWORK_SECTION_STREAM_SIGNATURE SIGNATURE_32('S','X','S','S') +#define STREAM_NODE_FROM_LINK(Node) \ + CR (Node, FRAMEWORK_SECTION_STREAM_NODE, Link, FRAMEWORK_SECTION_STREAM_SIGNATURE) + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + UINTN StreamHandle; + UINT8 *StreamBuffer; + UINTN StreamLength; + LIST_ENTRY Children; + // + // Authentication status is from GUIDed encapsulations. + // + UINT32 AuthenticationStatus; +} FRAMEWORK_SECTION_STREAM_NODE; + +#define NULL_STREAM_HANDLE 0 + +typedef struct { + FRAMEWORK_SECTION_CHILD_NODE *ChildNode; + FRAMEWORK_SECTION_STREAM_NODE *ParentStream; + VOID *Registration; +} RPN_EVENT_CONTEXT; + +/** + SEP member function. This function creates and returns a new section stream + handle to represent the new section stream. + + @param This Indicates the calling context. + @param SectionStreamLength Size in bytes of the section stream. + @param SectionStream Buffer containing the new section stream. + @param SectionStreamHandle A pointer to a caller allocated UINTN that on output + contains the new section stream handle. + + @retval EFI_SUCCESS Section wase opened successfully. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of + last section. + +**/ +EFI_STATUS +EFIAPI +OpenSectionStream ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + OUT UINTN *SectionStreamHandle + ) +; + +/** + SEP member function. Retrieves requested section from section stream. + + @param This Pointer to SEP instance. + @param SectionStreamHandle The section stream from which to extract the requested + section. + @param SectionType A pointer to the type of section to search for. + @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED, then + SectionDefinitionGuid indicates which of these types + of sections to search for. + @param SectionInstance Indicates which instance of the requested section to + return. + @param Buffer Double indirection to buffer. If *Buffer is non-null on + input, then the buffer is caller allocated. If + *Buffer is NULL, then the buffer is callee allocated. + In either case, the requried buffer size is returned + in *BufferSize. + @param BufferSize On input, indicates the size of *Buffer if *Buffer is + non-null on input. On output, indicates the required + size (allocated size if callee allocated) of *Buffer. + @param AuthenticationStatus Indicates the authentication status of the retrieved + section. + + + @retval EFI_SUCCESS Section was retrieved successfully + @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the section + stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED + bit set, but there was no corresponding GUIDed Section + Extraction Protocol in the handle database. *Buffer is + unmodified. + @retval EFI_NOT_FOUND An error was encountered when parsing the SectionStream. + This indicates the SectionStream is not correctly + formatted. + @retval EFI_NOT_FOUND The requested section does not exist. + @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process the + request. + @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist. + @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is + insufficient to contain the requested section. The + input buffer is filled and contents are section contents + are truncated. + +**/ +EFI_STATUS +EFIAPI +GetSection ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamHandle, + IN EFI_SECTION_TYPE *SectionType, + IN EFI_GUID *SectionDefinitionGuid, + IN UINTN SectionInstance, + IN VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ) +; + +/** + SEP member function. Deletes an existing section stream + + @param This Indicates the calling context. + @param StreamHandleToClose Indicates the stream to close + + @retval EFI_SUCCESS Section stream was closed successfully. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of + last section. + +**/ +EFI_STATUS +EFIAPI +CloseSectionStream ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN StreamHandleToClose + ) +; + +// +// Module globals +// +LIST_ENTRY mStreamRoot = INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot); + +EFI_HANDLE mSectionExtractionHandle = NULL; + +EFI_SECTION_EXTRACTION_PROTOCOL mSectionExtraction = { + OpenSectionStream, + GetSection, + CloseSectionStream +}; + +/** + Entry point of the section extraction code. Initializes an instance of the + section extraction interface and installs it on a new handle. + + @param ImageHandle A handle for the image that is initializing this driver + @param SystemTable A pointer to the EFI system table + + @retval EFI_SUCCESS Driver initialized successfully + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources + +**/ +EFI_STATUS +EFIAPI +SectionExtractionEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install SEP to a new handle + // + Status = gBS->InstallProtocolInterface ( + &mSectionExtractionHandle, + &gEfiSectionExtractionProtocolGuid, + EFI_NATIVE_INTERFACE, + &mSectionExtraction + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + + Check if a stream is valid. + + @param SectionStream The section stream to be checked + @param SectionStreamLength The length of section stream + + @return A boolean value indicating the validness of the section stream. + +**/ +BOOLEAN +IsValidSectionStream ( + IN VOID *SectionStream, + IN UINTN SectionStreamLength + ) +{ + UINTN TotalLength; + UINTN SectionLength; + EFI_COMMON_SECTION_HEADER *SectionHeader; + EFI_COMMON_SECTION_HEADER *NextSectionHeader; + + TotalLength = 0; + SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream; + + while (TotalLength < SectionStreamLength) { + if (IS_SECTION2 (SectionHeader)) { + SectionLength = SECTION2_SIZE (SectionHeader); + } else { + SectionLength = SECTION_SIZE (SectionHeader); + } + TotalLength += SectionLength; + + if (TotalLength == SectionStreamLength) { + return TRUE; + } + + // + // Move to the next byte following the section... + // + SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength); + + // + // Figure out where the next section begins + // + NextSectionHeader = ALIGN_POINTER(SectionHeader, 4); + TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader; + SectionHeader = NextSectionHeader; + } + + ASSERT (FALSE); + return FALSE; +} + +/** + Worker function. Constructor for section streams. + + @param SectionStreamLength Size in bytes of the section stream. + @param SectionStream Buffer containing the new section stream. + @param AllocateBuffer Indicates whether the stream buffer is to be copied + or the input buffer is to be used in place. + @param AuthenticationStatus Indicates the default authentication status for the + new stream. + @param SectionStreamHandle A pointer to a caller allocated section stream handle. + + @retval EFI_SUCCESS Stream was added to stream database. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + +**/ +EFI_STATUS +OpenSectionStreamEx ( + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + IN BOOLEAN AllocateBuffer, + IN UINT32 AuthenticationStatus, + OUT UINTN *SectionStreamHandle + ) +{ + FRAMEWORK_SECTION_STREAM_NODE *NewStream; + EFI_TPL OldTpl; + + // + // Allocate a new stream + // + NewStream = AllocatePool (sizeof (FRAMEWORK_SECTION_STREAM_NODE)); + if (NewStream == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (AllocateBuffer) { + // + // if we're here, we're double buffering, allocate the buffer and copy the + // data in + // + if (SectionStreamLength > 0) { + NewStream->StreamBuffer = AllocatePool (SectionStreamLength); + if (NewStream->StreamBuffer == NULL) { + FreePool (NewStream); + return EFI_OUT_OF_RESOURCES; + } + // + // Copy in stream data + // + CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength); + } else { + // + // It's possible to have a zero length section stream. + // + NewStream->StreamBuffer = NULL; + } + } else { + // + // If were here, the caller has supplied the buffer (it's an internal call) + // so just assign the buffer. This happens when we open section streams + // as a result of expanding an encapsulating section. + // + NewStream->StreamBuffer = SectionStream; + } + + // + // Initialize the rest of the section stream + // + NewStream->Signature = FRAMEWORK_SECTION_STREAM_SIGNATURE; + NewStream->StreamHandle = (UINTN) NewStream; + NewStream->StreamLength = SectionStreamLength; + InitializeListHead (&NewStream->Children); + NewStream->AuthenticationStatus = AuthenticationStatus; + + // + // Add new stream to stream list + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + InsertTailList (&mStreamRoot, &NewStream->Link); + gBS->RestoreTPL (OldTpl); + + *SectionStreamHandle = NewStream->StreamHandle; + + return EFI_SUCCESS; +} + +/** + SEP member function. This function creates and returns a new section stream + handle to represent the new section stream. + + @param This Indicates the calling context. + @param SectionStreamLength Size in bytes of the section stream. + @param SectionStream Buffer containing the new section stream. + @param SectionStreamHandle A pointer to a caller allocated UINTN that on output + contains the new section stream handle. + + @retval EFI_SUCCESS Section wase opened successfully. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of + last section. + +**/ +EFI_STATUS +EFIAPI +OpenSectionStream ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + OUT UINTN *SectionStreamHandle + ) +{ + // + // Check to see section stream looks good... + // + if (!IsValidSectionStream (SectionStream, SectionStreamLength)) { + return EFI_INVALID_PARAMETER; + } + + return OpenSectionStreamEx ( + SectionStreamLength, + SectionStream, + TRUE, + 0, + SectionStreamHandle + ); +} + +/** + Worker function. Determine if the input stream:child matches the input type. + + @param Stream Indicates the section stream associated with the child + @param Child Indicates the child to check + @param SearchType Indicates the type of section to check against for + @param SectionDefinitionGuid Indicates the GUID to check against if the type is + EFI_SECTION_GUID_DEFINED + + @retval TRUE The child matches + @retval FALSE The child doesn't match + +**/ +BOOLEAN +ChildIsType ( + IN FRAMEWORK_SECTION_STREAM_NODE *Stream, + IN FRAMEWORK_SECTION_CHILD_NODE *Child, + IN EFI_SECTION_TYPE SearchType, + IN EFI_GUID *SectionDefinitionGuid + ) +{ + EFI_GUID_DEFINED_SECTION *GuidedSection; + + if (SearchType == EFI_SECTION_ALL) { + return TRUE; + } + if (Child->Type != SearchType) { + return FALSE; + } + if ((SearchType != EFI_SECTION_GUID_DEFINED) || (SectionDefinitionGuid == NULL)) { + return TRUE; + } + GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream); + if (IS_SECTION2 (GuidedSection)) { + return CompareGuid (&(((EFI_GUID_DEFINED_SECTION2 *) GuidedSection)->SectionDefinitionGuid), SectionDefinitionGuid); + } else { + return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid); + } +} + +/** + Create a protocol notification event and return it. + + @param ProtocolGuid Protocol to register notification event on. + @param NotifyTpl Maximum TPL to signal the NotifyFunction. + @param NotifyFunction EFI notification routine. + @param NotifyContext Context passed into Event when it is created. + @param Registration Registration key returned from RegisterProtocolNotify(). + @param SignalFlag Boolean value to decide whether kick the event after register or not. + + @return The EFI_EVENT that has been registered to be signaled when a ProtocolGuid + is added to the system. + +**/ +EFI_EVENT +CreateProtocolNotifyEvent ( + IN EFI_GUID *ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT VOID **Registration, + IN BOOLEAN SignalFlag + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + // + // Create the event + // + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + NotifyTpl, + NotifyFunction, + NotifyContext, + &Event + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for protocol notifactions on this event + // + + Status = gBS->RegisterProtocolNotify ( + ProtocolGuid, + Event, + Registration + ); + ASSERT_EFI_ERROR (Status); + + if (SignalFlag) { + // + // Kick the event so we will perform an initial pass of + // current installed drivers + // + gBS->SignalEvent (Event); + } + + return Event; +} + +/** + Verify the Guided Section GUID by checking if there is the Guided Section GUID configuration table recorded the GUID itself. + + @param GuidedSectionGuid The Guided Section GUID. + @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Protocol + for the Guided Section. + + @return TRUE The GuidedSectionGuid could be identified, and the pointer to + the Guided Section Extraction Protocol will be returned to *GuidedSectionExtraction. + @return FALSE The GuidedSectionGuid could not be identified, or + the Guided Section Extraction Protocol has not been installed yet. + +**/ +BOOLEAN +VerifyGuidedSectionGuid ( + IN EFI_GUID *GuidedSectionGuid, + OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL **GuidedSectionExtraction + ) +{ + EFI_GUID *GuidRecorded; + VOID *Interface; + EFI_STATUS Status; + + // + // Check if there is the Guided Section GUID configuration table recorded the GUID itself. + // + Status = EfiGetSystemConfigurationTable (GuidedSectionGuid, (VOID **) &GuidRecorded); + if (Status == EFI_SUCCESS) { + if (CompareGuid (GuidRecorded, GuidedSectionGuid)) { + // + // Found the recorded GuidedSectionGuid. + // + Status = gBS->LocateProtocol (GuidedSectionGuid, NULL, (VOID **) &Interface); + if (!EFI_ERROR (Status) && Interface != NULL) { + // + // Found the supported Guided Section Extraction Porotocol for the Guided Section. + // + *GuidedSectionExtraction = (EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *) Interface; + return TRUE; + } + return FALSE; + } + } + + return FALSE; +} + +/** + RPN callback function. + 1. Initialize the section stream when the GUIDED_SECTION_EXTRACTION_PROTOCOL is installed. + 2. Removes a stale section stream and re-initializes it with an updated AuthenticationStatus. + + @param Event The event that fired + @param RpnContext A pointer to the context that allows us to identify + the relevent encapsulation. + +**/ +VOID +EFIAPI +NotifyGuidedExtraction ( + IN EFI_EVENT Event, + IN VOID *RpnContext + ) +{ + EFI_STATUS Status; + EFI_GUID_DEFINED_SECTION *GuidedHeader; + EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction; + VOID *NewStreamBuffer; + UINTN NewStreamBufferSize; + UINT32 AuthenticationStatus; + RPN_EVENT_CONTEXT *Context; + + Context = RpnContext; + Status = EFI_SUCCESS; + if (Context->ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) { + Status = CloseSectionStream (&mSectionExtraction, Context->ChildNode->EncapsulatedStreamHandle); + } + if (!EFI_ERROR (Status)) { + // + // The stream is not initialized, open it. + // Or the stream closed successfully, so re-open the stream with correct AuthenticationStatus. + // + + GuidedHeader = (EFI_GUID_DEFINED_SECTION *) + (Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream); + ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED); + + if (!VerifyGuidedSectionGuid (Context->ChildNode->EncapsulationGuid, &GuidedExtraction)) { + return; + } + + Status = GuidedExtraction->ExtractSection ( + GuidedExtraction, + GuidedHeader, + &NewStreamBuffer, + &NewStreamBufferSize, + &AuthenticationStatus + ); + ASSERT_EFI_ERROR (Status); + // + // OR in the parent stream's aggregate status. + // + AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL; + Status = OpenSectionStreamEx ( + NewStreamBufferSize, + NewStreamBuffer, + FALSE, + AuthenticationStatus, + &Context->ChildNode->EncapsulatedStreamHandle + ); + ASSERT_EFI_ERROR (Status); + } + + // + // If above, the stream did not close successfully, it indicates it's + // already been closed by someone, so just destroy the event and be done with + // it. + // + + gBS->CloseEvent (Event); + Context->ChildNode->Event = NULL; + FreePool (Context); +} + +/** + Worker function. Constructor for RPN event if needed to keep AuthenticationStatus + cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears... + + @param ParentStream Indicates the parent of the ecnapsulation section (child) + @param ChildNode Indicates the child node that is the encapsulation section. + +**/ +VOID +CreateGuidedExtractionRpnEvent ( + IN FRAMEWORK_SECTION_STREAM_NODE *ParentStream, + IN FRAMEWORK_SECTION_CHILD_NODE *ChildNode + ) +{ + RPN_EVENT_CONTEXT *Context; + + // + // Allocate new event structure and context + // + Context = AllocatePool (sizeof (RPN_EVENT_CONTEXT)); + ASSERT (Context != NULL); + + Context->ChildNode = ChildNode; + Context->ParentStream = ParentStream; + + Context->ChildNode->Event = CreateProtocolNotifyEvent ( + Context->ChildNode->EncapsulationGuid, + TPL_NOTIFY, + NotifyGuidedExtraction, + Context, + &Context->Registration, + FALSE + ); +} + +/** + Worker function. Constructor for new child nodes. + + @param Stream Indicates the section stream in which to add the child. + @param ChildOffset Indicates the offset in Stream that is the beginning + of the child section. + @param ChildNode Indicates the Callee allocated and initialized child. + + @retval EFI_SUCCESS Child node was found and returned. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream handles when + the child node is created. If the section type is GUID + defined, and the extraction GUID does not exist, and + producing the stream requires the GUID, then a protocol + error is generated and no child is produced. + Values returned by OpenSectionStreamEx. + +**/ +EFI_STATUS +CreateChildNode ( + IN FRAMEWORK_SECTION_STREAM_NODE *Stream, + IN UINT32 ChildOffset, + OUT FRAMEWORK_SECTION_CHILD_NODE **ChildNode + ) +{ + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *SectionHeader; + EFI_COMPRESSION_SECTION *CompressionHeader; + EFI_GUID_DEFINED_SECTION *GuidedHeader; + EFI_DECOMPRESS_PROTOCOL *Decompress; + EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction; + VOID *NewStreamBuffer; + VOID *ScratchBuffer; + UINT32 ScratchSize; + UINTN NewStreamBufferSize; + UINT32 AuthenticationStatus; + VOID *CompressionSource; + UINT32 CompressionSourceSize; + UINT32 UncompressedLength; + UINT8 CompressionType; + UINT16 GuidedSectionAttributes; + + FRAMEWORK_SECTION_CHILD_NODE *Node; + + SectionHeader = (EFI_COMMON_SECTION_HEADER *) (Stream->StreamBuffer + ChildOffset); + + // + // Allocate a new node + // + *ChildNode = AllocateZeroPool (sizeof (FRAMEWORK_SECTION_CHILD_NODE)); + Node = *ChildNode; + if (Node == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Now initialize it + // + Node->Signature = FRAMEWORK_SECTION_CHILD_SIGNATURE; + Node->Type = SectionHeader->Type; + if (IS_SECTION2 (SectionHeader)) { + Node->Size = SECTION2_SIZE (SectionHeader); + } else { + Node->Size = SECTION_SIZE (SectionHeader); + } + Node->OffsetInStream = ChildOffset; + Node->EncapsulatedStreamHandle = NULL_STREAM_HANDLE; + Node->EncapsulationGuid = NULL; + + // + // If it's an encapsulating section, then create the new section stream also + // + switch (Node->Type) { + case EFI_SECTION_COMPRESSION: + // + // Get the CompressionSectionHeader + // + if (Node->Size < sizeof (EFI_COMPRESSION_SECTION)) { + FreePool (Node); + return EFI_NOT_FOUND; + } + + CompressionHeader = (EFI_COMPRESSION_SECTION *) SectionHeader; + + if (IS_SECTION2 (CompressionHeader)) { + CompressionSource = (VOID *) ((UINT8 *) CompressionHeader + sizeof (EFI_COMPRESSION_SECTION2)); + CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionHeader) - sizeof (EFI_COMPRESSION_SECTION2)); + UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionHeader)->UncompressedLength; + CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionHeader)->CompressionType; + } else { + CompressionSource = (VOID *) ((UINT8 *) CompressionHeader + sizeof (EFI_COMPRESSION_SECTION)); + CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionHeader) - sizeof (EFI_COMPRESSION_SECTION)); + UncompressedLength = CompressionHeader->UncompressedLength; + CompressionType = CompressionHeader->CompressionType; + } + + // + // Allocate space for the new stream + // + if (UncompressedLength > 0) { + NewStreamBufferSize = UncompressedLength; + NewStreamBuffer = AllocatePool (NewStreamBufferSize); + if (NewStreamBuffer == NULL) { + FreePool (Node); + return EFI_OUT_OF_RESOURCES; + } + + if (CompressionType == EFI_NOT_COMPRESSED) { + // + // stream is not actually compressed, just encapsulated. So just copy it. + // + CopyMem (NewStreamBuffer, CompressionSource, NewStreamBufferSize); + } else if (CompressionType == EFI_STANDARD_COMPRESSION) { + // + // Only support the EFI_SATNDARD_COMPRESSION algorithm. + // + + // + // Decompress the stream + // + Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **)&Decompress); + + ASSERT_EFI_ERROR (Status); + + Status = Decompress->GetInfo ( + Decompress, + CompressionSource, + CompressionSourceSize, + (UINT32 *)&NewStreamBufferSize, + &ScratchSize + ); + if (EFI_ERROR (Status) || (NewStreamBufferSize != UncompressedLength)) { + FreePool (Node); + FreePool (NewStreamBuffer); + if (!EFI_ERROR (Status)) { + Status = EFI_BAD_BUFFER_SIZE; + } + return Status; + } + + ScratchBuffer = AllocatePool (ScratchSize); + if (ScratchBuffer == NULL) { + FreePool (Node); + FreePool (NewStreamBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Status = Decompress->Decompress ( + Decompress, + CompressionSource, + CompressionSourceSize, + NewStreamBuffer, + (UINT32)NewStreamBufferSize, + ScratchBuffer, + ScratchSize + ); + FreePool (ScratchBuffer); + if (EFI_ERROR (Status)) { + FreePool (Node); + FreePool (NewStreamBuffer); + return Status; + } + } + } else { + NewStreamBuffer = NULL; + NewStreamBufferSize = 0; + } + + Status = OpenSectionStreamEx ( + NewStreamBufferSize, + NewStreamBuffer, + FALSE, + Stream->AuthenticationStatus, + &Node->EncapsulatedStreamHandle + ); + if (EFI_ERROR (Status)) { + FreePool (Node); + FreePool (NewStreamBuffer); + return Status; + } + break; + + case EFI_SECTION_GUID_DEFINED: + GuidedHeader = (EFI_GUID_DEFINED_SECTION *) SectionHeader; + if (IS_SECTION2 (GuidedHeader)) { + Node->EncapsulationGuid = &(((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->SectionDefinitionGuid); + GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->Attributes; + } else { + Node->EncapsulationGuid = &GuidedHeader->SectionDefinitionGuid; + GuidedSectionAttributes = GuidedHeader->Attributes; + } + if (VerifyGuidedSectionGuid (Node->EncapsulationGuid, &GuidedExtraction)) { + // + // NewStreamBuffer is always allocated by ExtractSection... No caller + // allocation here. + // + Status = GuidedExtraction->ExtractSection ( + GuidedExtraction, + GuidedHeader, + &NewStreamBuffer, + &NewStreamBufferSize, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + FreePool (*ChildNode); + return EFI_PROTOCOL_ERROR; + } + + // + // Make sure we initialize the new stream with the correct + // authentication status for both aggregate and local status fields. + // + if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) { + // + // OR in the parent stream's aggregate status. + // + AuthenticationStatus |= Stream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL; + } else { + // + // since there's no authentication data contributed by the section, + // just inherit the full value from our immediate parent. + // + AuthenticationStatus = Stream->AuthenticationStatus; + } + + Status = OpenSectionStreamEx ( + NewStreamBufferSize, + NewStreamBuffer, + FALSE, + AuthenticationStatus, + &Node->EncapsulatedStreamHandle + ); + if (EFI_ERROR (Status)) { + FreePool (*ChildNode); + FreePool (NewStreamBuffer); + return Status; + } + } else { + // + // There's no GUIDed section extraction protocol available. + // + if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == EFI_GUIDED_SECTION_PROCESSING_REQUIRED) { + // + // If the section REQUIRES an extraction protocol, register for RPN + // when the required GUIDed extraction protocol becomes available. + // + AuthenticationStatus = 0; + CreateGuidedExtractionRpnEvent (Stream, Node); + } else { + // + // Figure out the proper authentication status + // + AuthenticationStatus = Stream->AuthenticationStatus; + if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) { + // + // The local status of the new stream is contained in + // AuthenticaionStatus. This value needs to be ORed into the + // Aggregate bits also... + // + + // + // Clear out and initialize the local status + // + AuthenticationStatus &= ~EFI_LOCAL_AUTH_STATUS_ALL; + AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED; + // + // OR local status into aggregate status + // + AuthenticationStatus |= AuthenticationStatus >> 16; + } + + if (IS_SECTION2 (GuidedHeader)) { + Status = OpenSectionStreamEx ( + SECTION2_SIZE (GuidedHeader) - ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->DataOffset, + (UINT8 *) GuidedHeader + ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->DataOffset, + TRUE, + AuthenticationStatus, + &Node->EncapsulatedStreamHandle + ); + } else { + Status = OpenSectionStreamEx ( + SECTION_SIZE (GuidedHeader) - ((EFI_GUID_DEFINED_SECTION *) GuidedHeader)->DataOffset, + (UINT8 *) GuidedHeader + ((EFI_GUID_DEFINED_SECTION *) GuidedHeader)->DataOffset, + TRUE, + AuthenticationStatus, + &Node->EncapsulatedStreamHandle + ); + } + if (EFI_ERROR (Status)) { + FreePool (Node); + return Status; + } + } + } + + if ((AuthenticationStatus & EFI_LOCAL_AUTH_STATUS_ALL) == + (EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED)) { + // + // Need to register for RPN for when the required GUIDed extraction + // protocol becomes available. This will enable us to refresh the + // AuthenticationStatus cached in the Stream if it's ever requested + // again. + // + CreateGuidedExtractionRpnEvent (Stream, Node); + } + + break; + + default: + + // + // Nothing to do if it's a leaf + // + break; + } + + // + // Last, add the new child node to the stream + // + InsertTailList (&Stream->Children, &Node->Link); + + return EFI_SUCCESS; +} + +/** + Worker function Recursively searches / builds section stream database + looking for requested section. + + + @param SourceStream Indicates the section stream in which to do the search. + @param SearchType Indicates the type of section to search for. + @param SectionInstance Indicates which instance of section to find. This is + an in/out parameter to deal with recursions. + @param SectionDefinitionGuid Guid of section definition + @param FoundChild Output indicating the child node that is found. + @param FoundStream Output indicating which section stream the child was + found in. If this stream was generated as a result of + an encapsulation section, the streamhandle is visible + within the SEP driver only. + @param AuthenticationStatus Indicates the authentication status of the found section. + + @retval EFI_SUCCESS Child node was found and returned. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_NOT_FOUND Requested child node does not exist. + @retval EFI_PROTOCOL_ERROR A required GUIDED section extraction protocol does not + exist + +**/ +EFI_STATUS +FindChildNode ( + IN FRAMEWORK_SECTION_STREAM_NODE *SourceStream, + IN EFI_SECTION_TYPE SearchType, + IN OUT UINTN *SectionInstance, + IN EFI_GUID *SectionDefinitionGuid, + OUT FRAMEWORK_SECTION_CHILD_NODE **FoundChild, + OUT FRAMEWORK_SECTION_STREAM_NODE **FoundStream, + OUT UINT32 *AuthenticationStatus + ) +{ + FRAMEWORK_SECTION_CHILD_NODE *CurrentChildNode; + FRAMEWORK_SECTION_CHILD_NODE *RecursedChildNode; + FRAMEWORK_SECTION_STREAM_NODE *RecursedFoundStream; + UINT32 NextChildOffset; + EFI_STATUS ErrorStatus; + EFI_STATUS Status; + + CurrentChildNode = NULL; + ErrorStatus = EFI_NOT_FOUND; + + if (SourceStream->StreamLength == 0) { + return EFI_NOT_FOUND; + } + + if (IsListEmpty (&SourceStream->Children) && + SourceStream->StreamLength >= sizeof (EFI_COMMON_SECTION_HEADER)) { + // + // This occurs when a section stream exists, but no child sections + // have been parsed out yet. Therefore, extract the first child and add it + // to the list of children so we can get started. + // Section stream may contain an array of zero or more bytes. + // So, its size should be >= the size of commen section header. + // + Status = CreateChildNode (SourceStream, 0, &CurrentChildNode); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // At least one child has been parsed out of the section stream. So, walk + // through the sections that have already been parsed out looking for the + // requested section, if necessary, continue parsing section stream and + // adding children until either the requested section is found, or we run + // out of data + // + CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children)); + + for (;;) { + ASSERT (CurrentChildNode != NULL); + if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) { + // + // The type matches, so check the instance count to see if it's the one we want + // + (*SectionInstance)--; + if (*SectionInstance == 0) { + // + // Got it! + // + *FoundChild = CurrentChildNode; + *FoundStream = SourceStream; + *AuthenticationStatus = SourceStream->AuthenticationStatus; + return EFI_SUCCESS; + } + } + + if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) { + // + // If the current node is an encapsulating node, recurse into it... + // + Status = FindChildNode ( + (FRAMEWORK_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle, + SearchType, + SectionInstance, + SectionDefinitionGuid, + &RecursedChildNode, + &RecursedFoundStream, + AuthenticationStatus + ); + // + // If the status is not EFI_SUCCESS, just save the error code and continue + // to find the request child node in the rest stream. + // + if (*SectionInstance == 0) { + ASSERT_EFI_ERROR (Status); + *FoundChild = RecursedChildNode; + *FoundStream = RecursedFoundStream; + return EFI_SUCCESS; + } else { + ErrorStatus = Status; + } + } else if ((CurrentChildNode->Type == EFI_SECTION_GUID_DEFINED) && (SearchType != EFI_SECTION_GUID_DEFINED)) { + // + // When Node Type is GUIDED section, but Node has no encapsulated data, Node data should not be parsed + // because a required GUIDED section extraction protocol does not exist. + // If SearchType is not GUIDED section, EFI_PROTOCOL_ERROR should return. + // + ErrorStatus = EFI_PROTOCOL_ERROR; + } + + if (!IsNodeAtEnd (&SourceStream->Children, &CurrentChildNode->Link)) { + // + // We haven't found the child node we're interested in yet, but there's + // still more nodes that have already been parsed so get the next one + // and continue searching.. + // + CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream->Children, &CurrentChildNode->Link)); + } else { + // + // We've exhausted children that have already been parsed, so see if + // there's any more data and continue parsing out more children if there + // is. + // + NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size; + // + // Round up to 4 byte boundary + // + NextChildOffset += 3; + NextChildOffset &= ~(UINTN)3; + if (NextChildOffset <= SourceStream->StreamLength - sizeof (EFI_COMMON_SECTION_HEADER)) { + // + // There's an unparsed child remaining in the stream, so create a new child node + // + Status = CreateChildNode (SourceStream, NextChildOffset, &CurrentChildNode); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + ASSERT (EFI_ERROR (ErrorStatus)); + return ErrorStatus; + } + } + } +} + +/** + Worker function. Search stream database for requested stream handle. + + @param SearchHandle Indicates which stream to look for. + @param FoundStream Output pointer to the found stream. + + @retval EFI_SUCCESS StreamHandle was found and *FoundStream contains + the stream node. + @retval EFI_NOT_FOUND SearchHandle was not found in the stream database. + +**/ +EFI_STATUS +FindStreamNode ( + IN UINTN SearchHandle, + OUT FRAMEWORK_SECTION_STREAM_NODE **FoundStream + ) +{ + FRAMEWORK_SECTION_STREAM_NODE *StreamNode; + + if (!IsListEmpty (&mStreamRoot)) { + StreamNode = STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot)); + for (;;) { + if (StreamNode->StreamHandle == SearchHandle) { + *FoundStream = StreamNode; + return EFI_SUCCESS; + } else if (IsNodeAtEnd (&mStreamRoot, &StreamNode->Link)) { + break; + } else { + StreamNode = STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot, &StreamNode->Link)); + } + } + } + + return EFI_NOT_FOUND; +} + +/** + SEP member function. Retrieves requested section from section stream. + + @param This Pointer to SEP instance. + @param SectionStreamHandle The section stream from which to extract the requested + section. + @param SectionType A pointer to the type of section to search for. + @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED, then + SectionDefinitionGuid indicates which of these types + of sections to search for. + @param SectionInstance Indicates which instance of the requested section to + return. + @param Buffer Double indirection to buffer. If *Buffer is non-null on + input, then the buffer is caller allocated. If + *Buffer is NULL, then the buffer is callee allocated. + In either case, the requried buffer size is returned + in *BufferSize. + @param BufferSize On input, indicates the size of *Buffer if *Buffer is + non-null on input. On output, indicates the required + size (allocated size if callee allocated) of *Buffer. + @param AuthenticationStatus Indicates the authentication status of the retrieved + section. + + + @retval EFI_SUCCESS Section was retrieved successfully + @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the section + stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED + bit set, but there was no corresponding GUIDed Section + Extraction Protocol in the handle database. *Buffer is + unmodified. + @retval EFI_NOT_FOUND An error was encountered when parsing the SectionStream. + This indicates the SectionStream is not correctly + formatted. + @retval EFI_NOT_FOUND The requested section does not exist. + @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process the + request. + @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist. + @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is + insufficient to contain the requested section. The + input buffer is filled and contents are section contents + are truncated. + +**/ +EFI_STATUS +EFIAPI +GetSection ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamHandle, + IN EFI_SECTION_TYPE *SectionType, + IN EFI_GUID *SectionDefinitionGuid, + IN UINTN SectionInstance, + IN VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ) +{ + FRAMEWORK_SECTION_STREAM_NODE *StreamNode; + EFI_TPL OldTpl; + EFI_STATUS Status; + FRAMEWORK_SECTION_CHILD_NODE *ChildNode; + FRAMEWORK_SECTION_STREAM_NODE *ChildStreamNode; + UINTN CopySize; + UINT32 ExtractedAuthenticationStatus; + UINTN Instance; + UINT8 *CopyBuffer; + UINTN SectionSize; + EFI_COMMON_SECTION_HEADER *Section; + + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + Instance = SectionInstance + 1; + ChildStreamNode = NULL; + + // + // Locate target stream + // + Status = FindStreamNode (SectionStreamHandle, &StreamNode); + if (EFI_ERROR (Status)) { + Status = EFI_INVALID_PARAMETER; + goto GetSection_Done; + } + + // + // Found the stream, now locate and return the appropriate section + // + if (SectionType == NULL) { + // + // SectionType == NULL means return the WHOLE section stream... + // + CopySize = StreamNode->StreamLength; + CopyBuffer = StreamNode->StreamBuffer; + *AuthenticationStatus = StreamNode->AuthenticationStatus; + } else { + // + // There's a requested section type, so go find it and return it... + // + Status = FindChildNode ( + StreamNode, + *SectionType, + &Instance, + SectionDefinitionGuid, + &ChildNode, + &ChildStreamNode, + &ExtractedAuthenticationStatus + ); + if (EFI_ERROR (Status)) { + goto GetSection_Done; + } + ASSERT (ChildNode != NULL); + ASSERT (ChildStreamNode != NULL); + Section = (EFI_COMMON_SECTION_HEADER *) (ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream); + + if (IS_SECTION2 (Section)) { + CopySize = SECTION2_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER2); + CopyBuffer = (UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2); + } else { + CopySize = SECTION_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER); + CopyBuffer = (UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER); + } + *AuthenticationStatus = ExtractedAuthenticationStatus; + } + + SectionSize = CopySize; + if (*Buffer != NULL) { + // + // Caller allocated buffer. Fill to size and return required size... + // + if (*BufferSize < CopySize) { + Status = EFI_WARN_BUFFER_TOO_SMALL; + CopySize = *BufferSize; + } + } else { + // + // Callee allocated buffer. Allocate buffer and return size. + // + *Buffer = AllocatePool (CopySize); + if (*Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto GetSection_Done; + } + } + CopyMem (*Buffer, CopyBuffer, CopySize); + *BufferSize = SectionSize; + +GetSection_Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Worker function. Destructor for child nodes. + + @param ChildNode Indicates the node to destroy + +**/ +VOID +FreeChildNode ( + IN FRAMEWORK_SECTION_CHILD_NODE *ChildNode + ) +{ + ASSERT (ChildNode->Signature == FRAMEWORK_SECTION_CHILD_SIGNATURE); + // + // Remove the child from it's list + // + RemoveEntryList (&ChildNode->Link); + + if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) { + // + // If it's an encapsulating section, we close the resulting section stream. + // CloseSectionStream will free all memory associated with the stream. + // + CloseSectionStream (&mSectionExtraction, ChildNode->EncapsulatedStreamHandle); + } + + if (ChildNode->Event != NULL) { + gBS->CloseEvent (ChildNode->Event); + } + + // + // Last, free the child node itself + // + FreePool (ChildNode); +} + +/** + SEP member function. Deletes an existing section stream + + @param This Indicates the calling context. + @param StreamHandleToClose Indicates the stream to close + + @retval EFI_SUCCESS Section stream was closed successfully. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of + last section. + +**/ +EFI_STATUS +EFIAPI +CloseSectionStream ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN StreamHandleToClose + ) +{ + FRAMEWORK_SECTION_STREAM_NODE *StreamNode; + EFI_TPL OldTpl; + EFI_STATUS Status; + LIST_ENTRY *Link; + FRAMEWORK_SECTION_CHILD_NODE *ChildNode; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Locate target stream + // + Status = FindStreamNode (StreamHandleToClose, &StreamNode); + if (!EFI_ERROR (Status)) { + // + // Found the stream, so close it + // + RemoveEntryList (&StreamNode->Link); + while (!IsListEmpty (&StreamNode->Children)) { + Link = GetFirstNode (&StreamNode->Children); + ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link); + FreeChildNode (ChildNode); + } + FreePool (StreamNode->StreamBuffer); + FreePool (StreamNode); + Status = EFI_SUCCESS; + } else { + Status = EFI_INVALID_PARAMETER; + } + + gBS->RestoreTPL (OldTpl); + return Status; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf b/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf new file mode 100644 index 0000000000..ab0bd63076 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf @@ -0,0 +1,57 @@ +## @file +# Section Extraction Dxe Driver produces framework section extract protocol. +# +# The section is implemented as a linked list of section streams, +# where each stream contains a linked list of children, which may be leaves or +# encapsulations. Encapsulation section will further generate new section stream entries. +# +# 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 +# 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 = SectionExtractionDxe + MODULE_UNI_FILE = SectionExtractionDxe.uni + FILE_GUID = 801ADCA0-815E-46a4-84F7-657F53621A57 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SectionExtractionEntryPoint + +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + SectionExtraction.c + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + DebugLib + BaseLib + BaseMemoryLib + UefiDriverEntryPoint + UefiLib + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[Protocols] + gEfiSectionExtractionProtocolGuid ## PRODUCES + gEfiDecompressProtocolGuid ## SOMETIMES_CONSUMES + +[Depex] + gEfiDecompressProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + SectionExtractionDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.uni b/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.uni new file mode 100644 index 0000000000..98a01d2f90 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxeExtra.uni new file mode 100644 index 0000000000..84db1b982f Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c new file mode 100644 index 0000000000..5b42395dbd --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c @@ -0,0 +1,376 @@ +/** @file + Data Hub status code worker. + + 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 "DatahubStatusCodeHandlerDxe.h" + +// +// Initialize FIFO to cache records. +// +LIST_ENTRY mRecordsFifo = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsFifo); +LIST_ENTRY mRecordsBuffer = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsBuffer); +UINT32 mLogDataHubStatus = 0; +EFI_EVENT mLogDataHubEvent; +// +// Cache data hub protocol. +// +EFI_DATA_HUB_PROTOCOL *mDataHubProtocol = NULL; + + +/** + Retrieve one record of from free record buffer. This record is removed from + free record buffer. + + This function retrieves one record from free record buffer. + If the pool has been exhausted, then new memory would be allocated for it. + + @return Pointer to the free record. + NULL means failure to allocate new memeory for free record buffer. + +**/ +DATA_HUB_STATUS_CODE_DATA_RECORD * +AcquireRecordBuffer ( + VOID + ) +{ + DATAHUB_STATUSCODE_RECORD *Record; + EFI_TPL CurrentTpl; + LIST_ENTRY *Node; + UINT32 Index; + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + if (!IsListEmpty (&mRecordsBuffer)) { + // + // Strip one entry from free record buffer. + // + Node = GetFirstNode (&mRecordsBuffer); + RemoveEntryList (Node); + + Record = BASE_CR (Node, DATAHUB_STATUSCODE_RECORD, Node); + } else { + if (CurrentTpl > TPL_NOTIFY) { + // + // Memory management should work at <=TPL_NOTIFY + // + gBS->RestoreTPL (CurrentTpl); + return NULL; + } + + // + // If free record buffer is exhausted, then allocate 16 new records for it. + // + gBS->RestoreTPL (CurrentTpl); + Record = (DATAHUB_STATUSCODE_RECORD *) AllocateZeroPool (sizeof (DATAHUB_STATUSCODE_RECORD) * 16); + if (Record == NULL) { + return NULL; + } + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + // + // Here we only insert 15 new records to the free record buffer, for the first record + // will be returned immediately. + // + for (Index = 1; Index < 16; Index++) { + InsertTailList (&mRecordsBuffer, &Record[Index].Node); + } + } + + Record->Signature = DATAHUB_STATUS_CODE_SIGNATURE; + InsertTailList (&mRecordsFifo, &Record->Node); + + gBS->RestoreTPL (CurrentTpl); + + return (DATA_HUB_STATUS_CODE_DATA_RECORD *) (Record->Data); +} + + +/** + Retrieve one record from Records FIFO. The record would be removed from FIFO. + + @return Point to record, which is ready to be logged. + NULL means the FIFO of record is empty. + +**/ +DATA_HUB_STATUS_CODE_DATA_RECORD * +RetrieveRecord ( + VOID + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData; + DATAHUB_STATUSCODE_RECORD *Record; + LIST_ENTRY *Node; + EFI_TPL CurrentTpl; + + RecordData = NULL; + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + if (!IsListEmpty (&mRecordsFifo)) { + Node = GetFirstNode (&mRecordsFifo); + Record = CR (Node, DATAHUB_STATUSCODE_RECORD, Node, DATAHUB_STATUS_CODE_SIGNATURE); + ASSERT (Record != NULL); + + RemoveEntryList (&Record->Node); + RecordData = (DATA_HUB_STATUS_CODE_DATA_RECORD *) Record->Data; + } + + gBS->RestoreTPL (CurrentTpl); + + return RecordData; +} + +/** + Release given record and return it to free record buffer. + + @param RecordData Pointer to the record to release. + +**/ +VOID +ReleaseRecord ( + DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData + ) +{ + DATAHUB_STATUSCODE_RECORD *Record; + EFI_TPL CurrentTpl; + + Record = CR (RecordData, DATAHUB_STATUSCODE_RECORD, Data[0], DATAHUB_STATUS_CODE_SIGNATURE); + ASSERT (Record != NULL); + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + InsertTailList (&mRecordsBuffer, &Record->Node); + Record->Signature = 0; + + gBS->RestoreTPL (CurrentTpl); +} + +/** + Report status code into DataHub. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_DEVICE_ERROR Function is reentered. + @retval EFI_DEVICE_ERROR Function is called at runtime. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. + +**/ +EFI_STATUS +EFIAPI +DataHubStatusCodeReportWorker ( + 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 + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *Record; + UINT32 ErrorLevel; + BASE_LIST Marker; + CHAR8 *Format; + UINTN CharCount; + + // + // Use atom operation to avoid the reentant of report. + // If current status is not zero, then the function is reentrancy. + // + if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 0) == 1) { + return EFI_DEVICE_ERROR; + } + + Record = AcquireRecordBuffer (); + if (Record == NULL) { + // + // There are no empty record buffer in private buffers + // + return EFI_OUT_OF_RESOURCES; + } + + // + // Construct Data Hub Extended Data + // + Record->CodeType = CodeType; + Record->Value = Value; + Record->Instance = Instance; + + if (CallerId != NULL) { + CopyMem (&Record->CallerId, CallerId, sizeof (EFI_GUID)); + } + + if (Data != NULL) { + if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { + CharCount = UnicodeBSPrintAsciiFormat ( + (CHAR16 *) (Record + 1), + EFI_STATUS_CODE_DATA_MAX_SIZE, + Format, + Marker + ); + // + // Change record data type to DebugType. + // + CopyGuid (&Record->Data.Type, &gEfiStatusCodeDataTypeDebugGuid); + Record->Data.HeaderSize = Data->HeaderSize; + Record->Data.Size = (UINT16) ((CharCount + 1) * sizeof (CHAR16)); + } else { + // + // Copy status code data header + // + CopyMem (&Record->Data, Data, sizeof (EFI_STATUS_CODE_DATA)); + + if (Data->Size > EFI_STATUS_CODE_DATA_MAX_SIZE) { + Record->Data.Size = EFI_STATUS_CODE_DATA_MAX_SIZE; + } + CopyMem ((VOID *) (Record + 1), Data + 1, Record->Data.Size); + } + } + + gBS->SignalEvent (mLogDataHubEvent); + + return EFI_SUCCESS; +} + + +/** + The Event handler which will be notified to log data in Data Hub. + + @param Event Instance of the EFI_EVENT to signal whenever data is + available to be logged in the system. + @param Context Context of the event. + +**/ +VOID +EFIAPI +LogDataHubEventCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *Record; + UINT32 Size; + UINT64 DataRecordClass; + + // + // Use atom operation to avoid the reentant of report. + // If current status is not zero, then the function is reentrancy. + // + if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 1) == 1) { + return; + } + + // + // Log DataRecord in Data Hub. + // Journal records fifo to find all record entry. + // + while (TRUE) { + // + // Retrieve record from record FIFO until no more record can be retrieved. + // + Record = RetrieveRecord (); + if (Record == NULL) { + break; + } + // + // Add in the size of the header we added. + // + Size = sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD) + (UINT32) Record->Data.Size; + + if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_ERROR; + } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG; + } else { + // + // Should never get here. + // + DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG | + EFI_DATA_RECORD_CLASS_ERROR | + EFI_DATA_RECORD_CLASS_DATA | + EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } + + // + // Log DataRecord in Data Hub + // + mDataHubProtocol->LogData ( + mDataHubProtocol, + &gEfiDataHubStatusCodeRecordGuid, + &gEfiStatusCodeRuntimeProtocolGuid, + DataRecordClass, + Record, + Size + ); + + ReleaseRecord (Record); + } + + // + // Restore the nest status of report + // + InterlockedCompareExchange32 (&mLogDataHubStatus, 1, 0); +} + + +/** + Locate Data Hub Protocol and create event for logging data + as initialization for data hub status code worker. + + @retval EFI_SUCCESS Initialization is successful. + +**/ +EFI_STATUS +DataHubStatusCodeInitializeWorker ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID **) &mDataHubProtocol + ); + if (EFI_ERROR (Status)) { + mDataHubProtocol = NULL; + return Status; + } + + // + // Create a Notify Event to log data in Data Hub + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + LogDataHubEventCallBack, + NULL, + &mLogDataHubEvent + ); + + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c new file mode 100644 index 0000000000..ee7bdd36af --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c @@ -0,0 +1,88 @@ +/** @file + Status Code Handler Driver which produces datahub handler and hook it + onto the DXE status code router. + + 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 "DatahubStatusCodeHandlerDxe.h" + +EFI_EVENT mExitBootServicesEvent = NULL; +EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL; + +/** + Unregister status code callback functions only available at boot time from + report status code router when exiting boot services. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, which is + always zero in current implementation. + +**/ +VOID +EFIAPI +UnregisterBootTimeHandlers ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mRscHandlerProtocol->Unregister (DataHubStatusCodeReportWorker); +} + +/** + Entry point of DXE Status Code Driver. + + This function is the entry point of this DXE Status Code Driver. + It initializes registers status code handlers, and registers event for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. + + @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. + +**/ +EFI_STATUS +EFIAPI +DatahubStatusCodeHandlerDxeEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { + Status = gBS->LocateProtocol ( + &gEfiRscHandlerProtocolGuid, + NULL, + (VOID **) &mRscHandlerProtocol + ); + ASSERT_EFI_ERROR (Status); + + // + // Dispatch initialization request to supported devices + // + DataHubStatusCodeInitializeWorker (); + + mRscHandlerProtocol->Register (DataHubStatusCodeReportWorker, TPL_HIGH_LEVEL); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + UnregisterBootTimeHandlers, + NULL, + &gEfiEventExitBootServicesGuid, + &mExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + } + + return EFI_SUCCESS; +} diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h new file mode 100644 index 0000000000..8ee0b55fa8 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h @@ -0,0 +1,91 @@ +/** @file + Internal include file for Datahub Status Code Handler Driver. + + 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 __DATAHUB_STATUS_CODE_HANDLER_DXE_H__ +#define __DATAHUB_STATUS_CODE_HANDLER_DXE_H__ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Data hub worker definition +// +#define DATAHUB_STATUS_CODE_SIGNATURE SIGNATURE_32 ('B', 'D', 'H', 'S') + +typedef struct { + UINTN Signature; + LIST_ENTRY Node; + UINT8 Data[sizeof(DATA_HUB_STATUS_CODE_DATA_RECORD) + EFI_STATUS_CODE_DATA_MAX_SIZE]; +} DATAHUB_STATUSCODE_RECORD; + +/** + Report status code into DataHub. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_DEVICE_ERROR Function is reentered. + @retval EFI_DEVICE_ERROR Function is called at runtime. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. + +**/ +EFI_STATUS +EFIAPI +DataHubStatusCodeReportWorker ( + 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 + ); + +/** + Locate Data Hub Protocol and create event for logging data + as initialization for data hub status code worker. + + @retval EFI_SUCCESS Initialization is successful. + +**/ +EFI_STATUS +DataHubStatusCodeInitializeWorker ( + VOID + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf new file mode 100644 index 0000000000..1a576772a3 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf @@ -0,0 +1,72 @@ +## @file +# Status Code Handler Driver which produces datahub handler. +# +# 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 +# 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 = DatahubStatusCodeHandlerDxe + MODULE_UNI_FILE = DatahubStatusCodeHandlerDxe.uni + FILE_GUID = 863D214F-0920-437B-8CAD-88EA83A24E97 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DatahubStatusCodeHandlerDxeEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DatahubStatusCodeHandlerDxe.h + DatahubStatusCodeHandlerDxe.c + DataHubStatusCodeWorker.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + PcdLib + PrintLib + ReportStatusCodeLib + DebugLib + SynchronizationLib + BaseMemoryLib + +[Guids] + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + gEfiDataHubStatusCodeRecordGuid ## PRODUCES ## UNDEFINED # DataRecord Guid + gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_PRODUCES ## UNDEFINED # Record data type + +[Protocols] + gEfiRscHandlerProtocolGuid ## CONSUMES + gEfiDataHubProtocolGuid ## CONSUMES + gEfiStatusCodeRuntimeProtocolGuid ## UNDEFINED + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub ## CONSUMES + +[Depex] + gEfiRscHandlerProtocolGuid AND + gEfiDataHubProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + DatahubStatusCodeHandlerDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.uni b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.uni new file mode 100644 index 0000000000..57f0640fa4 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxeExtra.uni new file mode 100644 index 0000000000..0e648005ec Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxeExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/MemoryStausCodeWorker.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/MemoryStausCodeWorker.c new file mode 100644 index 0000000000..f0b36f23a2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/MemoryStausCodeWorker.c @@ -0,0 +1,118 @@ +/** @file + PEI memory status code worker. + + Copyright (c) 2006 - 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 "StatusCodePei.h" + +/** + Create the first memory status code GUID'ed HOB as initialization for memory status code worker. + + @retval EFI_SUCCESS The GUID'ed HOB is created successfully. + +**/ +EFI_STATUS +MemoryStatusCodeInitializeWorker ( + VOID + ) +{ + // + // Create memory status code GUID'ed HOB. + // + MEMORY_STATUSCODE_PACKET_HEADER *PacketHeader; + + // + // Build GUID'ed HOB with PCD defined size. + // + PacketHeader = BuildGuidHob ( + &gMemoryStatusCodeRecordGuid, + PcdGet16 (PcdStatusCodeMemorySize) * 1024 + sizeof (MEMORY_STATUSCODE_PACKET_HEADER) + ); + ASSERT (PacketHeader != NULL); + + PacketHeader->MaxRecordsNumber = (PcdGet16 (PcdStatusCodeMemorySize) * 1024) / sizeof (MEMORY_STATUSCODE_RECORD); + PacketHeader->PacketIndex = 0; + PacketHeader->RecordIndex = 0; + + return EFI_SUCCESS; +} + + +/** + Report status code into GUID'ed HOB. + + This function reports status code into GUID'ed HOB. If not all packets are full, then + write status code into available entry. Otherwise, create a new packet for it. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or + software entity. This includes information about the class and + subclass that is used to classify the entity as well as an operation. + For progress codes, the operation is the current activity. + For error codes, it is the exception.For debug codes,it is not defined at this time. + @param Instance The enumeration of a hardware or software entity within + the system. A system may contain multiple entities that match a class/subclass + pairing. The instance differentiates between them. An instance of 0 indicates + that instance information is unavailable, not meaningful, or not relevant. + Valid instance numbers start with 1. + + @retval EFI_SUCCESS The function always return EFI_SUCCESS. + +**/ +EFI_STATUS +MemoryStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance + ) +{ + + EFI_PEI_HOB_POINTERS Hob; + MEMORY_STATUSCODE_PACKET_HEADER *PacketHeader; + MEMORY_STATUSCODE_RECORD *Record; + + // + // Find GUID'ed HOBs to locate current record buffer. + // + Hob.Raw = GetFirstGuidHob (&gMemoryStatusCodeRecordGuid); + ASSERT (Hob.Raw != NULL); + + PacketHeader = (MEMORY_STATUSCODE_PACKET_HEADER *) GET_GUID_HOB_DATA (Hob.Guid); + Record = (MEMORY_STATUSCODE_RECORD *) (PacketHeader + 1); + Record = &Record[PacketHeader->RecordIndex++]; + + // + // Save status code. + // + Record->CodeType = CodeType; + Record->Instance = Instance; + Record->Value = Value; + + // + // If record index equals to max record number, then wrap around record index to zero. + // + // The reader of status code should compare the number of records with max records number, + // If it is equal to or larger than the max number, then the wrap-around had happened, + // so the first record is pointed by record index. + // If it is less then max number, index of the first record is zero. + // + if (PacketHeader->RecordIndex == PacketHeader->MaxRecordsNumber) { + // + // Wrap around record index. + // + PacketHeader->RecordIndex = 0; + PacketHeader->PacketIndex ++; + } + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/SerialStatusCodeWorker.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/SerialStatusCodeWorker.c new file mode 100644 index 0000000000..d62cb8f8c8 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/SerialStatusCodeWorker.c @@ -0,0 +1,162 @@ +/** @file + Serial I/O status code reporting worker. + + 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 + 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 "StatusCodePei.h" + +/** + Convert status code value and extended data to readable ASCII string, send string to serial I/O device. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or + software entity. This includes information about the class and + subclass that is used to classify the entity as well as an operation. + For progress codes, the operation is the current activity. + For error codes, it is the exception.For debug codes,it is not defined at this time. + @param Instance The enumeration of a hardware or software entity within + the system. A system may contain multiple entities that match a class/subclass + pairing. The instance differentiates between them. An instance of 0 indicates + that instance information is unavailable, not meaningful, or not relevant. + Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS Status code reported to serial I/O successfully. + +**/ +EFI_STATUS +SerialStatusCodeReportWorker ( + 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%08x:V%08x I%x", + CodeType, + Value, + Instance + ); + + 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%08x 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%08x:V%08x I%x\n\r", + CodeType, + Value, + Instance + ); + } + + // + // Call SerialPort Lib function to do print. + // + SerialPortWrite ((UINT8 *) Buffer, CharCount); + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.c new file mode 100644 index 0000000000..5b17df3862 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.c @@ -0,0 +1,146 @@ +/** @file + Status code PEIM which produces Status Code PPI. + + Copyright (c) 2006 - 2009, Intel 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 "StatusCodePei.h" + +EFI_PEI_PROGRESS_CODE_PPI mStatusCodePpi = { + ReportDispatcher + }; + +EFI_PEI_PPI_DESCRIPTOR mStatusCodePpiDescriptor = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiStatusCodePpiGuid, + &mStatusCodePpi + }; + +/** + Publishes an interface that allows PEIMs to report status codes. + + This function implements EFI_PEI_PROGRESS_CODE_PPI.ReportStatusCode(). + It publishes an interface that allows PEIMs to report status codes. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or + software entity. This includes information about the class and + subclass that is used to classify the entity as well as an operation. + For progress codes, the operation is the current activity. + For error codes, it is the exception.For debug codes,it is not defined at this time. + @param Instance The enumeration of a hardware or software entity within + the system. A system may contain multiple entities that match a class/subclass + pairing. The instance differentiates between them. An instance of 0 indicates + that instance information is unavailable, not meaningful, or not relevant. + Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +EFIAPI +ReportDispatcher ( + 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 OPTIONAL, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + if (FeaturePcdGet (PcdStatusCodeUseSerial)) { + SerialStatusCodeReportWorker ( + CodeType, + Value, + Instance, + CallerId, + Data + ); + } + if (FeaturePcdGet (PcdStatusCodeUseMemory)) { + MemoryStatusCodeReportWorker ( + CodeType, + Value, + Instance + ); + } + if (FeaturePcdGet (PcdStatusCodeUseOEM)) { + // + // Call OEM hook status code library API to report status code to OEM device + // + OemHookStatusCodeReport ( + CodeType, + Value, + Instance, + (EFI_GUID *)CallerId, + (EFI_STATUS_CODE_DATA *)Data + ); + } + + return EFI_SUCCESS; +} + +/** + Entry point of Status Code PEIM. + + This function is the entry point of this Status Code PEIM. + It initializes supported status code devices according to PCD settings, + and installs Status Code PPI. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully. + +**/ +EFI_STATUS +EFIAPI +PeiStatusCodeDriverEntry ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + // + // Dispatch initialization request to sub-statuscode-devices. + // If enable UseSerial, then initialize serial port. + // if enable UseMemory, then initialize memory status code worker. + // if enable UseOEM, then initialize Oem status code. + // + if (FeaturePcdGet (PcdStatusCodeUseSerial)) { + Status = SerialPortInitialize(); + ASSERT_EFI_ERROR (Status); + } + if (FeaturePcdGet (PcdStatusCodeUseMemory)) { + Status = MemoryStatusCodeInitializeWorker (); + ASSERT_EFI_ERROR (Status); + } + if (FeaturePcdGet (PcdStatusCodeUseOEM)) { + Status = OemHookStatusCodeInitialize (); + ASSERT_EFI_ERROR (Status); + } + + // + // Install Status Code PPI. + // It serves the PEI Service ReportStatusCode. + // + Status = PeiServicesInstallPpi (&mStatusCodePpiDescriptor); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.h b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.h new file mode 100644 index 0000000000..75078d0ef4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.h @@ -0,0 +1,147 @@ +/** @file + Internal include file for Status Code PEIM. + + Copyright (c) 2006 - 2009, Intel 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_STATUS_CODE_H__ +#define __PEI_STATUS_CODE_H__ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Convert status code value and extended data to readable ASCII string, send string to serial I/O device. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or + software entity. This includes information about the class and + subclass that is used to classify the entity as well as an operation. + For progress codes, the operation is the current activity. + For error codes, it is the exception.For debug codes,it is not defined at this time. + @param Instance The enumeration of a hardware or software entity within + the system. A system may contain multiple entities that match a class/subclass + pairing. The instance differentiates between them. An instance of 0 indicates + that instance information is unavailable, not meaningful, or not relevant. + Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS Status code reported to serial I/O successfully. + +**/ +EFI_STATUS +SerialStatusCodeReportWorker ( + 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 + ); + + +/** + Create the first memory status code GUID'ed HOB as initialization for memory status code worker. + + @retval EFI_SUCCESS The GUID'ed HOB is created successfully. + +**/ +EFI_STATUS +MemoryStatusCodeInitializeWorker ( + VOID + ); + +/** + Report status code into GUID'ed HOB. + + This function reports status code into GUID'ed HOB. If not all packets are full, then + write status code into available entry. Otherwise, create a new packet for it. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or + software entity. This includes information about the class and + subclass that is used to classify the entity as well as an operation. + For progress codes, the operation is the current activity. + For error codes, it is the exception.For debug codes,it is not defined at this time. + @param Instance The enumeration of a hardware or software entity within + the system. A system may contain multiple entities that match a class/subclass + pairing. The instance differentiates between them. An instance of 0 indicates + that instance information is unavailable, not meaningful, or not relevant. + Valid instance numbers start with 1. + + @retval EFI_SUCCESS The function always return EFI_SUCCESS. + +**/ +EFI_STATUS +MemoryStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance + ); + +/** + Publishes an interface that allows PEIMs to report status codes. + + This function implements EFI_PEI_PROGRESS_CODE_PPI.ReportStatusCode(). + It publishes an interface that allows PEIMs to report status codes. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or + software entity. This includes information about the class and + subclass that is used to classify the entity as well as an operation. + For progress codes, the operation is the current activity. + For error codes, it is the exception.For debug codes,it is not defined at this time. + @param Instance The enumeration of a hardware or software entity within + the system. A system may contain multiple entities that match a class/subclass + pairing. The instance differentiates between them. An instance of 0 indicates + that instance information is unavailable, not meaningful, or not relevant. + Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +EFIAPI +ReportDispatcher ( + 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 OPTIONAL, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +#endif + + diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf new file mode 100644 index 0000000000..04cef4a2f4 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf @@ -0,0 +1,78 @@ +## @file +# Status code PEIM which produces Status Code PPI. +# +# 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 +# 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 = StatusCodePei + MODULE_UNI_FILE = StatusCodePei.uni + FILE_GUID = 1EC0F53A-FDE0-4576-8F25-7A1A410F58EB + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = PeiStatusCodeDriverEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + StatusCodePei.c + StatusCodePei.h + MemoryStausCodeWorker.c + SerialStatusCodeWorker.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + PeimEntryPoint + OemHookStatusCodeLib + PeiServicesLib + PcdLib + HobLib + SerialPortLib + ReportStatusCodeLib + PrintLib + DebugLib + BaseLib + + +[Guids] + gMemoryStatusCodeRecordGuid ## SOMETIMES_CONSUMES ## HOB + gEfiStatusCodeDataTypeStringGuid ## SOMETIMES_CONSUMES ## UNDEFINED # String Data Type + +[Ppis] + gEfiPeiStatusCodePpiGuid ## PRODUCES + + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseOEM ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES + + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + StatusCodePeiExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.uni b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.uni new file mode 100644 index 0000000000..1e0b9edd0d Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePeiExtra.uni b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePeiExtra.uni new file mode 100644 index 0000000000..6385b4190e Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePeiExtra.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c new file mode 100644 index 0000000000..ffee2f9c2a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c @@ -0,0 +1,390 @@ +/** @file + Data Hub status code worker. + + Copyright (c) 2006 - 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 "StatusCodeRuntimeDxe.h" + +// +// Initialize FIFO to cache records. +// +LIST_ENTRY mRecordsFifo = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsFifo); +LIST_ENTRY mRecordsBuffer = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsBuffer); +UINT32 mLogDataHubStatus = 0; +EFI_EVENT mLogDataHubEvent; +// +// Cache data hub protocol. +// +EFI_DATA_HUB_PROTOCOL *mDataHubProtocol = NULL; + + +/** + Retrieve one record of from free record buffer. This record is removed from + free record buffer. + + This function retrieves one record from free record buffer. + If the pool has been exhausted, then new memory would be allocated for it. + + @return Pointer to the free record. + NULL means failure to allocate new memeory for free record buffer. + +**/ +DATA_HUB_STATUS_CODE_DATA_RECORD * +AcquireRecordBuffer ( + VOID + ) +{ + DATAHUB_STATUSCODE_RECORD *Record; + EFI_TPL CurrentTpl; + LIST_ENTRY *Node; + UINT32 Index; + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + if (!IsListEmpty (&mRecordsBuffer)) { + // + // Strip one entry from free record buffer. + // + Node = GetFirstNode (&mRecordsBuffer); + RemoveEntryList (Node); + + Record = BASE_CR (Node, DATAHUB_STATUSCODE_RECORD, Node); + } else { + if (CurrentTpl > TPL_NOTIFY) { + // + // Memory management should work at <=TPL_NOTIFY + // + gBS->RestoreTPL (CurrentTpl); + return NULL; + } + + // + // If free record buffer is exhausted, then allocate 16 new records for it. + // + gBS->RestoreTPL (CurrentTpl); + Record = (DATAHUB_STATUSCODE_RECORD *) AllocateZeroPool (sizeof (DATAHUB_STATUSCODE_RECORD) * 16); + if (Record == NULL) { + return NULL; + } + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + // + // Here we only insert 15 new records to the free record buffer, for the first record + // will be returned immediately. + // + for (Index = 1; Index < 16; Index++) { + InsertTailList (&mRecordsBuffer, &Record[Index].Node); + } + } + + Record->Signature = DATAHUB_STATUS_CODE_SIGNATURE; + InsertTailList (&mRecordsFifo, &Record->Node); + + gBS->RestoreTPL (CurrentTpl); + + return (DATA_HUB_STATUS_CODE_DATA_RECORD *) (Record->Data); +} + + +/** + Retrieve one record from Records FIFO. The record would be removed from FIFO. + + @return Point to record, which is ready to be logged. + NULL means the FIFO of record is empty. + +**/ +DATA_HUB_STATUS_CODE_DATA_RECORD * +RetrieveRecord ( + VOID + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData; + DATAHUB_STATUSCODE_RECORD *Record; + LIST_ENTRY *Node; + EFI_TPL CurrentTpl; + + RecordData = NULL; + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + if (!IsListEmpty (&mRecordsFifo)) { + Node = GetFirstNode (&mRecordsFifo); + Record = CR (Node, DATAHUB_STATUSCODE_RECORD, Node, DATAHUB_STATUS_CODE_SIGNATURE); + ASSERT (Record != NULL); + + RemoveEntryList (&Record->Node); + RecordData = (DATA_HUB_STATUS_CODE_DATA_RECORD *) Record->Data; + } + + gBS->RestoreTPL (CurrentTpl); + + return RecordData; +} + +/** + Release given record and return it to free record buffer. + + @param RecordData Pointer to the record to release. + +**/ +VOID +ReleaseRecord ( + DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData + ) +{ + DATAHUB_STATUSCODE_RECORD *Record; + EFI_TPL CurrentTpl; + + Record = CR (RecordData, DATAHUB_STATUSCODE_RECORD, Data[0], DATAHUB_STATUS_CODE_SIGNATURE); + ASSERT (Record != NULL); + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + InsertTailList (&mRecordsBuffer, &Record->Node); + Record->Signature = 0; + + gBS->RestoreTPL (CurrentTpl); +} + +/** + Report status code into DataHub. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_DEVICE_ERROR Function is reentered. + @retval EFI_DEVICE_ERROR Function is called at runtime. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. + +**/ +EFI_STATUS +DataHubStatusCodeReportWorker ( + 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 + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *Record; + UINT32 ErrorLevel; + BASE_LIST Marker; + CHAR8 *Format; + UINTN CharCount; + EFI_STATUS Status; + + // + // Use atom operation to avoid the reentant of report. + // If current status is not zero, then the function is reentrancy. + // + if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 0) == 1) { + return EFI_DEVICE_ERROR; + } + + // + // See whether in runtime phase or not. + // + if (EfiAtRuntime ()) { + return EFI_DEVICE_ERROR; + } + + if (mDataHubProtocol == NULL) { + Status = DataHubStatusCodeInitializeWorker (); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Record = AcquireRecordBuffer (); + if (Record == NULL) { + // + // There are no empty record buffer in private buffers + // + return EFI_OUT_OF_RESOURCES; + } + + // + // Construct Data Hub Extended Data + // + Record->CodeType = CodeType; + Record->Value = Value; + Record->Instance = Instance; + + if (CallerId != NULL) { + CopyMem (&Record->CallerId, CallerId, sizeof (EFI_GUID)); + } + + if (Data != NULL) { + if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { + CharCount = UnicodeBSPrintAsciiFormat ( + (CHAR16 *) (Record + 1), + EFI_STATUS_CODE_DATA_MAX_SIZE, + Format, + Marker + ); + // + // Change record data type to DebugType. + // + CopyGuid (&Record->Data.Type, &gEfiStatusCodeDataTypeDebugGuid); + Record->Data.HeaderSize = Data->HeaderSize; + Record->Data.Size = (UINT16) ((CharCount + 1) * sizeof (CHAR16)); + } else { + // + // Copy status code data header + // + CopyMem (&Record->Data, Data, sizeof (EFI_STATUS_CODE_DATA)); + + if (Data->Size > EFI_STATUS_CODE_DATA_MAX_SIZE) { + Record->Data.Size = EFI_STATUS_CODE_DATA_MAX_SIZE; + } + CopyMem ((VOID *) (Record + 1), Data + 1, Record->Data.Size); + } + } + + gBS->SignalEvent (mLogDataHubEvent); + + return EFI_SUCCESS; +} + + +/** + The Event handler which will be notified to log data in Data Hub. + + @param Event Instance of the EFI_EVENT to signal whenever data is + available to be logged in the system. + @param Context Context of the event. + +**/ +VOID +EFIAPI +LogDataHubEventCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *Record; + UINT32 Size; + UINT64 DataRecordClass; + + // + // Use atom operation to avoid the reentant of report. + // If current status is not zero, then the function is reentrancy. + // + if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 1) == 1) { + return; + } + + // + // Log DataRecord in Data Hub. + // Journal records fifo to find all record entry. + // + while (TRUE) { + // + // Retrieve record from record FIFO until no more record can be retrieved. + // + Record = RetrieveRecord (); + if (Record == NULL) { + break; + } + // + // Add in the size of the header we added. + // + Size = sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD) + (UINT32) Record->Data.Size; + + if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_ERROR; + } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG; + } else { + // + // Should never get here. + // + DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG | + EFI_DATA_RECORD_CLASS_ERROR | + EFI_DATA_RECORD_CLASS_DATA | + EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } + + // + // Log DataRecord in Data Hub + // + mDataHubProtocol->LogData ( + mDataHubProtocol, + &gEfiDataHubStatusCodeRecordGuid, + &gEfiStatusCodeRuntimeProtocolGuid, + DataRecordClass, + Record, + Size + ); + + ReleaseRecord (Record); + } + + // + // Restore the nest status of report + // + InterlockedCompareExchange32 (&mLogDataHubStatus, 1, 0); +} + + +/** + Locate Data Hub Protocol and create event for logging data + as initialization for data hub status code worker. + + @retval EFI_SUCCESS Initialization is successful. + +**/ +EFI_STATUS +DataHubStatusCodeInitializeWorker ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID **) &mDataHubProtocol + ); + if (EFI_ERROR (Status)) { + mDataHubProtocol = NULL; + return Status; + } + + // + // Create a Notify Event to log data in Data Hub + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + LogDataHubEventCallBack, + NULL, + &mLogDataHubEvent + ); + + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c new file mode 100644 index 0000000000..2a26e19e65 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c @@ -0,0 +1,104 @@ +/** @file + Runtime memory status code worker. + + Copyright (c) 2006 - 2009, Intel 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 "StatusCodeRuntimeDxe.h" + +RUNTIME_MEMORY_STATUSCODE_HEADER *mRtMemoryStatusCodeTable; + +/** + Initialize runtime memory status code table as initialization for runtime memory status code worker + + @retval EFI_SUCCESS Runtime memory status code table successfully initialized. + +**/ +EFI_STATUS +RtMemoryStatusCodeInitializeWorker ( + VOID + ) +{ + // + // Allocate runtime memory status code pool. + // + mRtMemoryStatusCodeTable = AllocateRuntimePool ( + sizeof (RUNTIME_MEMORY_STATUSCODE_HEADER) + + PcdGet16 (PcdStatusCodeMemorySize) * 1024 + ); + ASSERT (mRtMemoryStatusCodeTable != NULL); + + mRtMemoryStatusCodeTable->RecordIndex = 0; + mRtMemoryStatusCodeTable->NumberOfRecords = 0; + mRtMemoryStatusCodeTable->MaxRecordsNumber = + (PcdGet16 (PcdStatusCodeMemorySize) * 1024) / sizeof (MEMORY_STATUSCODE_RECORD); + + return EFI_SUCCESS; +} + + +/** + Report status code into runtime memory. If the runtime pool is full, roll back to the + first record and overwrite it. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + + @retval EFI_SUCCESS Status code successfully recorded in runtime memory status code table. + +**/ +EFI_STATUS +RtMemoryStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance + ) +{ + MEMORY_STATUSCODE_RECORD *Record; + + // + // Locate current record buffer. + // + Record = (MEMORY_STATUSCODE_RECORD *) (mRtMemoryStatusCodeTable + 1); + Record = &Record[mRtMemoryStatusCodeTable->RecordIndex++]; + + // + // Save status code. + // + Record->CodeType = CodeType; + Record->Value = Value; + Record->Instance = Instance; + + // + // If record index equals to max record number, then wrap around record index to zero. + // + // The reader of status code should compare the number of records with max records number, + // If it is equal to or larger than the max number, then the wrap-around had happened, + // so the first record is pointed by record index. + // If it is less then max number, index of the first record is zero. + // + mRtMemoryStatusCodeTable->NumberOfRecords++; + if (mRtMemoryStatusCodeTable->RecordIndex == mRtMemoryStatusCodeTable->MaxRecordsNumber) { + // + // Wrap around record index. + // + mRtMemoryStatusCodeTable->RecordIndex = 0; + } + + return EFI_SUCCESS; +} + + + diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c new file mode 100644 index 0000000000..e1d02630e7 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c @@ -0,0 +1,160 @@ +/** @file + Serial I/O status code reporting worker. + + 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 + 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 "StatusCodeRuntimeDxe.h" + +/** + Convert status code value and extended data to readable ASCII string, send string to serial I/O device. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS Status code reported to serial I/O successfully. + @retval EFI_DEVICE_ERROR EFI serial device cannot work after ExitBootService() is called. + @retval EFI_DEVICE_ERROR EFI serial device cannot work with TPL higher than TPL_CALLBACK. + +**/ +EFI_STATUS +SerialStatusCodeReportWorker ( + 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 + ) +{ + 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\rDXE_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%08x:V%08x I%x", + CodeType, + Value, + Instance + ); + + 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%08x 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%08x:V%08x I%x\n\r", + CodeType, + Value, + Instance + ); + } + + // + // Call SerialPort Lib function to do print. + // + SerialPortWrite ((UINT8 *) Buffer, CharCount); + + return EFI_SUCCESS; +} + diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c new file mode 100644 index 0000000000..6435e1f727 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c @@ -0,0 +1,301 @@ +/** @file + Status code driver for IA32/X64/EBC architecture. + + Copyright (c) 2006 - 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 "StatusCodeRuntimeDxe.h" + +EFI_EVENT mVirtualAddressChangeEvent = NULL; +EFI_HANDLE mHandle = NULL; + +// +// Declaration of status code protocol. +// +EFI_STATUS_CODE_PROTOCOL mEfiStatusCodeProtocol = { + ReportDispatcher +}; + +// +// Report operation nest status. +// If it is set, then the report operation has nested. +// +UINT32 mStatusCodeNestStatus = 0; + +/** + Entry point of DXE Status Code Driver. + + This function is the entry point of this DXE Status Code Driver. + It installs Status Code Runtime Protocol, and registers event for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. + + @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. + +**/ +EFI_STATUS +EFIAPI +StatusCodeRuntimeDxeEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Dispatch initialization request to supported devices + // + InitializationDispatcherWorker (); + + // + // Install Status Code Runtime Protocol implementation as defined in PI Specification. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiStatusCodeRuntimeProtocolGuid, + &mEfiStatusCodeProtocol, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + VirtualAddressChangeCallBack, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mVirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Report status code to all supported device. + + This function implements EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). + It calls into the workers which dispatches the platform specific listeners. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. + +**/ +EFI_STATUS +EFIAPI +ReportDispatcher ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + // + // Use atom operation to avoid the reentant of report. + // If current status is not zero, then the function is reentrancy. + // + if (InterlockedCompareExchange32 (&mStatusCodeNestStatus, 0, 1) == 1) { + return EFI_DEVICE_ERROR; + } + + if (FeaturePcdGet (PcdStatusCodeUseSerial)) { + SerialStatusCodeReportWorker ( + CodeType, + Value, + Instance, + CallerId, + Data + ); + } + if (FeaturePcdGet (PcdStatusCodeUseMemory)) { + RtMemoryStatusCodeReportWorker ( + CodeType, + Value, + Instance + ); + } + if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { + DataHubStatusCodeReportWorker ( + CodeType, + Value, + Instance, + CallerId, + Data + ); + } + if (FeaturePcdGet (PcdStatusCodeUseOEM)) { + // + // Call OEM hook status code library API to report status code to OEM device + // + OemHookStatusCodeReport ( + CodeType, + Value, + Instance, + CallerId, + Data + ); + } + + // + // Restore the nest status of report + // + InterlockedCompareExchange32 (&mStatusCodeNestStatus, 1, 0); + + return EFI_SUCCESS; +} + + +/** + Virtual address change notification call back. It converts global pointer + to virtual address. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, which is + always zero in current implementation. + +**/ +VOID +EFIAPI +VirtualAddressChangeCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Convert memory status code table to virtual address; + // + EfiConvertPointer ( + 0, + (VOID **) &mRtMemoryStatusCodeTable + ); +} + +/** + Dispatch initialization request to sub status code devices based on + customized feature flags. + +**/ +VOID +InitializationDispatcherWorker ( + VOID + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_STATUS Status; + MEMORY_STATUSCODE_PACKET_HEADER *PacketHeader; + MEMORY_STATUSCODE_RECORD *Record; + UINTN Index; + UINTN MaxRecordNumber; + + // + // If enable UseSerial, then initialize serial port. + // if enable UseRuntimeMemory, then initialize runtime memory status code worker. + // if enable UseDataHub, then initialize data hub status code worker. + // + if (FeaturePcdGet (PcdStatusCodeUseSerial)) { + // + // Call Serial Port Lib API to initialize serial port. + // + Status = SerialPortInitialize (); + ASSERT_EFI_ERROR (Status); + } + if (FeaturePcdGet (PcdStatusCodeUseMemory)) { + Status = RtMemoryStatusCodeInitializeWorker (); + ASSERT_EFI_ERROR (Status); + } + if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { + DataHubStatusCodeInitializeWorker (); + } + if (FeaturePcdGet (PcdStatusCodeUseOEM)) { + // + // Call OEM hook status code library API to initialize OEM device for status code. + // + Status = OemHookStatusCodeInitialize (); + ASSERT_EFI_ERROR (Status); + } + + // + // Replay Status code which saved in GUID'ed HOB to all supported devices. + // + if (FeaturePcdGet (PcdStatusCodeReplayIn)) { + // + // Journal GUID'ed HOBs to find all record entry, if found, + // then output record to support replay device. + // + Hob.Raw = GetFirstGuidHob (&gMemoryStatusCodeRecordGuid); + if (Hob.Raw != NULL) { + PacketHeader = (MEMORY_STATUSCODE_PACKET_HEADER *) GET_GUID_HOB_DATA (Hob.Guid); + Record = (MEMORY_STATUSCODE_RECORD *) (PacketHeader + 1); + MaxRecordNumber = (UINTN) PacketHeader->RecordIndex; + if (PacketHeader->PacketIndex > 0) { + // + // Record has been wrapped around. So, record number has arrived at max number. + // + MaxRecordNumber = (UINTN) PacketHeader->MaxRecordsNumber; + } + for (Index = 0; Index < MaxRecordNumber; Index++) { + // + // Dispatch records to devices based on feature flag. + // + if (FeaturePcdGet (PcdStatusCodeUseSerial)) { + SerialStatusCodeReportWorker ( + Record[Index].CodeType, + Record[Index].Value, + Record[Index].Instance, + NULL, + NULL + ); + } + if (FeaturePcdGet (PcdStatusCodeUseMemory)) { + RtMemoryStatusCodeReportWorker ( + Record[Index].CodeType, + Record[Index].Value, + Record[Index].Instance + ); + } + if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { + DataHubStatusCodeReportWorker ( + Record[Index].CodeType, + Record[Index].Value, + Record[Index].Instance, + NULL, + NULL + ); + } + if (FeaturePcdGet (PcdStatusCodeUseOEM)) { + // + // Call OEM hook status code library API to report status code to OEM device + // + OemHookStatusCodeReport ( + Record[Index].CodeType, + Record[Index].Value, + Record[Index].Instance, + NULL, + NULL + ); + } + } + } + } +} diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h new file mode 100644 index 0000000000..9d0ed19c4a --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h @@ -0,0 +1,240 @@ +/** @file + Internal include file of Status Code Runtime DXE Driver. + + Copyright (c) 2006 - 2009, Intel 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 __STATUS_CODE_RUNTIME_DXE_H__ +#define __STATUS_CODE_RUNTIME_DXE_H__ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Data hub worker definition +// +#define DATAHUB_STATUS_CODE_SIGNATURE SIGNATURE_32 ('B', 'D', 'H', 'S') + +typedef struct { + UINTN Signature; + LIST_ENTRY Node; + UINT8 Data[sizeof(DATA_HUB_STATUS_CODE_DATA_RECORD) + EFI_STATUS_CODE_DATA_MAX_SIZE]; +} DATAHUB_STATUSCODE_RECORD; + + +// +// Runtime memory status code worker definition +// +typedef struct { + UINT32 RecordIndex; + UINT32 NumberOfRecords; + UINT32 MaxRecordsNumber; +} RUNTIME_MEMORY_STATUSCODE_HEADER; + +extern RUNTIME_MEMORY_STATUSCODE_HEADER *mRtMemoryStatusCodeTable; + +/** + Report status code to all supported device. + + This function implements EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). + It calls into the workers which dispatches the platform specific listeners. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. + +**/ +EFI_STATUS +EFIAPI +ReportDispatcher ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + Dispatch initialization request to sub status code devices based on + customized feature flags. + +**/ +VOID +InitializationDispatcherWorker ( + VOID + ); + + +/** + Locates Serial I/O Protocol as initialization for serial status code worker. + + @retval EFI_SUCCESS Serial I/O Protocol is successfully located. + +**/ +EFI_STATUS +EfiSerialStatusCodeInitializeWorker ( + VOID + ); + + +/** + Convert status code value and extended data to readable ASCII string, send string to serial I/O device. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS Status code reported to serial I/O successfully. + @retval EFI_DEVICE_ERROR EFI serial device cannot work after ExitBootService() is called. + @retval EFI_DEVICE_ERROR EFI serial device cannot work with TPL higher than TPL_CALLBACK. + +**/ +EFI_STATUS +SerialStatusCodeReportWorker ( + 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 + ); + +/** + Initialize runtime memory status code table as initialization for runtime memory status code worker + + @retval EFI_SUCCESS Runtime memory status code table successfully initialized. + +**/ +EFI_STATUS +RtMemoryStatusCodeInitializeWorker ( + VOID + ); + +/** + Report status code into runtime memory. If the runtime pool is full, roll back to the + first record and overwrite it. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + + @retval EFI_SUCCESS Status code successfully recorded in runtime memory status code table. + +**/ +EFI_STATUS +RtMemoryStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance + ); + +/** + Locate Data Hub Protocol and create event for logging data + as initialization for data hub status code worker. + + @retval EFI_SUCCESS Initialization is successful. + +**/ +EFI_STATUS +DataHubStatusCodeInitializeWorker ( + VOID + ); + + +/** + Report status code into DataHub. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_DEVICE_ERROR Function is reentered. + @retval EFI_DEVICE_ERROR Function is called at runtime. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. + +**/ +EFI_STATUS +DataHubStatusCodeReportWorker ( + 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 + ); + + +/** + Virtual address change notification call back. It converts global pointer + to virtual address. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, which is + always zero in current implementation. + +**/ +VOID +EFIAPI +VirtualAddressChangeCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +#endif diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf new file mode 100644 index 0000000000..d7c35021a2 --- /dev/null +++ b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf @@ -0,0 +1,88 @@ +## @file +# Status Code Runtime Dxe driver produces Status Code Runtime 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 +# 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 = StatusCodeRuntimeDxe + MODULE_UNI_FILE = StatusCodeRuntimeDxe.uni + FILE_GUID = FEDE0A1B-BCA2-4A9F-BB2B-D9FD7DEC2E9F + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = StatusCodeRuntimeDxeEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# +# VIRTUAL_ADDRESS_MAP_CALLBACK = VirtualAddressChangeCallBack +# + +[Sources] + SerialStatusCodeWorker.c + RtMemoryStatusCodeWorker.c + DataHubStatusCodeWorker.c + StatusCodeRuntimeDxe.h + StatusCodeRuntimeDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + OemHookStatusCodeLib + SerialPortLib + UefiRuntimeLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + HobLib + PcdLib + PrintLib + ReportStatusCodeLib + DebugLib + BaseMemoryLib + BaseLib + SynchronizationLib + + +[Guids] + gEfiDataHubStatusCodeRecordGuid ## SOMETIMES_PRODUCES ## UNDEFINED # DataRecord Guid + gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_PRODUCES ## UNDEFINED # Record data type + gMemoryStatusCodeRecordGuid ## SOMETIMES_CONSUMES ## HOB + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + gEfiStatusCodeDataTypeStringGuid ## SOMETIMES_CONSUMES ## UNDEFINED + +[Protocols] + gEfiStatusCodeRuntimeProtocolGuid ## PRODUCES + gEfiDataHubProtocolGuid ## SOMETIMES_CONSUMES # Needed if Data Hub is supported for status code + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeReplayIn ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseOEM ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize |128| gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES + +[Depex] + TRUE +[UserExtensions.TianoCore."ExtraFiles"] + StatusCodeRuntimeDxeExtra.uni diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni new file mode 100644 index 0000000000..963a16e9e6 Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni differ diff --git a/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxeExtra.uni b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxeExtra.uni new file mode 100644 index 0000000000..ae409adbed Binary files /dev/null and b/Core/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxeExtra.uni differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c deleted file mode 100644 index 1663d7fcd5..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.c +++ /dev/null @@ -1,182 +0,0 @@ -/** @file - UEFI Component Name(2) protocol implementation for IsaBus 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 "InternalIsaBus.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaBusComponentName = { - IsaBusComponentNameGetDriverName, - IsaBusComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaBusComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaBusComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaBusComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaBusDriverNameTable[] = { - { - "eng;en", - L"ISA Bus Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -IsaBusComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mIsaBusDriverNameTable, - DriverName, - (BOOLEAN)(This == &gIsaBusComponentName) - ); -} - -/** - 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 -IsaBusComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h deleted file mode 100644 index ffacf44063..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/ComponentName.h +++ /dev/null @@ -1,148 +0,0 @@ -/** @file - Header file for implementation of UEFI Component Name(2) protocol. - -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 _COMPONENT_NAME_H_ -#define _COMPONENT_NAME_H_ - -extern EFI_COMPONENT_NAME_PROTOCOL gIsaBusComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gIsaBusComponentName2; - -/** - 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 -IsaBusComponentNameGetDriverName ( - 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 -IsaBusComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h deleted file mode 100644 index 9e559da72b..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaBus.h +++ /dev/null @@ -1,297 +0,0 @@ -/** @file - The header file for ISA bus driver - -Copyright (c) 2006 - 2009, Intel 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_ISA_BUS_H_ -#define _INTERNAL_ISA_BUS_H_ - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ComponentName.h" - -// -// 8237 DMA registers -// -#define R_8237_DMA_BASE_CA_CH0 0x00 -#define R_8237_DMA_BASE_CA_CH1 0x02 -#define R_8237_DMA_BASE_CA_CH2 0x04 -#define R_8237_DMA_BASE_CA_CH3 0xd6 -#define R_8237_DMA_BASE_CA_CH5 0xc4 -#define R_8237_DMA_BASE_CA_CH6 0xc8 -#define R_8237_DMA_BASE_CA_CH7 0xcc - -#define R_8237_DMA_BASE_CC_CH0 0x01 -#define R_8237_DMA_BASE_CC_CH1 0x03 -#define R_8237_DMA_BASE_CC_CH2 0x05 -#define R_8237_DMA_BASE_CC_CH3 0xd7 -#define R_8237_DMA_BASE_CC_CH5 0xc6 -#define R_8237_DMA_BASE_CC_CH6 0xca -#define R_8237_DMA_BASE_CC_CH7 0xce - -#define R_8237_DMA_MEM_LP_CH0 0x87 -#define R_8237_DMA_MEM_LP_CH1 0x83 -#define R_8237_DMA_MEM_LP_CH2 0x81 -#define R_8237_DMA_MEM_LP_CH3 0x82 -#define R_8237_DMA_MEM_LP_CH5 0x8B -#define R_8237_DMA_MEM_LP_CH6 0x89 -#define R_8237_DMA_MEM_LP_CH7 0x8A - - -#define R_8237_DMA_COMMAND_CH0_3 0x08 -#define R_8237_DMA_COMMAND_CH4_7 0xd0 -#define B_8237_DMA_COMMAND_GAP 0x10 -#define B_8237_DMA_COMMAND_CGE 0x04 - - -#define R_8237_DMA_STA_CH0_3 0xd8 -#define R_8237_DMA_STA_CH4_7 0xd0 - -#define R_8237_DMA_WRSMSK_CH0_3 0x0a -#define R_8237_DMA_WRSMSK_CH4_7 0xd4 -#define B_8237_DMA_WRSMSK_CMS 0x04 - - -#define R_8237_DMA_CHMODE_CH0_3 0x0b -#define R_8237_DMA_CHMODE_CH4_7 0xd6 -#define V_8237_DMA_CHMODE_DEMAND 0x00 -#define V_8237_DMA_CHMODE_SINGLE 0x40 -#define V_8237_DMA_CHMODE_CASCADE 0xc0 -#define B_8237_DMA_CHMODE_DECREMENT 0x20 -#define B_8237_DMA_CHMODE_INCREMENT 0x00 -#define B_8237_DMA_CHMODE_AE 0x10 -#define V_8237_DMA_CHMODE_VERIFY 0 -#define V_8237_DMA_CHMODE_IO2MEM 0x04 -#define V_8237_DMA_CHMODE_MEM2IO 0x08 - -#define R_8237_DMA_CBPR_CH0_3 0x0c -#define R_8237_DMA_CBPR_CH4_7 0xd8 - -#define R_8237_DMA_MCR_CH0_3 0x0d -#define R_8237_DMA_MCR_CH4_7 0xda - -#define R_8237_DMA_CLMSK_CH0_3 0x0e -#define R_8237_DMA_CLMSK_CH4_7 0xdc - -#define R_8237_DMA_WRMSK_CH0_3 0x0f -#define R_8237_DMA_WRMSK_CH4_7 0xde - -typedef enum { - IsaAccessTypeUnknown, - IsaAccessTypeIo, - IsaAccessTypeMem, - IsaAccessTypeMaxType -} ISA_ACCESS_TYPE; - -// -// 16 MB Memory Range -// -#define ISA_MAX_MEMORY_ADDRESS 0x1000000 -// -// 64K I/O Range -// -#define ISA_MAX_IO_ADDRESS 0x10000 - -typedef struct { - UINT8 Address; - UINT8 Page; - UINT8 Count; -} EFI_ISA_DMA_REGISTERS; - -// -// ISA I/O Device Structure -// -#define ISA_IO_DEVICE_SIGNATURE SIGNATURE_32 ('i', 's', 'a', 'i') - -typedef struct { - UINT32 Signature; - EFI_HANDLE Handle; - EFI_ISA_IO_PROTOCOL IsaIo; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; -} ISA_IO_DEVICE; - -#define ISA_IO_DEVICE_FROM_ISA_IO_THIS(a) CR (a, ISA_IO_DEVICE, IsaIo, ISA_IO_DEVICE_SIGNATURE) - -// -// Mapping structure for performing ISA DMA to a buffer above 16 MB -// -typedef struct { - EFI_ISA_IO_PROTOCOL_OPERATION Operation; - UINTN NumberOfBytes; - UINTN NumberOfPages; - EFI_PHYSICAL_ADDRESS HostAddress; - EFI_PHYSICAL_ADDRESS MappedHostAddress; -} ISA_MAP_INFO; - -// -// EFI Driver Binding Protocol Interface Functions -// - -/** - Tests to see if a controller can be managed by the ISA Bus Driver. If a child device is provided, - it further tests to see if this driver supports creating a handle for the specified child device. - - Note that the ISA Bus driver always creates all of its child handles on the first call to Start(). - How the Start() function of a driver is implemented can affect how the Supported() function is implemented. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] Controller The handle of the controller to test. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS The device is supported by this driver. - @retval EFI_ALREADY_STARTED The device is already being managed by this driver. - @retval EFI_ACCESS_DENIED The device is already being managed by a different driver - or an application that requires exclusive access. - @retval EFI_UNSUPPORTED The device is is not supported by this driver. - -**/ -EFI_STATUS -EFIAPI -IsaBusControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ); - -/** - Start this driver on ControllerHandle. - - Note that the ISA Bus driver always creates all of its child handles on the first call to Start(). - The Start() function is designed to be invoked from the EFI boot service ConnectController(). - As a result, much of the error checking on the parameters to Start() has been moved into this - common boot service. It is legal to call Start() from other locations, but the following calling - restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE. - 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned - EFI_DEVICE_PATH_PROTOCOL. - 3. Prior to calling Start(), the Supported() function for the driver specified by This must - have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - This parameter is ignored by device drivers, and is optional for bus drivers. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error. - Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. -**/ -EFI_STATUS -EFIAPI -IsaBusControllerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ); - -/** - Stop this driver on ControllerHandle. - - The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). - As a result, much of the error checking on the parameters to Stop() has been moved - into this common boot service. It is legal to call Stop() from other locations, - but the following calling restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this - same driver's Start() function. - 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid - EFI_HANDLE. In addition, all of these handles must have been created in this driver's - Start() function, and the Start() function must have called OpenProtocol() on - ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. -**/ -EFI_STATUS -EFIAPI -IsaBusControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL * This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE * ChildHandleBuffer OPTIONAL - ); - -// -// Function Prototypes -// - -/** - Create EFI Handle for a ISA device found via ISA ACPI Protocol - - @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] Controller The handle of ISA bus controller(PCI to ISA bridge) - @param[in] PciIo The Pointer to the PCI protocol - @param[in] ParentDevicePath Device path of the ISA bus controller - @param[in] IsaDeviceResourceList The resource list of the ISA device - @param[out] ChildDevicePath The pointer to the child device. - - @retval EFI_SUCCESS The handle for the child device was created. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval EFI_DEVICE_ERROR The handle for the child device can not be created. -**/ -EFI_STATUS -IsaCreateDevice ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, - IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList, - OUT EFI_DEVICE_PATH_PROTOCOL **ChildDevicePath - ); - -/** - Initializes an ISA I/O Instance - - @param[in] IsaIoDevice The iso device to be initialized. - @param[in] IsaDeviceResourceList The resource list. - -**/ -VOID -InitializeIsaIoInstance ( - IN ISA_IO_DEVICE *IsaIoDevice, - IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDevice - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h deleted file mode 100644 index 054a6b9bab..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/InternalIsaIo.h +++ /dev/null @@ -1,331 +0,0 @@ -/** @file - The header file for EFI_ISA_IO protocol implementation. - -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 _INTERNAL_ISA_IO_H_ -#define _INTERNAL_ISA_IO_H_ - -#include "InternalIsaBus.h" - -// -// Bits definition of PcdIsaBusSupportedFeatures -// -#define PCD_ISA_BUS_SUPPORT_DMA BIT0 -#define PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA BIT1 -#define PCD_ISA_BUS_SUPPORT_ISA_MEMORY BIT2 - -// -// ISA I/O Support Function Prototypes -// - -/** - Verifies access to an ISA device - - @param[in] IsaIoDevice The ISA device to be verified. - @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. - @param[in] Width The width of the memory operation. - @param[in] Count The number of memory operations to perform. - @param[in] Offset The offset in ISA memory space to start the memory operation. - - @retval EFI_SUCCESS Verify success. - @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. - @retval EFI_UNSUPPORTED The device ont support the access type. -**/ -EFI_STATUS -IsaIoVerifyAccess ( - IN ISA_IO_DEVICE *IsaIoDevice, - IN ISA_ACCESS_TYPE Type, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINTN Count, - IN UINT32 Offset - ); - -/** - Performs an ISA I/O Read Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O operation. - @param[in] Offset The offset in ISA I/O space to start the I/O operation. - @param[in] Count The number of I/O operations to perform. - @param[out] Buffer The destination buffer to store the results - - @retval EFI_SUCCESS The data was read from the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoIoRead ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - OUT VOID *Buffer - ); - -/** - Performs an ISA I/O Write Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O operation. - @param[in] Offset The offset in ISA I/O space to start the I/O operation. - @param[in] Count The number of I/O operations to perform. - @param[in] Buffer The source buffer to write data from - - @retval EFI_SUCCESS The data was writen to the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoIoWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN VOID *Buffer - ); - -/** - Maps a memory region for DMA - - @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param Operation Indicates the type of DMA (slave or bus master), and if - the DMA operation is going to read or write to system memory. - @param ChannelNumber The slave channel number to use for this DMA operation. - If Operation and ChannelAttributes shows that this device - performs bus mastering DMA, then this field is ignored. - The legal range for this field is 0..7. - @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation - @param HostAddress The system memory address to map to the device. - @param NumberOfBytes On input the number of bytes to map. On output the number - of bytes that were mapped. - @param DeviceAddress The resulting map address for the bus master device to use - to access the hosts HostAddress. - @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). - - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. - @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -EFIAPI -IsaIoMap ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ); - -/** - Unmaps a memory region for DMA - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). - - @retval EFI_SUCCESS The range was unmapped. - @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. -**/ -EFI_STATUS -EFIAPI -IsaIoUnmap ( - IN EFI_ISA_IO_PROTOCOL *This, - IN VOID *Mapping - ); - -/** - Flushes any posted write data to the system memory. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - - @retval EFI_SUCCESS The buffers were flushed. - @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. -**/ -EFI_STATUS -EFIAPI -IsaIoFlush ( - IN EFI_ISA_IO_PROTOCOL *This - ); - -/** - Writes I/O operation base address and count number to a 8 bit I/O Port. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] AddrOffset The address' offset. - @param[in] PageOffset The page's offest. - @param[in] CountOffset The count's offset. - @param[in] BaseAddress The base address. - @param[in] Count The number of I/O operations to perform. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Parameter is invalid. - @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -WriteDmaPort ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINT32 AddrOffset, - IN UINT32 PageOffset, - IN UINT32 CountOffset, - IN UINT32 BaseAddress, - IN UINT16 Count - ); - -/** - Writes an 8-bit I/O Port - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Offset The offset in ISA IO space to start the IO operation. - @param[in] Value The data to write port. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Parameter is invalid. - @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -WritePort ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINT32 Offset, - IN UINT8 Value - ); - -/** - Performs an ISA Memory Read Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory operation. - @param[in] Offset The offset in ISA memory space to start the memory operation. - @param[in] Count The number of memory operations to perform. - @param[out] Buffer The destination buffer to store the results - - @retval EFI_SUCCESS The data was read from the device successfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoMemRead ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - OUT VOID *Buffer - ); - - -/** - Performs an ISA Memory Write Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory operation. - @param[in] Offset The offset in ISA memory space to start the memory operation. - @param[in] Count The number of memory operations to perform. - @param[in] Buffer The source buffer to write data from - - @retval EFI_SUCCESS The data was written to the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoMemWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN VOID *Buffer - ); - -/** - Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory copy operation. - @param[in] DestOffset The offset of the destination - @param[in] SrcOffset The offset of the source - @param[in] Count The number of memory copy operations to perform - - @retval EFI_SUCCESS The data was copied sucessfully. - @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoCopyMem ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 DestOffset, - IN UINT32 SrcOffset, - IN UINTN Count - ); - -/** - Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Type The type allocation to perform. - @param[in] MemoryType The type of memory to allocate. - @param[in] Pages The number of pages to allocate. - @param[out] HostAddress A pointer to store the base address of the allocated range. - @param[in] Attributes The requested bit mask of attributes for the allocated range. - - @retval EFI_SUCCESS The requested memory pages were allocated. - @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL - @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified - by HostAddress, Pages, and Type is not available for common buffer use. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -EFIAPI -IsaIoAllocateBuffer ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ALLOCATE_TYPE Type, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Pages, - OUT VOID **HostAddress, - IN UINT64 Attributes - ); - -/** - Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Pages The number of pages to free. - @param[in] HostAddress The base address of the allocated range. - - @retval EFI_SUCCESS The requested memory pages were freed. - @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). -**/ -EFI_STATUS -EFIAPI -IsaIoFreeBuffer ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINTN Pages, - IN VOID *HostAddress - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c deleted file mode 100644 index 1312f260f9..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c +++ /dev/null @@ -1,673 +0,0 @@ -/** @file - ISA Bus UEFI driver. - - Discovers all the ISA Controllers and their resources by using the ISA ACPI - Protocol, produces an instance of the ISA I/O Protocol for every ISA - Controller found. This driver is designed to manage a PCI-to-ISA bridge Device - such as LPC bridge. - -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 -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 "InternalIsaBus.h" - -// -// ISA Bus Driver Global Variables -// -EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver = { - IsaBusControllerDriverSupported, - IsaBusControllerDriverStart, - IsaBusControllerDriverStop, - 0xa, - NULL, - NULL -}; - -/** - The main entry point for the ISA Bus 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 EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. -**/ -EFI_STATUS -EFIAPI -InitializeIsaBus( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gIsaBusControllerDriver, - ImageHandle, - &gIsaBusComponentName, - &gIsaBusComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} - -/** - Tests to see if a controller can be managed by the ISA Bus Driver. If a child device is provided, - it further tests to see if this driver supports creating a handle for the specified child device. - - Note that the ISA Bus driver always creates all of its child handles on the first call to Start(). - How the Start() function of a driver is implemented can affect how the Supported() function is implemented. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] Controller The handle of the controller to test. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS The device is supported by this driver. - @retval EFI_ALREADY_STARTED The device is already being managed by this driver. - @retval EFI_ACCESS_DENIED The device is already being managed by a different driver - or an application that requires exclusive access. - @retval EFI_UNSUPPORTED The device is is not supported by this driver. - -**/ -EFI_STATUS -EFIAPI -IsaBusControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_ISA_ACPI_PROTOCOL *IsaAcpi; - - // - // If RemainingDevicePath is not NULL, it should verify that the first device - // path node in RemainingDevicePath is an ACPI Device path node which is a - // legal Device Path Node for this bus driver's children. - // - if (RemainingDevicePath != NULL) { - if (RemainingDevicePath->Type != ACPI_DEVICE_PATH) { - return EFI_UNSUPPORTED; - } else if (RemainingDevicePath->SubType == ACPI_DP) { - if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_HID_DEVICE_PATH)) { - return EFI_UNSUPPORTED; - } - } else if (RemainingDevicePath->SubType == ACPI_EXTENDED_DP) { - if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)) { - return EFI_UNSUPPORTED; - } - } else { - return EFI_UNSUPPORTED; - } - } - // - // Try to open EFI DEVICE PATH protocol on the controller - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - // - // Although this driver creates all child handles at one time, - // but because all child handles may be not stopped at one time in EFI Driver Binding.Stop(), - // So it is allowed to create child handles again in successive calls to EFI Driver Binding.Start(). - // - if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - return Status; - } - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Try to get Pci IO Protocol because it is assumed - // to have been opened by ISA ACPI driver - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - NULL, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Try to open the Isa Acpi protocol on the controller - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaAcpiProtocolGuid, - (VOID **) &IsaAcpi, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Add more check to see if the child device is valid by calling IsaAcpi->DeviceEnumerate? - // - - gBS->CloseProtocol ( - Controller, - &gEfiIsaAcpiProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Start this driver on ControllerHandle. - - Note that the ISA Bus driver always creates all of its child handles on the first call to Start(). - The Start() function is designed to be invoked from the EFI boot service ConnectController(). - As a result, much of the error checking on the parameters to Start() has been moved into this - common boot service. It is legal to call Start() from other locations, but the following calling - restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE. - 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned - EFI_DEVICE_PATH_PROTOCOL. - 3. Prior to calling Start(), the Supported() function for the driver specified by This must - have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - This parameter is ignored by device drivers, and is optional for bus drivers. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error. - Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. -**/ -EFI_STATUS -EFIAPI -IsaBusControllerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_ISA_ACPI_PROTOCOL *IsaAcpi; - EFI_ISA_ACPI_DEVICE_ID *IsaDevice; - EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; - EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; - - // - // Local variables declaration for StatusCode reporting - // - EFI_DEVICE_PATH_PROTOCOL *DevicePathData; - - DevicePathData = NULL; - - // - // Get Pci IO Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Open Device Path Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { - return Status; - } - - // - // Open ISA Acpi Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaAcpiProtocolGuid, - (VOID **) &IsaAcpi, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { - // - // Close opened protocol - // - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - return Status; - } - // - // The IsaBus driver will use memory below 16M, which is not tested yet, - // so call CompatibleRangeTest to test them. Since memory below 1M should - // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M - // ~15M here - // - Status = gBS->LocateProtocol ( - &gEfiGenericMemTestProtocolGuid, - NULL, - (VOID **) &GenMemoryTest - ); - - if (!EFI_ERROR (Status)) { - Status = GenMemoryTest->CompatibleRangeTest ( - GenMemoryTest, - 0x100000, - 0xE00000 - ); - } - // - // Report Status Code here since we will initialize the host controller - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT), - ParentDevicePath - ); - - // - // first init ISA interface - // - IsaAcpi->InterfaceInit (IsaAcpi); - - // - // Report Status Code here since we will enable the host controller - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE), - ParentDevicePath - ); - - // - // Create each ISA device handle in this ISA bus - // - IsaDevice = NULL; - do { - Status = IsaAcpi->DeviceEnumerate (IsaAcpi, &IsaDevice); - if (EFI_ERROR (Status)) { - break; - } - // - // Get current resource of this ISA device - // - ResourceList = NULL; - Status = IsaAcpi->GetCurResource (IsaAcpi, IsaDevice, &ResourceList); - if (EFI_ERROR (Status)) { - continue; - } - - // - // Create handle for this ISA device - // - // If any child device handle was created in previous call to Start() and not stopped - // in previous call to Stop(), it will not be created again because the - // InstallMultipleProtocolInterfaces() boot service will reject same device path. - // - Status = IsaCreateDevice ( - This, - Controller, - PciIo, - ParentDevicePath, - ResourceList, - &DevicePathData - ); - - if (EFI_ERROR (Status)) { - continue; - } - // - // Initialize ISA device - // - IsaAcpi->InitDevice (IsaAcpi, IsaDevice); - - // - // Set resources for this ISA device - // - Status = IsaAcpi->SetResource (IsaAcpi, IsaDevice, ResourceList); - - // - // Report Status Code here when failed to resource conflicts - // - if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) { - // - // It's hard to tell which resource conflicts - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE, - (EFI_IO_BUS_LPC | EFI_IOB_EC_RESOURCE_CONFLICT), - DevicePathData - ); - - } - // - // Set power for this ISA device - // - IsaAcpi->SetPower (IsaAcpi, IsaDevice, TRUE); - - // - // Enable this ISA device - // - IsaAcpi->EnableDevice (IsaAcpi, IsaDevice, TRUE); - - } while (TRUE); - - return EFI_SUCCESS; -} - -/** - Stop this driver on ControllerHandle. - - The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). - As a result, much of the error checking on the parameters to Stop() has been moved - into this common boot service. It is legal to call Stop() from other locations, - but the following calling restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this - same driver's Start() function. - 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid - EFI_HANDLE. In addition, all of these handles must have been created in this driver's - Start() function, and the Start() function must have called OpenProtocol() on - ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. -**/ -EFI_STATUS -EFIAPI -IsaBusControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL * This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE * ChildHandleBuffer OPTIONAL - ) -{ - EFI_STATUS Status; - UINTN Index; - BOOLEAN AllChildrenStopped; - ISA_IO_DEVICE *IsaIoDevice; - EFI_ISA_IO_PROTOCOL *IsaIo; - EFI_PCI_IO_PROTOCOL *PciIo; - - if (NumberOfChildren == 0) { - // - // Close the bus driver - // - Status = gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->CloseProtocol ( - Controller, - &gEfiIsaAcpiProtocolGuid, - This->DriverBindingHandle, - Controller - ); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; - } - // - // Complete all outstanding transactions to Controller. - // Don't allow any new transaction to Controller to be started. - // - // - // Stop all the children - // Find all the ISA devices that were discovered on this PCI to ISA Bridge - // with the Start() function. - // - AllChildrenStopped = TRUE; - - for (Index = 0; Index < NumberOfChildren; Index++) { - - Status = gBS->OpenProtocol ( - ChildHandleBuffer[Index], - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo); - - // - // Close the child handle - // - - Status = gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - ChildHandleBuffer[Index] - ); - Status = gBS->UninstallMultipleProtocolInterfaces ( - ChildHandleBuffer[Index], - &gEfiDevicePathProtocolGuid, - IsaIoDevice->DevicePath, - &gEfiIsaIoProtocolGuid, - &IsaIoDevice->IsaIo, - NULL - ); - - if (!EFI_ERROR (Status)) { - FreePool (IsaIoDevice->DevicePath); - FreePool (IsaIoDevice); - } else { - // - // Re-open PCI IO Protocol on behalf of the child device - // because of failure of destroying the child device handle - // - gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - ChildHandleBuffer[Index], - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - } - } - - if (EFI_ERROR (Status)) { - AllChildrenStopped = FALSE; - } - } - - if (!AllChildrenStopped) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -// -// Internal Function -// - -/** - Create EFI Handle for a ISA device found via ISA ACPI Protocol - - @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] Controller The handle of ISA bus controller(PCI to ISA bridge) - @param[in] PciIo The Pointer to the PCI protocol - @param[in] ParentDevicePath Device path of the ISA bus controller - @param[in] IsaDeviceResourceList The resource list of the ISA device - @param[out] ChildDevicePath The pointer to the child device. - - @retval EFI_SUCCESS The handle for the child device was created. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval EFI_DEVICE_ERROR The handle for the child device can not be created. -**/ -EFI_STATUS -IsaCreateDevice ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, - IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList, - OUT EFI_DEVICE_PATH_PROTOCOL **ChildDevicePath - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - EFI_DEV_PATH Node; - - // - // Initialize the PCI_IO_DEVICE structure - // - IsaIoDevice = AllocateZeroPool (sizeof (ISA_IO_DEVICE)); - if (IsaIoDevice == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - IsaIoDevice->Signature = ISA_IO_DEVICE_SIGNATURE; - IsaIoDevice->Handle = NULL; - IsaIoDevice->PciIo = PciIo; - - // - // Initialize the ISA I/O instance structure - // - InitializeIsaIoInstance (IsaIoDevice, IsaDeviceResourceList); - - // - // Build the child device path - // - Node.DevPath.Type = ACPI_DEVICE_PATH; - Node.DevPath.SubType = ACPI_DP; - SetDevicePathNodeLength (&Node.DevPath, sizeof (ACPI_HID_DEVICE_PATH)); - Node.Acpi.HID = IsaDeviceResourceList->Device.HID; - Node.Acpi.UID = IsaDeviceResourceList->Device.UID; - - IsaIoDevice->DevicePath = AppendDevicePathNode ( - ParentDevicePath, - &Node.DevPath - ); - - if (IsaIoDevice->DevicePath == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - *ChildDevicePath = IsaIoDevice->DevicePath; - - // - // Create a child handle and install Device Path and ISA I/O protocols - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &IsaIoDevice->Handle, - &gEfiDevicePathProtocolGuid, - IsaIoDevice->DevicePath, - &gEfiIsaIoProtocolGuid, - &IsaIoDevice->IsaIo, - NULL - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - IsaIoDevice->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - if (EFI_ERROR (Status)) { - gBS->UninstallMultipleProtocolInterfaces ( - IsaIoDevice->Handle, - &gEfiDevicePathProtocolGuid, - IsaIoDevice->DevicePath, - &gEfiIsaIoProtocolGuid, - &IsaIoDevice->IsaIo, - NULL - ); - } - -Done: - - if (EFI_ERROR (Status)) { - if (IsaIoDevice->DevicePath != NULL) { - FreePool (IsaIoDevice->DevicePath); - } - - FreePool (IsaIoDevice); - } - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf deleted file mode 100644 index be6dd43ea6..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf +++ /dev/null @@ -1,73 +0,0 @@ -## @file -# Generates ISA I/O Protocols based on the ISA ACPI Protocol instances. -# -# Discovers all the ISA Controllers and their resources by using the ISA ACPI -# Protocol, produces an instance of the ISA I/O Protocol for every ISA -# Controller found. This driver is designed to manage a PCI-to-ISA bridge Device -# such as an LPC bridge. -# -# 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 -# 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 = IsaBusDxe - MODULE_UNI_FILE = IsaBusDxe.uni - FILE_GUID = 240612B5-A063-11d4-9A3A-0090273FC14D - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializeIsaBus - -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# DRIVER_BINDING = gIsaBusControllerDriver -# COMPONENT_NAME = gIsaBusComponentName; -# COMPONENT_NAME2 = gIsaBusComponentName2; -# - -[Sources] - ComponentName.c - IsaIo.c - IsaBus.c - InternalIsaIo.h - InternalIsaBus.h - ComponentName.h - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - PcdLib - ReportStatusCodeLib - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - DevicePathLib - UefiLib - UefiDriverEntryPoint - DebugLib - -[Protocols] - gEfiIsaIoProtocolGuid ## BY_START - gEfiDevicePathProtocolGuid ## BY_START - gEfiIsaAcpiProtocolGuid ## TO_START - gEfiPciIoProtocolGuid ## TO_START - gEfiDevicePathProtocolGuid ## TO_START - gEfiGenericMemTestProtocolGuid ## TO_START - -[Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures ## CONSUMES - -[UserExtensions.TianoCore."ExtraFiles"] - IsaBusDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.uni deleted file mode 100644 index 204dc2d336..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni deleted file mode 100644 index 47d9737806..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c b/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c deleted file mode 100644 index 6f1cd1b8b1..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaIo.c +++ /dev/null @@ -1,1463 +0,0 @@ -/** @file - The implementation for EFI_ISA_IO_PROTOCOL. - -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 "InternalIsaIo.h" - -// -// Module Variables -// -EFI_ISA_IO_PROTOCOL mIsaIoInterface = { - { - IsaIoMemRead, - IsaIoMemWrite - }, - { - IsaIoIoRead, - IsaIoIoWrite - }, - IsaIoCopyMem, - IsaIoMap, - IsaIoUnmap, - IsaIoAllocateBuffer, - IsaIoFreeBuffer, - IsaIoFlush, - NULL, - 0, - NULL -}; - -EFI_ISA_DMA_REGISTERS mDmaRegisters[8] = { - { - 0x00, - 0x87, - 0x01 - }, - { - 0x02, - 0x83, - 0x03 - }, - { - 0x04, - 0x81, - 0x05 - }, - { - 0x06, - 0x82, - 0x07 - }, - { - 0x00, - 0x00, - 0x00 - }, // Channel 4 is invalid - { - 0xC4, - 0x8B, - 0xC6 - }, - { - 0xC8, - 0x89, - 0xCA - }, - { - 0xCC, - 0x8A, - 0xCE - }, -}; - -/** - Initializes an ISA I/O Instance - - @param[in] IsaIoDevice The iso device to be initialized. - @param[in] IsaDeviceResourceList The resource list. - -**/ -VOID -InitializeIsaIoInstance ( - IN ISA_IO_DEVICE *IsaIoDevice, - IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList - ) -{ - // - // Use the ISA IO Protocol structure template to initialize the ISA IO instance - // - CopyMem ( - &IsaIoDevice->IsaIo, - &mIsaIoInterface, - sizeof (EFI_ISA_IO_PROTOCOL) - ); - - IsaIoDevice->IsaIo.ResourceList = IsaDeviceResourceList; -} - -/** - Performs an ISA I/O Read Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O operation. - @param[in] Offset The offset in ISA I/O space to start the I/O operation. - @param[in] Count The number of I/O operations to perform. - @param[out] Buffer The destination buffer to store the results - - @retval EFI_SUCCESS The data was read from the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoIoRead ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - OUT VOID *Buffer - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify Isa IO Access - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeIo, - Width, - Count, - Offset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->Io.Read ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - Count, - Buffer - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Performs an ISA I/O Write Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O operation. - @param[in] Offset The offset in ISA I/O space to start the I/O operation. - @param[in] Count The number of I/O operations to perform. - @param[in] Buffer The source buffer to write data from - - @retval EFI_SUCCESS The data was writen to the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoIoWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN VOID *Buffer - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify Isa IO Access - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeIo, - Width, - Count, - Offset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->Io.Write ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - Count, - Buffer - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Writes an 8-bit I/O Port - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Offset The offset in ISA IO space to start the IO operation. - @param[in] Value The data to write port. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Parameter is invalid. - @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -WritePort ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINT32 Offset, - IN UINT8 Value - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - Status = IsaIoDevice->PciIo->Io.Write ( - IsaIoDevice->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - 1, - &Value - ); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - return Status; - } - - gBS->Stall (50); - - return EFI_SUCCESS; -} - -/** - Writes I/O operation base address and count number to a 8 bit I/O Port. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] AddrOffset The address' offset. - @param[in] PageOffset The page's offest. - @param[in] CountOffset The count's offset. - @param[in] BaseAddress The base address. - @param[in] Count The number of I/O operations to perform. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Parameter is invalid. - @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -WriteDmaPort ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINT32 AddrOffset, - IN UINT32 PageOffset, - IN UINT32 CountOffset, - IN UINT32 BaseAddress, - IN UINT16 Count - ) -{ - EFI_STATUS Status; - - Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff)); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff)); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff)); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff)); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff)); - return Status; -} - -/** - Unmaps a memory region for DMA - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). - - @retval EFI_SUCCESS The range was unmapped. - @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. -**/ -EFI_STATUS -EFIAPI -IsaIoUnmap ( - IN EFI_ISA_IO_PROTOCOL *This, - IN VOID *Mapping - ) -{ - ISA_MAP_INFO *IsaMapInfo; - - // - // Check if DMA is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { - return EFI_UNSUPPORTED; - } - - // - // See if the Map() operation associated with this Unmap() required a mapping - // buffer.If a mapping buffer was not required, then this function simply - // returns EFI_SUCCESS. - // - if (Mapping != NULL) { - // - // Get the MAP_INFO structure from Mapping - // - IsaMapInfo = (ISA_MAP_INFO *) Mapping; - - // - // If this is a write operation from the Agent's point of view, - // then copy the contents of the mapped buffer into the real buffer - // so the processor can read the contents of the real buffer. - // - if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) { - CopyMem ( - (VOID *) (UINTN) IsaMapInfo->HostAddress, - (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, - IsaMapInfo->NumberOfBytes - ); - } - // - // Free the mapped buffer and the MAP_INFO structure. - // - gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages); - FreePool (IsaMapInfo); - } - - return EFI_SUCCESS; -} - -/** - Flushes any posted write data to the system memory. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - - @retval EFI_SUCCESS The buffers were flushed. - @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. -**/ -EFI_STATUS -EFIAPI -IsaIoFlush ( - IN EFI_ISA_IO_PROTOCOL *This - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Verifies access to an ISA device - - @param[in] IsaIoDevice The ISA device to be verified. - @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. - @param[in] Width The width of the memory operation. - @param[in] Count The number of memory operations to perform. - @param[in] Offset The offset in ISA memory space to start the memory operation. - - @retval EFI_SUCCESS Verify success. - @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. - @retval EFI_UNSUPPORTED The device ont support the access type. -**/ -EFI_STATUS -IsaIoVerifyAccess ( - IN ISA_IO_DEVICE *IsaIoDevice, - IN ISA_ACCESS_TYPE Type, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINTN Count, - IN UINT32 Offset - ) -{ - EFI_ISA_ACPI_RESOURCE *Item; - EFI_STATUS Status; - - if ((UINT32)Width >= EfiIsaIoWidthMaximum || - Width == EfiIsaIoWidthReserved || - Width == EfiIsaIoWidthFifoReserved || - Width == EfiIsaIoWidthFillReserved - ) { - return EFI_INVALID_PARAMETER; - } - - // - // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX - // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX - // - if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) { - Count = 1; - } - - Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03); - - Status = EFI_UNSUPPORTED; - Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem; - while (Item->Type != EfiIsaAcpiResourceEndOfList) { - if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) || - (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) { - if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) { - return EFI_SUCCESS; - } - - if (Offset >= Item->StartRange && Offset <= Item->EndRange) { - Status = EFI_INVALID_PARAMETER; - } - } - - Item++; - } - - return Status; -} - -/** - Performs an ISA Memory Read Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory operation. - @param[in] Offset The offset in ISA memory space to start the memory operation. - @param[in] Count The number of memory operations to perform. - @param[out] Buffer The destination buffer to store the results - - @retval EFI_SUCCESS The data was read from the device successfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoMemRead ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - OUT VOID *Buffer - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - // - // Check if ISA memory is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { - return EFI_UNSUPPORTED; - } - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify the Isa Io Access - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeMem, - Width, - Count, - Offset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->Mem.Read ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - Count, - Buffer - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Performs an ISA Memory Write Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory operation. - @param[in] Offset The offset in ISA memory space to start the memory operation. - @param[in] Count The number of memory operations to perform. - @param[in] Buffer The source buffer to write data from - - @retval EFI_SUCCESS The data was written to the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoMemWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN VOID *Buffer - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - // - // Check if ISA memory is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { - return EFI_UNSUPPORTED; - } - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify Isa IO Access - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeMem, - Width, - Count, - Offset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->Mem.Write ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - Count, - Buffer - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory copy operation. - @param[in] DestOffset The offset of the destination - @param[in] SrcOffset The offset of the source - @param[in] Count The number of memory copy operations to perform - - @retval EFI_SUCCESS The data was copied sucessfully. - @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoCopyMem ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 DestOffset, - IN UINT32 SrcOffset, - IN UINTN Count - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - // - // Check if ISA memory is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { - return EFI_UNSUPPORTED; - } - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify Isa IO Access for destination and source - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeMem, - Width, - Count, - DestOffset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeMem, - Width, - Count, - SrcOffset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->CopyMem ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - DestOffset, - EFI_PCI_IO_PASS_THROUGH_BAR, - SrcOffset, - Count - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Maps a memory region for DMA, note this implementation - only supports slave read/write operation to save code size. - - @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param Operation Indicates the type of DMA (slave or bus master), and if - the DMA operation is going to read or write to system memory. - @param ChannelNumber The slave channel number to use for this DMA operation. - If Operation and ChannelAttributes shows that this device - performs bus mastering DMA, then this field is ignored. - The legal range for this field is 0..7. - @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation - @param HostAddress The system memory address to map to the device. - @param NumberOfBytes On input the number of bytes to map. On output the number - of bytes that were mapped. - @param DeviceAddress The resulting map address for the bus master device to use - to access the hosts HostAddress. - @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). - - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. - @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -IsaIoMapOnlySupportSlaveReadWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - ISA_MAP_INFO *IsaMapInfo; - UINT8 DmaMode; - UINTN MaxNumberOfBytes; - UINT32 BaseAddress; - UINT16 Count; - UINT8 DmaMask; - UINT8 DmaClear; - UINT8 DmaChannelMode; - - if ((NULL == This) || - (NULL == HostAddress) || - (NULL == NumberOfBytes) || - (NULL == DeviceAddress) || - (NULL == Mapping) - ) { - return EFI_INVALID_PARAMETER; - } - - // - // Initialize the return values to their defaults - // - *Mapping = NULL; - - // - // Make sure the Operation parameter is valid. - // Light IsaIo only supports two operations. - // - if (!(Operation == EfiIsaIoOperationSlaveRead || - Operation == EfiIsaIoOperationSlaveWrite)) { - return EFI_INVALID_PARAMETER; - } - - if (ChannelNumber >= 4) { - // - // The Light IsaIo doesn't support channelNumber larger than 4. - // - return EFI_INVALID_PARAMETER; - } - - // - // Map the HostAddress to a DeviceAddress. - // - PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; - if ((PhysicalAddress + *NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) { - // - // Common Buffer operations can not be remapped. If the common buffer - // is above 16MB, then it is not possible to generate a mapping, so return - // an error. - // - if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { - return EFI_UNSUPPORTED; - } - // - // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() - // is called later. - // - IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); - if (IsaMapInfo == NULL) { - *NumberOfBytes = 0; - return EFI_OUT_OF_RESOURCES; - } - // - // Return a pointer to the MAP_INFO structure in Mapping - // - *Mapping = IsaMapInfo; - - // - // Initialize the MAP_INFO structure - // - IsaMapInfo->Operation = Operation; - IsaMapInfo->NumberOfBytes = *NumberOfBytes; - IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); - IsaMapInfo->HostAddress = PhysicalAddress; - IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1; - - // - // Allocate a buffer below 16MB to map the transfer to. - // - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiBootServicesData, - IsaMapInfo->NumberOfPages, - &IsaMapInfo->MappedHostAddress - ); - if (EFI_ERROR (Status)) { - FreePool (IsaMapInfo); - *NumberOfBytes = 0; - *Mapping = NULL; - return Status; - } - // - // If this is a read operation from the DMA agents's point of view, - // then copy the contents of the real buffer into the mapped buffer - // so the DMA agent can read the contents of the real buffer. - // - if (Operation == EfiIsaIoOperationSlaveRead) { - CopyMem ( - (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, - (VOID *) (UINTN) IsaMapInfo->HostAddress, - IsaMapInfo->NumberOfBytes - ); - } - // - // The DeviceAddress is the address of the maped buffer below 16 MB - // - *DeviceAddress = IsaMapInfo->MappedHostAddress; - } else { - // - // The transfer is below 16 MB, so the DeviceAddress is simply the - // HostAddress - // - *DeviceAddress = PhysicalAddress; - } - - // - // Figure out what to program into the DMA Channel Mode Register - // - DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); - if (Operation == EfiIsaIoOperationSlaveRead) { - DmaMode |= V_8237_DMA_CHMODE_MEM2IO; - } else { - DmaMode |= V_8237_DMA_CHMODE_IO2MEM; - } - // - // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo - // - DmaMode |= V_8237_DMA_CHMODE_SINGLE; - - // - // A Slave DMA transfer can not cross a 64K boundary. - // Compute *NumberOfBytes based on this restriction. - // - MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); - if (*NumberOfBytes > MaxNumberOfBytes) { - *NumberOfBytes = MaxNumberOfBytes; - } - // - // Compute the values to program into the BaseAddress and Count registers - // of the Slave DMA controller - // - BaseAddress = (UINT32) (*DeviceAddress); - Count = (UINT16) (*NumberOfBytes - 1); - // - // Program the DMA Write Single Mask Register for ChannelNumber - // Clear the DMA Byte Pointer Register - // - DmaMask = R_8237_DMA_WRSMSK_CH0_3; - DmaClear = R_8237_DMA_CBPR_CH0_3; - DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; - - Status = WritePort ( - This, - DmaMask, - (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort ( - This, - DmaClear, - (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, DmaChannelMode, DmaMode); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WriteDmaPort ( - This, - mDmaRegisters[ChannelNumber].Address, - mDmaRegisters[ChannelNumber].Page, - mDmaRegisters[ChannelNumber].Count, - BaseAddress, - Count - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort ( - This, - DmaMask, - (UINT8) (ChannelNumber & 0x03) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - Maps a memory region for DMA. This implementation implement the - the full mapping support. - - @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param Operation Indicates the type of DMA (slave or bus master), and if - the DMA operation is going to read or write to system memory. - @param ChannelNumber The slave channel number to use for this DMA operation. - If Operation and ChannelAttributes shows that this device - performs bus mastering DMA, then this field is ignored. - The legal range for this field is 0..7. - @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation - @param HostAddress The system memory address to map to the device. - @param NumberOfBytes On input the number of bytes to map. On output the number - of bytes that were mapped. - @param DeviceAddress The resulting map address for the bus master device to use - to access the hosts HostAddress. - @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). - - @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. - @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. -**/ -EFI_STATUS -IsaIoMapFullSupport ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ) -{ - EFI_STATUS Status; - BOOLEAN Master; - BOOLEAN Read; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - ISA_MAP_INFO *IsaMapInfo; - UINT8 DmaMode; - UINTN MaxNumberOfBytes; - UINT32 BaseAddress; - UINT16 Count; - UINT8 DmaMask; - UINT8 DmaClear; - UINT8 DmaChannelMode; - - if ((NULL == This) || - (NULL == HostAddress) || - (NULL == NumberOfBytes) || - (NULL == DeviceAddress) || - (NULL == Mapping) - ) { - return EFI_INVALID_PARAMETER; - } - - // - // Initialize the return values to their defaults - // - *Mapping = NULL; - - // - // Make sure the Operation parameter is valid - // - if ((UINT32)Operation >= EfiIsaIoOperationMaximum) { - return EFI_INVALID_PARAMETER; - } - - if (ChannelNumber >= 8) { - return EFI_INVALID_PARAMETER; - } - - // - // See if this is a Slave DMA Operation - // - Master = TRUE; - Read = FALSE; - if (Operation == EfiIsaIoOperationSlaveRead) { - Operation = EfiIsaIoOperationBusMasterRead; - Master = FALSE; - Read = TRUE; - } - - if (Operation == EfiIsaIoOperationSlaveWrite) { - Operation = EfiIsaIoOperationBusMasterWrite; - Master = FALSE; - Read = FALSE; - } - - if (!Master) { - // - // Make sure that ChannelNumber is a valid channel number - // Channel 4 is used to cascade, so it is illegal. - // - if (ChannelNumber == 4 || ChannelNumber > 7) { - return EFI_INVALID_PARAMETER; - } - // - // This implementation only support COMPATIBLE DMA Transfers - // - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) { - return EFI_INVALID_PARAMETER; - } - - if ((ChannelAttributes & - (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A | - EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B | - EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) { - return EFI_INVALID_PARAMETER; - } - - if (ChannelNumber < 4) { - // - // If this is Channel 0..3, then the width must be 8 bit - // - if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) || - ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0) - ) { - return EFI_INVALID_PARAMETER; - } - } else { - // - // If this is Channel 4..7, then the width must be 16 bit - // - if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) || - ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) { - return EFI_INVALID_PARAMETER; - } - } - // - // Either Demand Mode or Single Mode must be selected, but not both - // - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { - return EFI_INVALID_PARAMETER; - } - } else { - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) { - return EFI_INVALID_PARAMETER; - } - } - } - // - // Map the HostAddress to a DeviceAddress. - // - PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; - if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) { - // - // Common Buffer operations can not be remapped. If the common buffer - // is above 16MB, then it is not possible to generate a mapping, so return - // an error. - // - if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { - return EFI_UNSUPPORTED; - } - // - // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() - // is called later. - // - IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); - if (IsaMapInfo == NULL) { - *NumberOfBytes = 0; - return EFI_OUT_OF_RESOURCES; - } - // - // Return a pointer to the MAP_INFO structure in Mapping - // - *Mapping = IsaMapInfo; - - // - // Initialize the MAP_INFO structure - // - IsaMapInfo->Operation = Operation; - IsaMapInfo->NumberOfBytes = *NumberOfBytes; - IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); - IsaMapInfo->HostAddress = PhysicalAddress; - IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1; - - // - // Allocate a buffer below 16MB to map the transfer to. - // - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiBootServicesData, - IsaMapInfo->NumberOfPages, - &IsaMapInfo->MappedHostAddress - ); - if (EFI_ERROR (Status)) { - FreePool (IsaMapInfo); - *NumberOfBytes = 0; - *Mapping = NULL; - return Status; - } - // - // If this is a read operation from the DMA agents's point of view, - // then copy the contents of the real buffer into the mapped buffer - // so the DMA agent can read the contents of the real buffer. - // - if (Operation == EfiIsaIoOperationBusMasterRead) { - CopyMem ( - (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, - (VOID *) (UINTN) IsaMapInfo->HostAddress, - IsaMapInfo->NumberOfBytes - ); - } - // - // The DeviceAddress is the address of the maped buffer below 16 MB - // - *DeviceAddress = IsaMapInfo->MappedHostAddress; - } else { - // - // The transfer is below 16 MB, so the DeviceAddress is simply the - // HostAddress - // - *DeviceAddress = PhysicalAddress; - } - // - // If this is a Bus Master operation then return - // - if (Master) { - return EFI_SUCCESS; - } - // - // Figure out what to program into the DMA Channel Mode Register - // - DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); - if (Read) { - DmaMode |= V_8237_DMA_CHMODE_MEM2IO; - } else { - DmaMode |= V_8237_DMA_CHMODE_IO2MEM; - } - - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) { - DmaMode |= B_8237_DMA_CHMODE_AE; - } - - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { - DmaMode |= V_8237_DMA_CHMODE_DEMAND; - } - - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { - DmaMode |= V_8237_DMA_CHMODE_SINGLE; - } - // - // A Slave DMA transfer can not cross a 64K boundary. - // Compute *NumberOfBytes based on this restriction. - // - MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); - if (*NumberOfBytes > MaxNumberOfBytes) { - *NumberOfBytes = MaxNumberOfBytes; - } - // - // Compute the values to program into the BaseAddress and Count registers - // of the Slave DMA controller - // - if (ChannelNumber < 4) { - BaseAddress = (UINT32) (*DeviceAddress); - Count = (UINT16) (*NumberOfBytes - 1); - } else { - BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1)); - Count = (UINT16) ((*NumberOfBytes - 1) >> 1); - } - // - // Program the DMA Write Single Mask Register for ChannelNumber - // Clear the DMA Byte Pointer Register - // - if (ChannelNumber < 4) { - DmaMask = R_8237_DMA_WRSMSK_CH0_3; - DmaClear = R_8237_DMA_CBPR_CH0_3; - DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; - } else { - DmaMask = R_8237_DMA_WRSMSK_CH4_7; - DmaClear = R_8237_DMA_CBPR_CH4_7; - DmaChannelMode = R_8237_DMA_CHMODE_CH4_7; - } - - Status = WritePort ( - This, - DmaMask, - (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort ( - This, - DmaClear, - (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, DmaChannelMode, DmaMode); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WriteDmaPort ( - This, - mDmaRegisters[ChannelNumber].Address, - mDmaRegisters[ChannelNumber].Page, - mDmaRegisters[ChannelNumber].Count, - BaseAddress, - Count - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort ( - This, - DmaMask, - (UINT8) (ChannelNumber & 0x03) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - Maps a memory region for DMA - - @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param Operation Indicates the type of DMA (slave or bus master), and if - the DMA operation is going to read or write to system memory. - @param ChannelNumber The slave channel number to use for this DMA operation. - If Operation and ChannelAttributes shows that this device - performs bus mastering DMA, then this field is ignored. - The legal range for this field is 0..7. - @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation - @param HostAddress The system memory address to map to the device. - @param NumberOfBytes On input the number of bytes to map. On output the number - of bytes that were mapped. - @param DeviceAddress The resulting map address for the bus master device to use - to access the hosts HostAddress. - @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). - - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. - @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -EFIAPI -IsaIoMap ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ) -{ - // - // Check if DMA is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { - return EFI_UNSUPPORTED; - } - // - // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for - // ISA Bus Master. - // - // So we just return EFI_UNSUPPORTED for these functions. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) { - return IsaIoMapOnlySupportSlaveReadWrite ( - This, - Operation, - ChannelNumber, - ChannelAttributes, - HostAddress, - NumberOfBytes, - DeviceAddress, - Mapping - ); - - } else { - return IsaIoMapFullSupport ( - This, - Operation, - ChannelNumber, - ChannelAttributes, - HostAddress, - NumberOfBytes, - DeviceAddress, - Mapping - ); - } -} - -/** - Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Type The type allocation to perform. - @param[in] MemoryType The type of memory to allocate. - @param[in] Pages The number of pages to allocate. - @param[out] HostAddress A pointer to store the base address of the allocated range. - @param[in] Attributes The requested bit mask of attributes for the allocated range. - - @retval EFI_SUCCESS The requested memory pages were allocated. - @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL - @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified - by HostAddress, Pages, and Type is not available for common buffer use. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -EFIAPI -IsaIoAllocateBuffer ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ALLOCATE_TYPE Type, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Pages, - OUT VOID **HostAddress, - IN UINT64 Attributes - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - - // - // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for - // ISA Bus Master. - // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. - // - if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || - ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { - return EFI_UNSUPPORTED; - } - - if (HostAddress == NULL) { - return EFI_INVALID_PARAMETER; - } - - if ((UINT32)Type >= MaxAllocateType) { - return EFI_INVALID_PARAMETER; - } - // - // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData - // - if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { - return EFI_INVALID_PARAMETER; - } - - if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) { - return EFI_UNSUPPORTED; - } - - PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (ISA_MAX_MEMORY_ADDRESS - 1); - if (Type == AllocateAddress) { - if ((UINTN) (*HostAddress) >= ISA_MAX_MEMORY_ADDRESS) { - return EFI_UNSUPPORTED; - } else { - PhysicalAddress = (UINTN) (*HostAddress); - } - } - - if (Type == AllocateAnyPages) { - Type = AllocateMaxAddress; - } - - Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - return Status; - } - - *HostAddress = (VOID *) (UINTN) PhysicalAddress; - return Status; -} - -/** - Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Pages The number of pages to free. - @param[in] HostAddress The base address of the allocated range. - - @retval EFI_SUCCESS The requested memory pages were freed. - @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). -**/ -EFI_STATUS -EFIAPI -IsaIoFreeBuffer ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINTN Pages, - IN VOID *HostAddress - ) -{ - EFI_STATUS Status; - - // - // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for - // ISA Bus Master. - // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. - // - if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || - ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { - return EFI_UNSUPPORTED; - } - - Status = gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, - Pages - ); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.c deleted file mode 100644 index f3341ed884..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.c +++ /dev/null @@ -1,249 +0,0 @@ -/** @file - UEFI Component Name(2) protocol implementation for Isa Floppy driver. - -Copyright (c) 2006 - 2015, Intel 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 "IsaFloppy.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaFloppyComponentName = { - IsaFloppyComponentNameGetDriverName, - IsaFloppyComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaFloppyComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaFloppyComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaFloppyComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaFloppyDriverNameTable[] = { - { - "eng;en", - L"ISA Floppy Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - @param[in] Language 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[out] DriverName 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 -IsaFloppyComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mIsaFloppyDriverNameTable, - DriverName, - (BOOLEAN)(This == &gIsaFloppyComponentName) - ); -} - -/** - 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - @param[in] 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[in] 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[in] Language 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[out] 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 -IsaFloppyComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - FDC_BLK_IO_DEV *FdcDev; - - if (Language == NULL || ControllerName == NULL) { - return EFI_INVALID_PARAMETER; - } - // - // This is a device driver, so ChildHandle must be NULL. - // - if (ChildHandle != NULL) { - return EFI_UNSUPPORTED; - } - - // - // Check if this driver is currently managing ControllerHandle - // - Status = EfiTestManagedDevice ( - ControllerHandle, - gFdcControllerDriver.DriverBindingHandle, - &gEfiIsaIoProtocolGuid - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the device context - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo, - gFdcControllerDriver.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo); - - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - FdcDev->ControllerNameTable, - ControllerName, - (BOOLEAN)(This == &gIsaFloppyComponentName) - ); -} - -/** - Add the component name for the floppy device - - @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV instance. - -**/ -VOID -AddName ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - CHAR16 FloppyDriveName[FLOPPY_DRIVE_NAME_LEN + 1]; - - if (!(FeaturePcdGet(PcdComponentNameDisable) && FeaturePcdGet(PcdComponentName2Disable))) { - StrCpyS (FloppyDriveName, FLOPPY_DRIVE_NAME_LEN + 1, FLOPPY_DRIVE_NAME); - FloppyDriveName[FLOPPY_DRIVE_NAME_LEN - 1] = (CHAR16) (L'0' + FdcDev->Disk); - - AddUnicodeString2 ( - "eng", - gIsaFloppyComponentName.SupportedLanguages, - &FdcDev->ControllerNameTable, - FloppyDriveName, - TRUE - ); - AddUnicodeString2 ( - "en", - gIsaFloppyComponentName2.SupportedLanguages, - &FdcDev->ControllerNameTable, - FloppyDriveName, - FALSE - ); - } -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.h deleted file mode 100644 index a136022ceb..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/ComponentName.h +++ /dev/null @@ -1,146 +0,0 @@ -/** @file - Header file for implementation of UEFI Component Name(2) protocol. - -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 _COMPONENT_NAME_H_ -#define _COMPONENT_NAME_H_ - -#define FLOPPY_DRIVE_NAME L"ISA Floppy Drive # " -#define FLOPPY_DRIVE_NAME_LEN ((sizeof (FLOPPY_DRIVE_NAME) / sizeof (CHAR16)) - 1) - -extern EFI_COMPONENT_NAME_PROTOCOL gIsaFloppyComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gIsaFloppyComponentName2; - -/** - 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - @param[in] Language 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[out] DriverName 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 -IsaFloppyComponentNameGetDriverName ( - 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[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - @param[in] 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[in] 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[in] Language 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[out] 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 -IsaFloppyComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - - -/** - Add the component name for the floppy device - - @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV instance. - -**/ -VOID -AddName ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c deleted file mode 100644 index 65555d3eb1..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c +++ /dev/null @@ -1,515 +0,0 @@ -/** @file - ISA Floppy Disk UEFI Driver conforming to the UEFI driver model - - 1. Support two types diskette drive - 1.44M drive and 2.88M drive (and now only support 1.44M) - 2. Support two diskette drives per floppy disk controller - 3. Use DMA channel 2 to transfer data - 4. Do not use interrupt - 5. Support diskette change line signal and write protect - -Copyright (c) 2006 - 2009, Intel 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 "IsaFloppy.h" - -LIST_ENTRY mControllerHead = INITIALIZE_LIST_HEAD_VARIABLE (mControllerHead); - -// -// ISA Floppy Driver Binding Protocol -// -EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver = { - FdcControllerDriverSupported, - FdcControllerDriverStart, - FdcControllerDriverStop, - 0xa, - NULL, - NULL -}; - - -/** - The main Entry Point for 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 -InitializeIsaFloppy( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gFdcControllerDriver, - ImageHandle, - &gIsaFloppyComponentName, - &gIsaFloppyComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} - -/** - Test if the controller is a floppy disk drive device - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] Controller The handle of the controller to test. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS The device is supported by this driver. - @retval EFI_ALREADY_STARTED The device is already being managed by this driver. - @retval EFI_ACCESS_DENIED The device is already being managed by a different driver - or an application that requires exclusive access. - @retval EFI_UNSUPPORTED The device is is not supported by this driver. -**/ -EFI_STATUS -EFIAPI -FdcControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_ISA_IO_PROTOCOL *IsaIo; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - - // - // Ignore the parameter RemainingDevicePath because this is a device driver. - // - - // - // Open the device path protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Open the ISA I/O Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Use the ISA I/O Protocol to see if Controller is a floppy disk drive device - // - Status = EFI_SUCCESS; - if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) { - Status = EFI_UNSUPPORTED; - } - // - // Close the ISA I/O Protocol - // - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Start this driver on Controller. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - This parameter is ignored by device drivers, and is optional for bus drivers. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error. - Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. -**/ -EFI_STATUS -EFIAPI -FdcControllerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - FDC_BLK_IO_DEV *FdcDev; - EFI_ISA_IO_PROTOCOL *IsaIo; - UINTN Index; - LIST_ENTRY *List; - BOOLEAN Found; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - - FdcDev = NULL; - IsaIo = NULL; - - // - // Open the device path protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Report enable progress code - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE, - ParentDevicePath - ); - - // - // Open the ISA I/O Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Allocate the floppy device's Device structure - // - FdcDev = AllocateZeroPool (sizeof (FDC_BLK_IO_DEV)); - if (FdcDev == NULL) { - goto Done; - } - // - // Initialize the floppy device's device structure - // - FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE; - FdcDev->Handle = Controller; - FdcDev->IsaIo = IsaIo; - FdcDev->Disk = (EFI_FDC_DISK) IsaIo->ResourceList->Device.UID; - FdcDev->Cache = NULL; - FdcDev->Event = NULL; - FdcDev->ControllerState = NULL; - FdcDev->DevicePath = ParentDevicePath; - - FdcDev->ControllerNameTable = NULL; - AddName (FdcDev); - - // - // Look up the base address of the Floppy Disk Controller which controls this floppy device - // - for (Index = 0; FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) { - if (FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) { - FdcDev->BaseAddress = (UINT16) FdcDev->IsaIo->ResourceList->ResourceItem[Index].StartRange; - } - } - // - // Maintain the list of floppy disk controllers - // - Found = FALSE; - List = mControllerHead.ForwardLink; - while (List != &mControllerHead) { - FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List); - if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) { - Found = TRUE; - break; - } - - List = List->ForwardLink; - } - - if (!Found) { - // - // A new floppy disk controller controlling this floppy disk drive is found - // - FdcDev->ControllerState = AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT)); - if (FdcDev->ControllerState == NULL) { - goto Done; - } - - FdcDev->ControllerState->Signature = FLOPPY_CONTROLLER_CONTEXT_SIGNATURE; - FdcDev->ControllerState->FddResetPerformed = FALSE; - FdcDev->ControllerState->NeedRecalibrate = FALSE; - FdcDev->ControllerState->BaseAddress = FdcDev->BaseAddress; - FdcDev->ControllerState->NumberOfDrive = 0; - - InsertTailList (&mControllerHead, &FdcDev->ControllerState->Link); - } - // - // Create a timer event for each floppy disk drive device. - // This timer event is used to control the motor on and off - // - Status = gBS->CreateEvent ( - EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - FddTimerProc, - FdcDev, - &FdcDev->Event - ); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Reset the Floppy Disk Controller - // - if (!FdcDev->ControllerState->FddResetPerformed) { - FdcDev->ControllerState->FddResetPerformed = TRUE; - FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev); - } - - if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT, - ParentDevicePath - ); - - // - // Discover the Floppy Drive - // - Status = DiscoverFddDevice (FdcDev); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - // - // Install protocol interfaces for the serial device. - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiBlockIoProtocolGuid, - &FdcDev->BlkIo, - NULL - ); - if (!EFI_ERROR (Status)) { - FdcDev->ControllerState->NumberOfDrive++; - } - -Done: - if (EFI_ERROR (Status)) { - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR, - ParentDevicePath - ); - - // - // If a floppy drive device structure was allocated, then free it - // - if (FdcDev != NULL) { - if (FdcDev->Event != NULL) { - // - // Close the event for turning the motor off - // - gBS->CloseEvent (FdcDev->Event); - } - - FreeUnicodeStringTable (FdcDev->ControllerNameTable); - FreePool (FdcDev); - } - - // - // Close the ISA I/O Protocol - // - if (IsaIo != NULL) { - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - } - - // - // Close the device path protocol - // - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - } - - return Status; -} - -/** - Stop this driver on ControllerHandle. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. -**/ -EFI_STATUS -EFIAPI -FdcControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - FDC_BLK_IO_DEV *FdcDev; - - // - // Ignore NumberOfChildren since this is a device driver - // - - // - // Get the Block I/O Protocol on Controller - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Get the floppy drive device's Device structure - // - FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo); - - // - // Report disable progress code - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE, - FdcDev->DevicePath - ); - - // - // Uninstall the Block I/O Protocol - // - Status = gBS->UninstallProtocolInterface ( - Controller, - &gEfiBlockIoProtocolGuid, - &FdcDev->BlkIo - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Close the event for turning the motor off - // - gBS->CloseEvent (FdcDev->Event); - - // - // Turn the motor off on the floppy drive device - // - FddTimerProc (FdcDev->Event, FdcDev); - - // - // Close the device path protocol - // - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Close the ISA I/O Protocol - // - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Free the controller list if needed - // - FdcDev->ControllerState->NumberOfDrive--; - - // - // Free the cache if one was allocated - // - FdcFreeCache (FdcDev); - - // - // Free the floppy drive device's device structure - // - FreeUnicodeStringTable (FdcDev->ControllerNameTable); - FreePool (FdcDev); - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.h b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.h deleted file mode 100644 index 30a2d7bf0c..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.h +++ /dev/null @@ -1,1093 +0,0 @@ -/** @file - Include file for ISA Floppy 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 -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 _ISA_FLOPPY_H_ -#define _ISA_FLOPPY_H_ - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver; - -#define STALL_1_SECOND 1000000 -#define STALL_1_MSECOND 1000 - -#define DATA_IN 1 -#define DATA_OUT 0 -#define READ 0 -#define WRITE 1 - -// -// Internal Data Structures -// -#define FDC_BLK_IO_DEV_SIGNATURE SIGNATURE_32 ('F', 'B', 'I', 'O') -#define FLOPPY_CONTROLLER_CONTEXT_SIGNATURE SIGNATURE_32 ('F', 'D', 'C', 'C') - -typedef enum { - FdcDisk0 = 0, - FdcDisk1 = 1, - FdcMaxDisk = 2 -} EFI_FDC_DISK; - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - BOOLEAN FddResetPerformed; - EFI_STATUS FddResetStatus; - BOOLEAN NeedRecalibrate; - UINT8 NumberOfDrive; - UINT16 BaseAddress; -} FLOPPY_CONTROLLER_CONTEXT; - -typedef struct { - UINTN Signature; - EFI_HANDLE Handle; - EFI_BLOCK_IO_PROTOCOL BlkIo; - EFI_BLOCK_IO_MEDIA BlkMedia; - - EFI_ISA_IO_PROTOCOL *IsaIo; - - UINT16 BaseAddress; - - EFI_FDC_DISK Disk; - UINT8 PresentCylinderNumber; - UINT8 *Cache; - - EFI_EVENT Event; - EFI_UNICODE_STRING_TABLE *ControllerNameTable; - FLOPPY_CONTROLLER_CONTEXT *ControllerState; - - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} FDC_BLK_IO_DEV; - -#include "ComponentName.h" - -#define FDD_BLK_IO_FROM_THIS(a) CR (a, FDC_BLK_IO_DEV, BlkIo, FDC_BLK_IO_DEV_SIGNATURE) -#define FLOPPY_CONTROLLER_FROM_LIST_ENTRY(a) \ - CR (a, \ - FLOPPY_CONTROLLER_CONTEXT, \ - Link, \ - FLOPPY_CONTROLLER_CONTEXT_SIGNATURE \ - ) - -#define DISK_1440K_EOT 0x12 -#define DISK_1440K_GPL 0x1b -#define DISK_1440K_DTL 0xff -#define DISK_1440K_NUMBER 0x02 -#define DISK_1440K_MAXTRACKNUM 0x4f -#define DISK_1440K_BYTEPERSECTOR 512 - -typedef struct { - UINT8 CommandCode; - UINT8 DiskHeadSel; - UINT8 Cylinder; - UINT8 Head; - UINT8 Sector; - UINT8 Number; - UINT8 EndOfTrack; - UINT8 GapLength; - UINT8 DataLength; -} FDD_COMMAND_PACKET1; - -typedef struct { - UINT8 CommandCode; - UINT8 DiskHeadSel; -} FDD_COMMAND_PACKET2; - -typedef struct { - UINT8 CommandCode; - UINT8 SrtHut; - UINT8 HltNd; -} FDD_SPECIFY_CMD; - -typedef struct { - UINT8 CommandCode; - UINT8 DiskHeadSel; - UINT8 NewCylinder; -} FDD_SEEK_CMD; - -typedef struct { - UINT8 CommandCode; - UINT8 DiskHeadSel; - UINT8 Cylinder; - UINT8 Head; - UINT8 Sector; - UINT8 EndOfTrack; - UINT8 GapLength; - UINT8 ScanTestPause; -} FDD_SCAN_CMD; - -typedef struct { - UINT8 Status0; - UINT8 Status1; - UINT8 Status2; - UINT8 Cylinder; - UINT8 Head; - UINT8 Sector; - UINT8 Number; -} FDD_RESULT_PACKET; - -// -// FDC Registers -// -// -// Digital Output Register address offset -// -#define FDC_REGISTER_DOR 2 - -// -// Main Status Register address offset -// -#define FDC_REGISTER_MSR 4 - -// -// Data Register address offset -// -#define FDC_REGISTER_DTR 5 - -// -// Configuration Control Register(data rate select) address offset -// -#define FDC_REGISTER_CCR 7 - -// -// Digital Input Register(diskchange) address offset -// -#define FDC_REGISTER_DIR 7 - - -// -// FDC Register Bit Definitions -// -// -// Digital Out Register(WO) -// -// -// Select Drive: 0=A 1=B -// -#define SELECT_DRV BIT0 - -// -// Reset FDC -// -#define RESET_FDC BIT2 - -// -// Enable Int & DMA -// -#define INT_DMA_ENABLE BIT3 - -// -// Turn On Drive A Motor -// -#define DRVA_MOTOR_ON BIT4 - -// -// Turn On Drive B Motor -// -#define DRVB_MOTOR_ON BIT5 - -// -// Main Status Register(RO) -// -// -// Drive A Busy -// -#define MSR_DAB BIT0 - -// -// Drive B Busy -// -#define MSR_DBB BIT1 - -// -// FDC Busy -// -#define MSR_CB BIT4 - -// -// Non-DMA Mode -// -#define MSR_NDM BIT5 - -// -// Data Input/Output -// -#define MSR_DIO BIT6 - -// -// Request For Master -// -#define MSR_RQM BIT7 - -// -// Configuration Control Register(WO) -// -// -// Data Rate select -// -#define CCR_DRC (BIT0 | BIT1) - -// -// Digital Input Register(RO) -// -// -// Disk change line -// -#define DIR_DCL BIT7 -// -// #define CCR_DCL BIT7 // Diskette change -// -// 500K -// -#define DRC_500KBS 0x0 - -// -// 300K -// -#define DRC_300KBS 0x01 - -// -// 250K -// -#define DRC_250KBS 0x02 - -// -// FDC Command Code -// -#define READ_DATA_CMD 0x06 -#define WRITE_DATA_CMD 0x05 -#define WRITE_DEL_DATA_CMD 0x09 -#define READ_DEL_DATA_CMD 0x0C -#define READ_TRACK_CMD 0x02 -#define READ_ID_CMD 0x0A -#define FORMAT_TRACK_CMD 0x0D -#define SCAN_EQU_CMD 0x11 -#define SCAN_LOW_EQU_CMD 0x19 -#define SCAN_HIGH_EQU_CMD 0x1D -#define SEEK_CMD 0x0F -#define RECALIBRATE_CMD 0x07 -#define SENSE_INT_STATUS_CMD 0x08 -#define SPECIFY_CMD 0x03 -#define SENSE_DRV_STATUS_CMD 0x04 - -// -// CMD_MT: Multi_Track Selector -// when set , this flag selects the multi-track operating mode. -// In this mode, the FDC treats a complete cylinder under head0 and 1 -// as a single track -// -#define CMD_MT BIT7 - -// -// CMD_MFM: MFM/FM Mode Selector -// A one selects the double density(MFM) mode -// A zero selects single density (FM) mode -// -#define CMD_MFM BIT6 - -// -// CMD_SK: Skip Flag -// When set to 1, sectors containing a deleted data address mark will -// automatically be skipped during the execution of Read Data. -// When set to 0, the sector is read or written the same as the read and -// write commands. -// -#define CMD_SK BIT5 - -// -// FDC Status Register Bit Definitions -// -// -// Status Register 0 -// -// -// Interrupt Code -// -#define STS0_IC (BIT7 | BIT6) - -// -// Seek End: the FDC completed a seek or recalibrate command -// -#define STS0_SE BIT5 - -// -// Equipment Check -// -#define STS0_EC BIT4 - -// -// Not Ready(unused), this bit is always 0 -// -#define STS0_NR BIT3 - -// -// Head Address: the current head address -// -#define STS0_HA BIT2 - -// -// STS0_US1 & STS0_US0: Drive Select(the current selected drive) -// -// -// Unit Select1 -// -#define STS0_US1 BIT1 - -// -// Unit Select0 -// -#define STS0_US0 BIT0 - -// -// Status Register 1 -// -// -// End of Cylinder -// -#define STS1_EN BIT7 - -// -// BIT6 is unused -// -// -// Data Error: The FDC detected a CRC error in either the ID field or -// data field of a sector -// -#define STS1_DE BIT5 - -// -// Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service -// within the required time interval -// -#define STS1_OR BIT4 - -// -// BIT3 is unused -// -// -// No data -// -#define STS1_ND BIT2 - -// -// Not Writable -// -#define STS1_NW BIT1 - -// -// Missing Address Mark -// -#define STS1_MA BIT0 - -// -// Control Mark -// -#define STS2_CM BIT6 - -// -// Data Error in Data Field: The FDC detected a CRC error in the data field -// -#define STS2_DD BIT5 - -// -// Wrong Cylinder: The track address from sector ID field is different from -// the track address maintained inside FDC -// -#define STS2_WC BIT4 - -// -// Bad Cylinder -// -#define STS2_BC BIT1 - -// -// Missing Address Mark in Data Field -// -#define STS2_MD BIT0 - -// -// Write Protected -// -#define STS3_WP BIT6 - -// -// Track 0 -// -#define STS3_T0 BIT4 - -// -// Head Address -// -#define STS3_HD BIT2 - -// -// STS3_US1 & STS3_US0 : Drive Select -// -#define STS3_US1 BIT1 -#define STS3_US0 BIT0 - -// -// Status Register 0 Interrupt Code Description -// -// -// Normal Termination of Command -// -#define IC_NT 0x0 - -// -// Abnormal Termination of Command -// -#define IC_AT 0x40 - -// -// Invalid Command -// -#define IC_IC 0x80 - -// -// Abnormal Termination caused by Polling -// -#define IC_ATRC 0xC0 - -// -// EFI Driver Binding Protocol Functions -// - -/** - Test controller is a floppy disk drive device - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] Controller The handle of the controller to test. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS The device is supported by this driver. - @retval EFI_ALREADY_STARTED The device is already being managed by this driver. - @retval EFI_ACCESS_DENIED The device is already being managed by a different driver - or an application that requires exclusive access. -**/ -EFI_STATUS -EFIAPI -FdcControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Start this driver on Controller. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - This parameter is ignored by device drivers, and is optional for bus drivers. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error. - Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. -**/ -EFI_STATUS -EFIAPI -FdcControllerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Stop this driver on ControllerHandle. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. -**/ -EFI_STATUS -EFIAPI -FdcControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// EFI Block I/O Protocol Functions -// - -/** - Reset the Floppy Logic Drive, call the FddReset function. - - @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface - @param ExtendedVerification BOOLEAN: Indicate that the driver may perform a more - exhaustive verification operation of the device during - reset, now this par is ignored in this driver - @retval EFI_SUCCESS: The Floppy Logic Drive is reset - @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly - and can not be reset - -**/ -EFI_STATUS -EFIAPI -FdcReset ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Flush block via fdd controller. - - @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface - @return EFI_SUCCESS - -**/ -EFI_STATUS -EFIAPI -FddFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ); - -/** - Read the requested number of blocks from the device. - - @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface - @param MediaId UINT32: The media id that the read request is for - @param Lba EFI_LBA: The starting logic block address to read from on the device - @param BufferSize UINTN: The size of the Buffer in bytes - @param Buffer VOID *: A pointer to the destination buffer for the data - - @retval EFI_SUCCESS: The data was read correctly from the device - @retval EFI_DEVICE_ERROR:The device reported an error while attempting to perform - the read operation - @retval EFI_NO_MEDIA: There is no media in the device - @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media - @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the - intrinsic 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 - -**/ -EFI_STATUS -EFIAPI -FddReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - Write a specified number of blocks to the device. - - @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface - @param MediaId UINT32: The media id that the write request is for - @param Lba EFI_LBA: The starting logic block address to be written - @param BufferSize UINTN: The size in bytes in Buffer - @param Buffer VOID *: A pointer to the source buffer for the data - - @retval EFI_SUCCESS: The data were written correctly to the device - @retval EFI_WRITE_PROTECTED: The device can not be written to - @retval EFI_NO_MEDIA: There is no media in the device - @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media - @retval EFI_DEVICE_ERROR: The device reported an error while attempting to perform - the write operation - @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the - intrinsic 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 -**/ -EFI_STATUS -EFIAPI -FddWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - IN VOID *Buffer - ); - -// -// Prototypes of internal functions -// -/** - - Detect the floppy drive is presented or not. - - @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV - @retval EFI_SUCCESS Drive is presented - @retval EFI_NOT_FOUND Drive is not presented - -**/ -EFI_STATUS -DiscoverFddDevice ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - - Do recalibrate and see the drive is presented or not. - Set the media parameters. - - @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV - @return the drive is presented or not - -**/ -EFI_STATUS -FddIdentify ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - - Reset the Floppy Logic Drive. - - @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV - - @retval EFI_SUCCESS: The Floppy Logic Drive is reset - @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and - can not be reset - -**/ -EFI_STATUS -FddReset ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - - Turn the drive's motor on. - The drive's motor must be on before any command can be executed. - - @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV - - @retval EFI_SUCCESS: Turn the drive's motor on successfully - @retval EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on - @retval EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer) - -**/ -EFI_STATUS -MotorOn ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - - Set a Timer and when Timer goes off, turn the motor off. - - - @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV - - @retval EFI_SUCCESS: Set the Timer successfully - @retval EFI_INVALID_PARAMETER: Fail to Set the timer - -**/ -EFI_STATUS -MotorOff ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - Detect the disk in the drive is changed or not. - - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - - @retval EFI_SUCCESS: No disk media change - @retval EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation - @retval EFI_NO_MEDIA: No disk in the drive - @retval EFI_MEDIA_CHANGED: There is a new disk in the drive -**/ -EFI_STATUS -DisketChanged ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - Do the Specify command, this command sets DMA operation - and the initial values for each of the three internal - times: HUT, SRT and HLT. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - - @retval EFI_SUCCESS: Execute the Specify command successfully - @retval EFI_DEVICE_ERROR: Fail to execute the command - -**/ -EFI_STATUS -Specify ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - Set the head of floppy drive to track 0. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - @retval EFI_SUCCESS: Execute the Recalibrate operation successfully - @retval EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation - -**/ -EFI_STATUS -Recalibrate ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - Set the head of floppy drive to the new cylinder. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - @param Lba EFI_LBA : The logic block address want to seek - - @retval EFI_SUCCESS: Execute the Seek operation successfully - @retval EFI_DEVICE_ERROR: Fail to execute the Seek operation - -**/ -EFI_STATUS -Seek ( - IN FDC_BLK_IO_DEV *FdcDev, - IN EFI_LBA Lba - ); - -/** - Do the Sense Interrupt Status command, this command resets the interrupt signal. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - @param StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC - @param PresentCylinderNumber UINT8 *: Be used to save present cylinder number - read from FDC - - @retval EFI_SUCCESS: Execute the Sense Interrupt Status command successfully - @retval EFI_DEVICE_ERROR: Fail to execute the command - -**/ -EFI_STATUS -SenseIntStatus ( - IN FDC_BLK_IO_DEV *FdcDev, - IN OUT UINT8 *StatusRegister0, - IN OUT UINT8 *PresentCylinderNumber - ); - -/** - Do the Sense Drive Status command. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - @param Lba EFI_LBA : Logic block address - - @retval EFI_SUCCESS: Execute the Sense Drive Status command successfully - @retval EFI_DEVICE_ERROR: Fail to execute the command - @retval EFI_WRITE_PROTECTED:The disk is write protected - -**/ -EFI_STATUS -SenseDrvStatus ( - IN FDC_BLK_IO_DEV *FdcDev, - IN EFI_LBA Lba - ); - -/** - Update the disk media properties and if necessary reinstall Block I/O interface. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - - @retval EFI_SUCCESS: Do the operation successfully - @retval EFI_DEVICE_ERROR: Fail to the operation - -**/ -EFI_STATUS -DetectMedia ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - Set the data rate and so on. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - - @retval EFI_SUCCESS success to set the data rate -**/ -EFI_STATUS -Setup ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -/** - Read or Write a number of blocks in the same cylinder. - - @param FdcDev A pointer to Data Structure FDC_BLK_IO_DEV - @param HostAddress device address - @param Lba The starting logic block address to read from on the device - @param NumberOfBlocks The number of block wanted to be read or write - @param Read Operation type: read or write - - @retval EFI_SUCCESS Success operate - -**/ -EFI_STATUS -ReadWriteDataSector ( - IN FDC_BLK_IO_DEV *FdcDev, - IN VOID *HostAddress, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks, - IN BOOLEAN Read - ); - -/** - Fill in FDD command's parameter. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - @param Lba The starting logic block address to read from on the device - @param Command FDD command - -**/ -VOID -FillPara ( - IN FDC_BLK_IO_DEV *FdcDev, - IN EFI_LBA Lba, - IN FDD_COMMAND_PACKET1 *Command - ); - -/** - Read result byte from Data Register of FDC. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - @param Pointer Buffer to store the byte read from FDC - - @retval EFI_SUCCESS Read result byte from FDC successfully - @retval EFI_DEVICE_ERROR The FDC is not ready to be read - -**/ -EFI_STATUS -DataInByte ( - IN FDC_BLK_IO_DEV *FdcDev, - OUT UINT8 *Pointer - ); - -/** - Write command byte to Data Register of FDC. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - @param Pointer Be used to save command byte written to FDC - - @retval EFI_SUCCESS: Write command byte to FDC successfully - @retval EFI_DEVICE_ERROR: The FDC is not ready to be written - -**/ -EFI_STATUS -DataOutByte ( - IN FDC_BLK_IO_DEV *FdcDev, - IN UINT8 *Pointer - ); - -/** - Detect the specified floppy logic drive is busy or not within a period of time. - - @param FdcDev Indicate it is drive A or drive B - @param Timeout The time period for waiting - - @retval EFI_SUCCESS: The drive and command are not busy - @retval EFI_TIMEOUT: The drive or command is still busy after a period time that - set by Timeout - -**/ -EFI_STATUS -FddWaitForBSYClear ( - IN FDC_BLK_IO_DEV *FdcDev, - IN UINTN Timeout - ); - -/** - Determine whether FDC is ready to write or read. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - @param Dio BOOLEAN: Indicate the FDC is waiting to write or read - @param Timeout The time period for waiting - - @retval EFI_SUCCESS: FDC is ready to write or read - @retval EFI_NOT_READY: FDC is not ready within the specified time period - -**/ -EFI_STATUS -FddDRQReady ( - IN FDC_BLK_IO_DEV *FdcDev, - IN BOOLEAN Dio, - IN UINTN Timeout - ); - -/** - Set FDC control structure's attribute according to result. - - @param Result Point to result structure - @param FdcDev FDC control structure - - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_SUCCESS - GC_TODO: Add description for return value - -**/ -EFI_STATUS -CheckResult ( - IN FDD_RESULT_PACKET *Result, - IN OUT FDC_BLK_IO_DEV *FdcDev - ); - -/** - Check the drive status information. - - @param StatusRegister3 the value of Status Register 3 - - @retval EFI_SUCCESS The disk is not write protected - @retval EFI_WRITE_PROTECTED: The disk is write protected - -**/ -EFI_STATUS -CheckStatus3 ( - IN UINT8 StatusRegister3 - ); - -/** - Calculate the number of block in the same cylinder according to Lba. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - @param Lba EFI_LBA: The starting logic block address - @param NumberOfBlocks UINTN: The number of blocks - - @return The number of blocks in the same cylinder which the starting - logic block address is Lba - -**/ -UINTN -GetTransferBlockCount ( - IN FDC_BLK_IO_DEV *FdcDev, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ); - -/** - When the Timer(2s) off, turn the drive's motor off. - - @param Event EFI_EVENT: Event(the timer) whose notification function is being - invoked - @param Context VOID *: Pointer to the notification function's context - -**/ -VOID -EFIAPI -FddTimerProc ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - Read I/O port for FDC. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - @param Offset The offset address of port - -**/ -UINT8 -FdcReadPort ( - IN FDC_BLK_IO_DEV *FdcDev, - IN UINT32 Offset - ); - -/** - Write I/O port for FDC. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV - @param Offset The offset address of port - @param Data Value written to port - -**/ -VOID -FdcWritePort ( - IN FDC_BLK_IO_DEV *FdcDev, - IN UINT32 Offset, - IN UINT8 Data - ); - -/** - Read or Write a number of blocks to floppy device. - - @param This Pointer to instance of EFI_BLOCK_IO_PROTOCOL - @param MediaId The media id of read/write request - @param Lba The starting logic block address to read from on the device - @param BufferSize The size of the Buffer in bytes - @param Operation - GC_TODO: add argument description - @param Buffer - GC_TODO: add argument description - - @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value - @retval EFI_SUCCESS - GC_TODO: Add description for return value - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_NO_MEDIA - GC_TODO: Add description for return value - @retval EFI_MEDIA_CHANGED - GC_TODO: Add description for return value - @retval EFI_WRITE_PROTECTED - GC_TODO: Add description for return value - @retval EFI_BAD_BUFFER_SIZE - GC_TODO: Add description for return value - @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value - @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value - @retval EFI_SUCCESS - GC_TODO: Add description for return value - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_SUCCESS - GC_TODO: Add description for return value - -**/ -EFI_STATUS -FddReadWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - IN BOOLEAN Operation, - OUT VOID *Buffer - ); - -/** - Common interface for free cache. - - @param FdcDev Pointer of FDC_BLK_IO_DEV instance - -**/ -VOID -FdcFreeCache ( - IN FDC_BLK_IO_DEV *FdcDev - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c deleted file mode 100644 index 39f0ba0191..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c +++ /dev/null @@ -1,375 +0,0 @@ -/** @file - Implementation of the EFI Block IO Protocol for ISA Floppy driver - -Copyright (c) 2006 - 2009, Intel 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 "IsaFloppy.h" - -/** - 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. -**/ -EFI_STATUS -EFIAPI -FdcReset ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - FDC_BLK_IO_DEV *FdcDev; - - // - // Reset the Floppy Disk Controller - // - FdcDev = FDD_BLK_IO_FROM_THIS (This); - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA, - FdcDev->DevicePath - ); - - return FddReset (FdcDev); -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -FddFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ) -{ - // - // Not supported yet - // - return EFI_SUCCESS; -} - -/** - Common report status code interface. - - @param This Pointer of FDC_BLK_IO_DEV instance - @param Read Read or write operation when error occurrs -**/ -VOID -FddReportStatus ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN Read - ) -{ - FDC_BLK_IO_DEV *FdcDev; - - FdcDev = FDD_BLK_IO_FROM_THIS (This); - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE, - ((Read) ? EFI_P_EC_INPUT_ERROR : EFI_P_EC_OUTPUT_ERROR) | EFI_PERIPHERAL_REMOVABLE_MEDIA, - FdcDev->DevicePath - ); -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -FddReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_STATUS Status; - - Status = FddReadWriteBlocks (This, MediaId, Lba, BufferSize, READ, Buffer); - - if (EFI_ERROR (Status)) { - FddReportStatus (This, TRUE); - } - - return Status; -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -FddWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - IN VOID *Buffer - ) -{ - EFI_STATUS Status; - - Status = FddReadWriteBlocks (This, MediaId, Lba, BufferSize, WRITE, Buffer); - - if (EFI_ERROR (Status)) { - FddReportStatus (This, FALSE); - } - - return Status; -} - -/** - Read or Write a number of blocks to floppy disk - - @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 Operation Specifies the read or write operation. - @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. - @retval EFI_WRITE_PROTECTED The device can not be written to. - -**/ -EFI_STATUS -FddReadWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - IN BOOLEAN Operation, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - FDC_BLK_IO_DEV *FdcDev; - UINTN BlockSize; - UINTN NumberOfBlocks; - UINTN BlockCount; - EFI_STATUS Status; - EFI_LBA Lba0; - UINT8 *Pointer; - - // - // Get the intrinsic block size - // - Media = This->Media; - BlockSize = Media->BlockSize; - FdcDev = FDD_BLK_IO_FROM_THIS (This); - - if (Operation == WRITE) { - if (Lba == 0) { - FdcFreeCache (FdcDev); - } - } - - // - // Set the drive motor on - // - Status = MotorOn (FdcDev); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - // - // Check to see if media can be detected - // - Status = DetectMedia (FdcDev); - if (EFI_ERROR (Status)) { - MotorOff (FdcDev); - FdcFreeCache (FdcDev); - return EFI_DEVICE_ERROR; - } - // - // Check to see if media is present - // - if (!(Media->MediaPresent)) { - MotorOff (FdcDev); - FdcFreeCache (FdcDev); - return EFI_NO_MEDIA; - } - // - // Check to see if media has been changed - // - if (MediaId != Media->MediaId) { - MotorOff (FdcDev); - FdcFreeCache (FdcDev); - return EFI_MEDIA_CHANGED; - } - - if (BufferSize == 0) { - MotorOff (FdcDev); - return EFI_SUCCESS; - } - - if (Operation == WRITE) { - if (Media->ReadOnly) { - MotorOff (FdcDev); - return EFI_WRITE_PROTECTED; - } - } - // - // Check the parameters for this read/write operation - // - if (Buffer == NULL) { - MotorOff (FdcDev); - return EFI_INVALID_PARAMETER; - } - - if (BufferSize % BlockSize != 0) { - MotorOff (FdcDev); - return EFI_BAD_BUFFER_SIZE; - } - - if (Lba > Media->LastBlock) { - MotorOff (FdcDev); - return EFI_INVALID_PARAMETER; - } - - if (((BufferSize / BlockSize) + Lba - 1) > Media->LastBlock) { - MotorOff (FdcDev); - return EFI_INVALID_PARAMETER; - } - - if (Operation == READ) { - // - // See if the data that is being read is already in the cache - // - if (FdcDev->Cache != NULL) { - if (Lba == 0 && BufferSize == BlockSize) { - MotorOff (FdcDev); - CopyMem ((UINT8 *) Buffer, (UINT8 *) FdcDev->Cache, BlockSize); - return EFI_SUCCESS; - } - } - } - // - // Set up Floppy Disk Controller - // - Status = Setup (FdcDev); - if (EFI_ERROR (Status)) { - MotorOff (FdcDev); - return EFI_DEVICE_ERROR; - } - - NumberOfBlocks = BufferSize / BlockSize; - Lba0 = Lba; - Pointer = Buffer; - - // - // read blocks in the same cylinder. - // in a cylinder , there are 18 * 2 = 36 blocks - // - BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks); - while ((BlockCount != 0) && !EFI_ERROR (Status)) { - Status = ReadWriteDataSector (FdcDev, Buffer, Lba, BlockCount, Operation); - if (EFI_ERROR (Status)) { - MotorOff (FdcDev); - FddReset (FdcDev); - return EFI_DEVICE_ERROR; - } - - Lba += BlockCount; - NumberOfBlocks -= BlockCount; - Buffer = (VOID *) ((UINTN) Buffer + BlockCount * BlockSize); - BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks); - } - - Buffer = Pointer; - - // - // Turn the motor off - // - MotorOff (FdcDev); - - if (Operation == READ) { - // - // Cache the data read - // - if (Lba0 == 0 && FdcDev->Cache == NULL) { - FdcDev->Cache = AllocateCopyPool (BlockSize, Buffer); - } - } - - return EFI_SUCCESS; - -} - -/** - Free cache for a floppy disk. - - @param FdcDev A Pointer to FDC_BLK_IO_DEV instance - -**/ -VOID -FdcFreeCache ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - if (FdcDev->Cache != NULL) { - FreePool (FdcDev->Cache); - FdcDev->Cache = NULL; - } -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c deleted file mode 100644 index 16ad6b02e3..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyCtrl.c +++ /dev/null @@ -1,1398 +0,0 @@ -/** @file - Internal floppy disk controller programming functions for the floppy 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 -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 "IsaFloppy.h" - -/** - Detect whether a floppy drive is present or not. - - @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV - - @retval EFI_SUCCESS The floppy disk drive is present - @retval EFI_NOT_FOUND The floppy disk drive is not present -**/ -EFI_STATUS -DiscoverFddDevice ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - EFI_STATUS Status; - - FdcDev->BlkIo.Media = &FdcDev->BlkMedia; - - Status = FddIdentify (FdcDev); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - - FdcDev->BlkIo.Reset = FdcReset; - FdcDev->BlkIo.FlushBlocks = FddFlushBlocks; - FdcDev->BlkIo.ReadBlocks = FddReadBlocks; - FdcDev->BlkIo.WriteBlocks = FddWriteBlocks; - FdcDev->BlkMedia.LogicalPartition = FALSE; - FdcDev->BlkMedia.WriteCaching = FALSE; - - return EFI_SUCCESS; -} - -/** - Do recalibrate and check if the drive is present or not - and set the media parameters if the driver is present. - - @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV - - @retval EFI_SUCCESS The floppy disk drive is present - @retval EFI_DEVICE_ERROR The floppy disk drive is not present -**/ -EFI_STATUS -FddIdentify ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - EFI_STATUS Status; - - // - // Set Floppy Disk Controller's motor on - // - Status = MotorOn (FdcDev); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Status = Recalibrate (FdcDev); - - if (EFI_ERROR (Status)) { - MotorOff (FdcDev); - FdcDev->ControllerState->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } - // - // Set Media Parameter - // - FdcDev->BlkIo.Media->RemovableMedia = TRUE; - FdcDev->BlkIo.Media->MediaPresent = TRUE; - FdcDev->BlkIo.Media->MediaId = 0; - - // - // Check Media - // - Status = DisketChanged (FdcDev); - - if (Status == EFI_NO_MEDIA) { - FdcDev->BlkIo.Media->MediaPresent = FALSE; - } else if ((Status != EFI_MEDIA_CHANGED) && - (Status != EFI_SUCCESS)) { - MotorOff (FdcDev); - return Status; - } - - // - // Check Disk Write Protected - // - Status = SenseDrvStatus (FdcDev, 0); - - if (Status == EFI_WRITE_PROTECTED) { - FdcDev->BlkIo.Media->ReadOnly = TRUE; - } else if (Status == EFI_SUCCESS) { - FdcDev->BlkIo.Media->ReadOnly = FALSE; - } else { - return EFI_DEVICE_ERROR; - } - - MotorOff (FdcDev); - - // - // Set Media Default Type - // - FdcDev->BlkIo.Media->BlockSize = DISK_1440K_BYTEPERSECTOR; - FdcDev->BlkIo.Media->LastBlock = DISK_1440K_EOT * 2 * (DISK_1440K_MAXTRACKNUM + 1) - 1; - - return EFI_SUCCESS; -} - -/** - Reset the Floppy Logic Drive. - - @param FdcDev FDC_BLK_IO_DEV * : A pointer to the FDC_BLK_IO_DEV - - @retval EFI_SUCCESS: The Floppy Logic Drive is reset - @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and - can not be reset - -**/ -EFI_STATUS -FddReset ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - UINT8 Data; - UINT8 StatusRegister0; - UINT8 PresentCylinderNumber; - UINTN Index; - - // - // Report reset progress code - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET, - FdcDev->DevicePath - ); - - // - // Reset specified Floppy Logic Drive according to FdcDev -> Disk - // Set Digital Output Register(DOR) to do reset work - // bit0 & bit1 of DOR : Drive Select - // bit2 : Reset bit - // bit3 : DMA and Int bit - // Reset : a "0" written to bit2 resets the FDC, this reset will remain - // active until - // a "1" is written to this bit. - // Reset step 1: - // use bit0 & bit1 to select the logic drive - // write "0" to bit2 - // - Data = 0x0; - Data = (UINT8) (Data | (SELECT_DRV & FdcDev->Disk)); - FdcWritePort (FdcDev, FDC_REGISTER_DOR, Data); - - // - // wait some time,at least 120us - // - MicroSecondDelay (500); - - // - // Reset step 2: - // write "1" to bit2 - // write "1" to bit3 : enable DMA - // - Data |= 0x0C; - FdcWritePort (FdcDev, FDC_REGISTER_DOR, Data); - - // - // Experience value - // - MicroSecondDelay (2000); - - // - // wait specified floppy logic drive is not busy - // - if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) { - return EFI_DEVICE_ERROR; - } - // - // Set the Transfer Data Rate - // - FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0); - - // - // Experience value - // - MicroSecondDelay (100); - - // - // Issue Sense interrupt command for each drive (total 4 drives) - // - for (Index = 0; Index < 4; Index++) { - if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) { - return EFI_DEVICE_ERROR; - } - } - // - // issue Specify command - // - if (EFI_ERROR (Specify (FdcDev))) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Turn the floppy disk drive's motor on. - The drive's motor must be on before any command can be executed. - - @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV - - @retval EFI_SUCCESS The drive's motor was turned on successfully - @retval EFI_DEVICE_ERROR The drive is busy, so can not turn motor on -**/ -EFI_STATUS -MotorOn ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - EFI_STATUS Status; - UINT8 DorData; - - // - // Control of the floppy drive motors is a big pain. If motor is off, you have - // to turn it on first. But you can not leave the motor on all the time, since - // that would wear out the disk. On the other hand, if you turn the motor off - // after each operation, the system performance will be awful. The compromise - // used in this driver is to leave the motor on for 2 seconds after - // each operation. If a new operation is started in that interval(2s), - // the motor need not be turned on again. If no new operation is started, - // a timer goes off and the motor is turned off - // - // - // Cancel the timer - // - Status = gBS->SetTimer (FdcDev->Event, TimerCancel, 0); - ASSERT_EFI_ERROR (Status); - - // - // Get the motor status - // - DorData = FdcReadPort (FdcDev, FDC_REGISTER_DOR); - - if (((FdcDev->Disk == FdcDisk0) && ((DorData & 0x10) == 0x10)) || - ((FdcDev->Disk == FdcDisk1) && ((DorData & 0x21) == 0x21)) - ) { - return EFI_SUCCESS; - } - // - // The drive's motor is off, so need turn it on - // first look at command and drive are busy or not - // - if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) { - return EFI_DEVICE_ERROR; - } - // - // for drive A: 1CH, drive B: 2DH - // - DorData = 0x0C; - DorData = (UINT8) (DorData | (SELECT_DRV & FdcDev->Disk)); - if (FdcDev->Disk == FdcDisk0) { - // - // drive A - // - DorData |= DRVA_MOTOR_ON; - } else { - // - // drive B - // - DorData |= DRVB_MOTOR_ON; - } - - FdcWritePort (FdcDev, FDC_REGISTER_DOR, DorData); - - // - // Experience value - // - MicroSecondDelay (4000); - - return EFI_SUCCESS; -} - -/** - Set a Timer and when Timer goes off, turn the motor off. - - @param[in] FdcDev A pointer to the FDC_BLK_IO_DEV - - @retval EFI_SUCCESS Set the Timer successfully - @retval EFI_INVALID_PARAMETER Fail to Set the timer -**/ -EFI_STATUS -MotorOff ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - // - // Set the timer : 2s - // - return gBS->SetTimer (FdcDev->Event, TimerRelative, 20000000); -} - -/** - Detect whether the disk in the drive is changed or not. - - @param[in] FdcDev A pointer to FDC_BLK_IO_DEV - - @retval EFI_SUCCESS No disk media change - @retval EFI_DEVICE_ERROR Fail to do the recalibrate or seek operation - @retval EFI_NO_MEDIA No disk in the drive - @retval EFI_MEDIA_CHANGED There is a new disk in the drive -**/ -EFI_STATUS -DisketChanged ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Check change line - // - Data = FdcReadPort (FdcDev, FDC_REGISTER_DIR); - - // - // Io delay - // - MicroSecondDelay (50); - - if ((Data & DIR_DCL) == 0x80) { - // - // disk change line is active - // - if (FdcDev->PresentCylinderNumber != 0) { - Status = Recalibrate (FdcDev); - } else { - Status = Seek (FdcDev, 0x30); - } - - if (EFI_ERROR (Status)) { - FdcDev->ControllerState->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - // - // Fail to do the seek or recalibrate operation - // - } - - Data = FdcReadPort (FdcDev, FDC_REGISTER_DIR); - - // - // Io delay - // - MicroSecondDelay (50); - - if ((Data & DIR_DCL) == 0x80) { - return EFI_NO_MEDIA; - } - - return EFI_MEDIA_CHANGED; - } - - return EFI_SUCCESS; -} - -/** - Do the Specify command, this command sets DMA operation - and the initial values for each of the three internal - times: HUT, SRT and HLT. - - @param[in] FdcDev Pointer to instance of FDC_BLK_IO_DEV - - @retval EFI_SUCCESS Execute the Specify command successfully - @retval EFI_DEVICE_ERROR Fail to execute the command -**/ -EFI_STATUS -Specify ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - FDD_SPECIFY_CMD Command; - UINTN Index; - UINT8 *CommandPointer; - - ZeroMem (&Command, sizeof (FDD_SPECIFY_CMD)); - Command.CommandCode = SPECIFY_CMD; - // - // set SRT, HUT - // - Command.SrtHut = 0xdf; - // - // 0xdf; - // - // set HLT and DMA - // - Command.HltNd = 0x02; - - CommandPointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDD_SPECIFY_CMD); Index++) { - if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { - return EFI_DEVICE_ERROR; - } - } - - return EFI_SUCCESS; -} - -/** - Set the head of floppy drive to track 0. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV - @retval EFI_SUCCESS: Execute the Recalibrate operation successfully - @retval EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation - -**/ -EFI_STATUS -Recalibrate ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - FDD_COMMAND_PACKET2 Command; - UINTN Index; - UINT8 StatusRegister0; - UINT8 PresentCylinderNumber; - UINT8 *CommandPointer; - UINT8 Count; - - Count = 2; - - while (Count > 0) { - ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2)); - Command.CommandCode = RECALIBRATE_CMD; - // - // drive select - // - if (FdcDev->Disk == FdcDisk0) { - Command.DiskHeadSel = 0; - // - // 0 - // - } else { - Command.DiskHeadSel = 1; - // - // 1 - // - } - - CommandPointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) { - if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { - return EFI_DEVICE_ERROR; - } - } - // - // Experience value - // - MicroSecondDelay (250000); - // - // need modify according to 1.44M or 2.88M - // - if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) { - return EFI_DEVICE_ERROR; - } - - if ((StatusRegister0 & 0xf0) == 0x20 && PresentCylinderNumber == 0) { - FdcDev->PresentCylinderNumber = 0; - FdcDev->ControllerState->NeedRecalibrate = FALSE; - return EFI_SUCCESS; - } else { - Count--; - if (Count == 0) { - return EFI_DEVICE_ERROR; - } - } - } - // - // end while - // - return EFI_SUCCESS; -} - -/** - Set the head of floppy drive to the new cylinder. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV - @param Lba EFI_LBA : The logic block address want to seek - - @retval EFI_SUCCESS: Execute the Seek operation successfully - @retval EFI_DEVICE_ERROR: Fail to execute the Seek operation - -**/ -EFI_STATUS -Seek ( - IN FDC_BLK_IO_DEV *FdcDev, - IN EFI_LBA Lba - ) -{ - FDD_SEEK_CMD Command; - UINT8 EndOfTrack; - UINT8 Head; - UINT8 Cylinder; - UINT8 StatusRegister0; - UINT8 *CommandPointer; - UINT8 PresentCylinderNumber; - UINTN Index; - UINT8 DelayTime; - - if (FdcDev->ControllerState->NeedRecalibrate) { - if (EFI_ERROR (Recalibrate (FdcDev))) { - FdcDev->ControllerState->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } - } - - EndOfTrack = DISK_1440K_EOT; - // - // Calculate cylinder based on Lba and EOT - // - Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2); - - // - // if the destination cylinder is the present cylinder, unnecessary to do the - // seek operation - // - if (FdcDev->PresentCylinderNumber == Cylinder) { - return EFI_SUCCESS; - } - // - // Calculate the head : 0 or 1 - // - Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); - - ZeroMem (&Command, sizeof (FDD_SEEK_CMD)); - Command.CommandCode = SEEK_CMD; - if (FdcDev->Disk == FdcDisk0) { - Command.DiskHeadSel = 0; - // - // 0 - // - } else { - Command.DiskHeadSel = 1; - // - // 1 - // - } - - Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2)); - Command.NewCylinder = Cylinder; - - CommandPointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDD_SEEK_CMD); Index++) { - if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { - return EFI_DEVICE_ERROR; - } - } - // - // Io delay - // - MicroSecondDelay (100); - - // - // Calculate waiting time - // - if (FdcDev->PresentCylinderNumber > Cylinder) { - DelayTime = (UINT8) (FdcDev->PresentCylinderNumber - Cylinder); - } else { - DelayTime = (UINT8) (Cylinder - FdcDev->PresentCylinderNumber); - } - - MicroSecondDelay ((DelayTime + 1) * 4000); - - if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) { - return EFI_DEVICE_ERROR; - } - - if ((StatusRegister0 & 0xf0) == 0x20) { - FdcDev->PresentCylinderNumber = Command.NewCylinder; - return EFI_SUCCESS; - } else { - FdcDev->ControllerState->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } -} - -/** - Do the Sense Interrupt Status command, this command - resets the interrupt signal. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV - @param StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC - @param PresentCylinderNumber UINT8 *: Be used to save present cylinder number - read from FDC - - @retval EFI_SUCCESS: Execute the Sense Interrupt Status command successfully - @retval EFI_DEVICE_ERROR: Fail to execute the command - -**/ -EFI_STATUS -SenseIntStatus ( - IN FDC_BLK_IO_DEV *FdcDev, - IN OUT UINT8 *StatusRegister0, - IN OUT UINT8 *PresentCylinderNumber - ) -{ - UINT8 Command; - - Command = SENSE_INT_STATUS_CMD; - if (EFI_ERROR (DataOutByte (FdcDev, &Command))) { - return EFI_DEVICE_ERROR; - } - - if (EFI_ERROR (DataInByte (FdcDev, StatusRegister0))) { - return EFI_DEVICE_ERROR; - } - - if (EFI_ERROR (DataInByte (FdcDev, PresentCylinderNumber))) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Do the Sense Drive Status command. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV - @param Lba EFI_LBA : Logic block address - - @retval EFI_SUCCESS: Execute the Sense Drive Status command successfully - @retval EFI_DEVICE_ERROR: Fail to execute the command - @retval EFI_WRITE_PROTECTED:The disk is write protected - -**/ -EFI_STATUS -SenseDrvStatus ( - IN FDC_BLK_IO_DEV *FdcDev, - IN EFI_LBA Lba - ) -{ - FDD_COMMAND_PACKET2 Command; - UINT8 Head; - UINT8 EndOfTrack; - UINTN Index; - UINT8 StatusRegister3; - UINT8 *CommandPointer; - - // - // Sense Drive Status command obtains drive status information, - // it has not execution phase and goes directly to the result phase from the - // command phase, Status Register 3 contains the drive status information - // - ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2)); - Command.CommandCode = SENSE_DRV_STATUS_CMD; - - if (FdcDev->Disk == FdcDisk0) { - Command.DiskHeadSel = 0; - } else { - Command.DiskHeadSel = 1; - } - - EndOfTrack = DISK_1440K_EOT; - Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); - Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2)); - - CommandPointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) { - if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { - return EFI_DEVICE_ERROR; - } - } - - if (EFI_ERROR (DataInByte (FdcDev, &StatusRegister3))) { - return EFI_DEVICE_ERROR; - } - // - // Io delay - // - MicroSecondDelay (50); - - // - // Check Status Register 3 to get drive status information - // - return CheckStatus3 (StatusRegister3); -} - -/** - Update the disk media properties and if necessary reinstall Block I/O interface. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV - - @retval EFI_SUCCESS: Do the operation successfully - @retval EFI_DEVICE_ERROR: Fail to the operation - -**/ -EFI_STATUS -DetectMedia ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - EFI_STATUS Status; - BOOLEAN Reset; - BOOLEAN ReadOnlyLastTime; - BOOLEAN MediaPresentLastTime; - - Reset = FALSE; - ReadOnlyLastTime = FdcDev->BlkIo.Media->ReadOnly; - MediaPresentLastTime = FdcDev->BlkIo.Media->MediaPresent; - - // - // Check disk change - // - Status = DisketChanged (FdcDev); - - if (Status == EFI_MEDIA_CHANGED) { - FdcDev->BlkIo.Media->MediaId++; - FdcDev->BlkIo.Media->MediaPresent = TRUE; - Reset = TRUE; - } else if (Status == EFI_NO_MEDIA) { - FdcDev->BlkIo.Media->MediaPresent = FALSE; - } else if (Status != EFI_SUCCESS) { - MotorOff (FdcDev); - return Status; - // - // EFI_DEVICE_ERROR - // - } - - if (FdcDev->BlkIo.Media->MediaPresent) { - // - // Check disk write protected - // - Status = SenseDrvStatus (FdcDev, 0); - if (Status == EFI_WRITE_PROTECTED) { - FdcDev->BlkIo.Media->ReadOnly = TRUE; - } else { - FdcDev->BlkIo.Media->ReadOnly = FALSE; - } - } - - if (FdcDev->BlkIo.Media->MediaPresent && (ReadOnlyLastTime != FdcDev->BlkIo.Media->ReadOnly)) { - Reset = TRUE; - } - - if (MediaPresentLastTime != FdcDev->BlkIo.Media->MediaPresent) { - Reset = TRUE; - } - - if (Reset) { - Status = gBS->ReinstallProtocolInterface ( - FdcDev->Handle, - &gEfiBlockIoProtocolGuid, - &FdcDev->BlkIo, - &FdcDev->BlkIo - ); - - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -} - -/** - Set the data rate and so on. - - @param FdcDev A pointer to FDC_BLK_IO_DEV - - @retval EFI_SUCCESS success to set the data rate -**/ -EFI_STATUS -Setup ( - IN FDC_BLK_IO_DEV *FdcDev - ) -{ - EFI_STATUS Status; - - // - // Set data rate 500kbs - // - FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0); - - // - // Io delay - // - MicroSecondDelay (50); - - Status = Specify (FdcDev); - - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Read or Write a number of blocks in the same cylinder. - - @param FdcDev A pointer to FDC_BLK_IO_DEV - @param HostAddress device address - @param Lba The starting logic block address to read from on the device - @param NumberOfBlocks The number of block wanted to be read or write - @param Read Operation type: read or write - - @retval EFI_SUCCESS Success operate - -**/ -EFI_STATUS -ReadWriteDataSector ( - IN FDC_BLK_IO_DEV *FdcDev, - IN VOID *HostAddress, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks, - IN BOOLEAN Read - ) -{ - EFI_STATUS Status; - FDD_COMMAND_PACKET1 Command; - FDD_RESULT_PACKET Result; - UINTN Index; - UINTN Times; - UINT8 *CommandPointer; - - EFI_PHYSICAL_ADDRESS DeviceAddress; - EFI_ISA_IO_PROTOCOL *IsaIo; - UINTN NumberofBytes; - VOID *Mapping; - EFI_ISA_IO_PROTOCOL_OPERATION Operation; - EFI_STATUS Status1; - UINT8 Channel; - EFI_ISA_ACPI_RESOURCE *ResourceItem; - UINT32 Attribute; - - Status = Seek (FdcDev, Lba); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - // - // Map Dma - // - IsaIo = FdcDev->IsaIo; - NumberofBytes = NumberOfBlocks * 512; - if (Read == READ) { - Operation = EfiIsaIoOperationSlaveWrite; - } else { - Operation = EfiIsaIoOperationSlaveRead; - } - - ResourceItem = IsaIo->ResourceList->ResourceItem; - Index = 0; - while (ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList) { - if (ResourceItem[Index].Type == EfiIsaAcpiResourceDma) { - break; - } - - Index++; - } - - if (ResourceItem[Index].Type == EfiIsaAcpiResourceEndOfList) { - return EFI_DEVICE_ERROR; - } - - Channel = (UINT8) IsaIo->ResourceList->ResourceItem[Index].StartRange; - Attribute = IsaIo->ResourceList->ResourceItem[Index].Attribute; - - Status1 = IsaIo->Map ( - IsaIo, - Operation, - Channel, - Attribute, - HostAddress, - &NumberofBytes, - &DeviceAddress, - &Mapping - ); - if (EFI_ERROR (Status1)) { - return Status1; - } - - // - // Allocate Read or Write command packet - // - ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET1)); - if (Read == READ) { - Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK; - } else { - Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM; - } - - FillPara (FdcDev, Lba, &Command); - - // - // Write command bytes to FDC - // - CommandPointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET1); Index++) { - if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) { - return EFI_DEVICE_ERROR; - } - } - // - // wait for some time - // - Times = (STALL_1_SECOND / 50) + 1; - do { - if ((FdcReadPort (FdcDev, FDC_REGISTER_MSR) & 0xc0) == 0xc0) { - break; - } - - MicroSecondDelay (50); - Times = Times - 1; - } while (Times > 0); - - if (Times == 0) { - return EFI_TIMEOUT; - } - // - // Read result bytes from FDC - // - CommandPointer = (UINT8 *) (&Result); - for (Index = 0; Index < sizeof (FDD_RESULT_PACKET); Index++) { - if (EFI_ERROR (DataInByte (FdcDev, CommandPointer++))) { - return EFI_DEVICE_ERROR; - } - } - // - // Flush before Unmap - // - if (Read == READ) { - Status1 = IsaIo->Flush (IsaIo); - if (EFI_ERROR (Status1)) { - return Status1; - } - } - // - // Unmap Dma - // - Status1 = IsaIo->Unmap (IsaIo, Mapping); - if (EFI_ERROR (Status1)) { - return Status1; - } - - return CheckResult (&Result, FdcDev); -} - -/** - Fill in FDD command's parameter. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - @param Lba The starting logic block address to read from on the device - @param Command FDD command - -**/ -VOID -FillPara ( - IN FDC_BLK_IO_DEV *FdcDev, - IN EFI_LBA Lba, - IN FDD_COMMAND_PACKET1 *Command - ) -{ - UINT8 EndOfTrack; - - // - // Get EndOfTrack from the Para table - // - EndOfTrack = DISK_1440K_EOT; - - // - // Fill the command parameter - // - if (FdcDev->Disk == FdcDisk0) { - Command->DiskHeadSel = 0; - } else { - Command->DiskHeadSel = 1; - } - - Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2); - Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); - Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1); - Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2)); - Command->Number = DISK_1440K_NUMBER; - Command->EndOfTrack = DISK_1440K_EOT; - Command->GapLength = DISK_1440K_GPL; - Command->DataLength = DISK_1440K_DTL; -} - -/** - Read result byte from Data Register of FDC. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - @param Pointer Buffer to store the byte read from FDC - - @retval EFI_SUCCESS Read result byte from FDC successfully - @retval EFI_DEVICE_ERROR The FDC is not ready to be read - -**/ -EFI_STATUS -DataInByte ( - IN FDC_BLK_IO_DEV *FdcDev, - OUT UINT8 *Pointer - ) -{ - UINT8 Data; - - // - // wait for 1ms and detect the FDC is ready to be read - // - if (EFI_ERROR (FddDRQReady (FdcDev, DATA_IN, 1))) { - return EFI_DEVICE_ERROR; - // - // is not ready - // - } - - Data = FdcReadPort (FdcDev, FDC_REGISTER_DTR); - - // - // Io delay - // - MicroSecondDelay (50); - - *Pointer = Data; - return EFI_SUCCESS; -} - -/** - Write command byte to Data Register of FDC. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - @param Pointer Be used to save command byte written to FDC - - @retval EFI_SUCCESS: Write command byte to FDC successfully - @retval EFI_DEVICE_ERROR: The FDC is not ready to be written - -**/ -EFI_STATUS -DataOutByte ( - IN FDC_BLK_IO_DEV *FdcDev, - IN UINT8 *Pointer - ) -{ - UINT8 Data; - - // - // wait for 1ms and detect the FDC is ready to be written - // - if (EFI_ERROR (FddDRQReady (FdcDev, DATA_OUT, 1))) { - // - // Not ready - // - return EFI_DEVICE_ERROR; - } - - Data = *Pointer; - - FdcWritePort (FdcDev, FDC_REGISTER_DTR, Data); - - // - // Io delay - // - MicroSecondDelay (50); - - return EFI_SUCCESS; -} - -/** - Detect the specified floppy logic drive is busy or not within a period of time. - - @param FdcDev Indicate it is drive A or drive B - @param Timeout The time period for waiting - - @retval EFI_SUCCESS: The drive and command are not busy - @retval EFI_TIMEOUT: The drive or command is still busy after a period time that - set by Timeout - -**/ -EFI_STATUS -FddWaitForBSYClear ( - IN FDC_BLK_IO_DEV *FdcDev, - IN UINTN Timeout - ) -{ - UINTN Delay; - UINT8 StatusRegister; - UINT8 Mask; - - // - // How to determine drive and command are busy or not: by the bits of - // Main Status Register - // bit0: Drive 0 busy (drive A) - // bit1: Drive 1 busy (drive B) - // bit4: Command busy - // - // - // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4 - // - Mask = (UINT8) ((FdcDev->Disk == FdcDisk0 ? MSR_DAB : MSR_DBB) | MSR_CB); - - Delay = ((Timeout * STALL_1_MSECOND) / 50) + 1; - do { - StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR); - if ((StatusRegister & Mask) == 0x00) { - break; - // - // not busy - // - } - - MicroSecondDelay (50); - Delay = Delay - 1; - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Determine whether FDC is ready to write or read. - - @param FdcDev Pointer to instance of FDC_BLK_IO_DEV - @param Dio BOOLEAN: Indicate the FDC is waiting to write or read - @param Timeout The time period for waiting - - @retval EFI_SUCCESS: FDC is ready to write or read - @retval EFI_NOT_READY: FDC is not ready within the specified time period - -**/ -EFI_STATUS -FddDRQReady ( - IN FDC_BLK_IO_DEV *FdcDev, - IN BOOLEAN Dio, - IN UINTN Timeout - ) -{ - UINTN Delay; - UINT8 StatusRegister; - UINT8 DataInOut; - - // - // Before writing to FDC or reading from FDC, the Host must examine - // the bit7(RQM) and bit6(DIO) of the Main Status Register. - // That is to say: - // command bytes can not be written to Data Register - // unless RQM is 1 and DIO is 0 - // result bytes can not be read from Data Register - // unless RQM is 1 and DIO is 1 - // - DataInOut = (UINT8) (Dio << 6); - // - // in order to compare bit6 - // - Delay = ((Timeout * STALL_1_MSECOND) / 50) + 1; - do { - StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR); - if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == DataInOut) { - break; - // - // FDC is ready - // - } - - MicroSecondDelay (50); - // - // Stall for 50 us - // - Delay = Delay - 1; - } while (Delay > 0); - - if (Delay == 0) { - return EFI_NOT_READY; - // - // FDC is not ready within the specified time period - // - } - - return EFI_SUCCESS; -} - -/** - Set FDC control structure's attribute according to result. - - @param Result Point to result structure - @param FdcDev FDC control structure - - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value - @retval EFI_SUCCESS - GC_TODO: Add description for return value - -**/ -EFI_STATUS -CheckResult ( - IN FDD_RESULT_PACKET *Result, - IN OUT FDC_BLK_IO_DEV *FdcDev - ) -{ - // - // Check Status Register0 - // - if ((Result->Status0 & STS0_IC) != IC_NT) { - if ((Result->Status0 & STS0_SE) == 0x20) { - // - // seek error - // - FdcDev->ControllerState->NeedRecalibrate = TRUE; - } - - FdcDev->ControllerState->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } - // - // Check Status Register1 - // - if ((Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) != 0) { - FdcDev->ControllerState->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } - // - // Check Status Register2 - // - if ((Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) != 0) { - FdcDev->ControllerState->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Check the drive status information. - - @param StatusRegister3 the value of Status Register 3 - - @retval EFI_SUCCESS The disk is not write protected - @retval EFI_WRITE_PROTECTED: The disk is write protected - -**/ -EFI_STATUS -CheckStatus3 ( - IN UINT8 StatusRegister3 - ) -{ - if ((StatusRegister3 & STS3_WP) != 0) { - return EFI_WRITE_PROTECTED; - } - - return EFI_SUCCESS; -} - -/** - Calculate the number of block in the same cylinder according to LBA. - - @param FdcDev FDC_BLK_IO_DEV *: A pointer to FDC_BLK_IO_DEV - @param LBA EFI_LBA: The starting logic block address - @param NumberOfBlocks UINTN: The number of blocks - - @return The number of blocks in the same cylinder which the starting - logic block address is LBA - -**/ -UINTN -GetTransferBlockCount ( - IN FDC_BLK_IO_DEV *FdcDev, - IN EFI_LBA LBA, - IN UINTN NumberOfBlocks - ) -{ - UINT8 EndOfTrack; - UINT8 Head; - UINT8 SectorsInTrack; - - // - // Calculate the number of block in the same cylinder - // - EndOfTrack = DISK_1440K_EOT; - Head = (UINT8) ((UINTN) LBA / EndOfTrack % 2); - - SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) LBA % EndOfTrack)); - if (SectorsInTrack < NumberOfBlocks) { - return SectorsInTrack; - } else { - return NumberOfBlocks; - } -} - -/** - When the Timer(2s) off, turn the drive's motor off. - - @param Event EFI_EVENT: Event(the timer) whose notification function is being - invoked - @param Context VOID *: Pointer to the notification function's context - -**/ -VOID -EFIAPI -FddTimerProc ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - FDC_BLK_IO_DEV *FdcDev; - UINT8 Data; - - FdcDev = (FDC_BLK_IO_DEV *) Context; - - // - // Get the motor status - // - Data = FdcReadPort (FdcDev, FDC_REGISTER_DOR); - - if (((FdcDev->Disk == FdcDisk0) && ((Data & 0x10) != 0x10)) || - ((FdcDev->Disk == FdcDisk1) && ((Data & 0x21) != 0x21)) - ) { - return ; - } - // - // the motor is on, so need motor off - // - Data = 0x0C; - Data = (UINT8) (Data | (SELECT_DRV & FdcDev->Disk)); - FdcWritePort (FdcDev, FDC_REGISTER_DOR, Data); - MicroSecondDelay (500); -} - -/** - Read an I/O port of FDC. - - @param[in] FdcDev A pointer to FDC_BLK_IO_DEV. - @param[in] Offset The address offset of the I/O port. - - @retval 8-bit data read from the I/O port. -**/ -UINT8 -FdcReadPort ( - IN FDC_BLK_IO_DEV *FdcDev, - IN UINT32 Offset - ) -{ - EFI_STATUS Status; - UINT8 Data; - - Status = FdcDev->IsaIo->Io.Read ( - FdcDev->IsaIo, - EfiIsaIoWidthUint8, - FdcDev->BaseAddress + Offset, - 1, - &Data - ); - ASSERT_EFI_ERROR (Status); - - return Data; -} - -/** - Write an I/O port of FDC. - - @param[in] FdcDev A pointer to FDC_BLK_IO_DEV - @param[in] Offset The address offset of the I/O port - @param[in] Data 8-bit Value written to the I/O port -**/ -VOID -FdcWritePort ( - IN FDC_BLK_IO_DEV *FdcDev, - IN UINT32 Offset, - IN UINT8 Data - ) -{ - EFI_STATUS Status; - - Status = FdcDev->IsaIo->Io.Write ( - FdcDev->IsaIo, - EfiIsaIoWidthUint8, - FdcDev->BaseAddress + Offset, - 1, - &Data - ); - ASSERT_EFI_ERROR (Status); -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf deleted file mode 100644 index 65756209f5..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf +++ /dev/null @@ -1,78 +0,0 @@ -## @file -# Provides ISA Floppy Disk support. -# -# Provides ISA Floppy Disk UEFI Driver conforming to the UEFI driver model. The -# driver provides support for two drives per controller, DMA channel 2, diskette -# change line and write protect. Currently only 1.44MB drives are supported. -# -# 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 -# 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 = IsaFloppyDxe - MODULE_UNI_FILE = IsaFloppyDxe.uni - FILE_GUID = 0abd8284-6da3-4616-971a-83a5148067ba - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializeIsaFloppy - -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# DRIVER_BINDING = gFdcControllerDriver; -# COMPONENT_NAME = gIsaFloppyComponentName; -# COMPONENT_NAME2 = gIsaFloppyComponentName2; -# -[Sources] - ComponentName.c - ComponentName.h - IsaFloppyCtrl.c - IsaFloppyBlock.c - IsaFloppy.c - IsaFloppy.h - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - ReportStatusCodeLib - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - UefiLib - BaseLib - UefiDriverEntryPoint - DebugLib - TimerLib - PcdLib - -[Protocols] - gEfiIsaIoProtocolGuid ## TO_START - gEfiBlockIoProtocolGuid ## BY_START - gEfiDevicePathProtocolGuid ## TO_START - -[FeaturePcd] - gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable ## CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable ## CONSUMES - -# -# [Event] -# ## -# # Floppy motor control timer event. -# # -# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES -# - -[UserExtensions.TianoCore."ExtraFiles"] - IsaFloppyDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni deleted file mode 100644 index b33eb0ebad..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni deleted file mode 100644 index e9e4b5bfd1..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h deleted file mode 100644 index a6a7e42aee..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/Fdc.h +++ /dev/null @@ -1,235 +0,0 @@ -/** @file -Definition of FDC registers and structures. - -Copyright (c) 2006 - 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 _PEI_RECOVERY_FDC_H_ -#define _PEI_RECOVERY_FDC_H_ - -// -// FDC Registers -// -#define FDC_REGISTER_DOR 2 //Digital Output Register -#define FDC_REGISTER_MSR 4 //Main Status Register -#define FDC_REGISTER_DTR 5 //Data Register -#define FDC_REGISTER_CCR 7 //Configuration Control Register(data rate select) -#define FDC_REGISTER_DIR 7 //Digital Input Register(diskchange) -// -// FDC Register Bit Definitions -// -// -// Digital Out Register(WO) -// -#define SELECT_DRV BIT0 // Select Drive: 0=A 1=B -#define RESET_FDC BIT2 // Reset FDC -#define INT_DMA_ENABLE BIT3 // Enable Int & DMA -#define DRVA_MOTOR_ON BIT4 // Turn On Drive A Motor -#define DRVB_MOTOR_ON BIT5 // Turn On Drive B Motor -// -// Main Status Register(RO) -// -#define MSR_DAB BIT0 // Drive A Busy -#define MSR_DBB BIT1 // Drive B Busy -#define MSR_CB BIT4 // FDC Busy -#define MSR_NDM BIT5 // Non-DMA Mode -#define MSR_DIO BIT6 // Data Input/Output -#define MSR_RQM BIT7 // Request For Master -// -// Configuration Control Register(WO) -// -#define CCR_DRC (BIT0 | BIT1) // Data Rate select -// -// Digital Input Register(RO) -// -#define DIR_DCL BIT7 // Disk change line -#define DRC_500KBS 0x0 // 500K -#define DRC_300KBS 0x01 // 300K -#define DRC_250KBS 0x02 // 250K -// -// FDC Command Code -// -#define READ_DATA_CMD 0x06 -#define SEEK_CMD 0x0F -#define RECALIBRATE_CMD 0x07 -#define SENSE_INT_STATUS_CMD 0x08 -#define SPECIFY_CMD 0x03 -#define SENSE_DRV_STATUS_CMD 0x04 - -/// -/// CMD_MT: Multi_Track Selector -/// when set , this flag selects the multi-track operating mode. -/// In this mode, the FDC treats a complete cylinder under head0 and 1 as a single track -/// -#define CMD_MT BIT7 - -/// -/// CMD_MFM: MFM/FM Mode Selector -/// A one selects the double density(MFM) mode -/// A zero selects single density (FM) mode -/// -#define CMD_MFM BIT6 - -/// -/// CMD_SK: Skip Flag -/// When set to 1, sectors containing a deleted data address mark will automatically be skipped -/// during the execution of Read Data. -/// When set to 0, the sector is read or written the same as the read and write commands. -/// -#define CMD_SK BIT5 - -// -// FDC Status Register Bit Definitions -// -// -// Status Register 0 -// -#define STS0_IC (BIT7 | BIT6) // Interrupt Code -#define STS0_SE BIT5 // Seek End: the FDC completed a seek or recalibrate command -#define STS0_EC BIT4 // Equipment Check -#define STS0_NR BIT3 // Not Ready(unused), this bit is always 0 -#define STS0_HA BIT2 // Head Address: the current head address -// -// STS0_US1 & STS0_US0: Drive Select(the current selected drive) -// -#define STS0_US1 BIT1 // Unit Select1 -#define STS0_US0 BIT0 // Unit Select0 -// -// Status Register 1 -// -#define STS1_EN BIT7 // End of Cylinder -// -// BIT6 is unused -// -#define STS1_DE BIT5 // Data Error: The FDC detected a CRC error in either the ID field or data field of a sector -#define STS1_OR BIT4 // Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service within the required time interval -// -// BIT3 is unused -// -#define STS1_ND BIT2 // No data -#define STS1_NW BIT1 // Not Writable -#define STS1_MA BIT0 // Missing Address Mark - -// -// Status Register 2 -// -// BIT7 is unused -// -#define STS2_CM BIT6 // Control Mark -#define STS2_DD BIT5 // Data Error in Data Field: The FDC detected a CRC error in the data field -#define STS2_WC BIT4 // Wrong Cylinder: The track address from sector ID field is different from the track address maintained inside FDC -// -// BIT3 is unused -// BIT2 is unused -// -#define STS2_BC BIT1 // Bad Cylinder -#define STS2_MD BIT0 // Missing Address Mark in DataField - -// -// Status Register 3 -// -// BIT7 is unused -// -#define STS3_WP BIT6 // Write Protected -// -// BIT5 is unused -// -#define STS3_T0 BIT4 // Track 0 -// -// BIT3 is unused -// -#define STS3_HD BIT2 // Head Address -// -// STS3_US1 & STS3_US0 : Drive Select -// -#define STS3_US1 BIT1 // Unit Select1 -#define STS3_US0 BIT0 // Unit Select0 - -// -// Status Register 0 Interrupt Code Description -// -#define IC_NT 0x0 // Normal Termination of Command -#define IC_AT 0x40 // Abnormal Termination of Command -#define IC_IC 0x80 // Invalid Command -#define IC_ATRC 0xC0 // Abnormal Termination caused by Polling - -/// -/// Table of parameters for diskette -/// -typedef struct { - UINT8 EndOfTrack; ///< End of track - UINT8 GapLength; ///< Gap length - UINT8 DataLength; ///< Data length - UINT8 Number; ///< Number of bytes per sector - UINT8 MaxTrackNum; - UINT8 MotorStartTime; - UINT8 MotorOffTime; - UINT8 HeadSettlingTime; - UINT8 DataTransferRate; -} DISKET_PARA_TABLE; - -/// -/// Structure for FDC Command Packet 1 -/// -typedef struct { - UINT8 CommandCode; - UINT8 DiskHeadSel; - UINT8 Cylinder; - UINT8 Head; - UINT8 Sector; - UINT8 Number; - UINT8 EndOfTrack; - UINT8 GapLength; - UINT8 DataLength; -} FDC_COMMAND_PACKET1; - -/// -/// Structure for FDC Command Packet 2 -/// -typedef struct { - UINT8 CommandCode; - UINT8 DiskHeadSel; -} FDC_COMMAND_PACKET2; - -/// -/// Structure for FDC Specify Command -/// -typedef struct { - UINT8 CommandCode; - UINT8 SrtHut; - UINT8 HltNd; -} FDC_SPECIFY_CMD; - -/// -/// Structure for FDC Seek Command -/// -typedef struct { - UINT8 CommandCode; - UINT8 DiskHeadSel; - UINT8 NewCylinder; -} FDC_SEEK_CMD; - -/// -/// Structure for FDC Result Packet -/// -typedef struct { - UINT8 Status0; - UINT8 Status1; - UINT8 Status2; - UINT8 CylinderNumber; - UINT8 HeaderAddress; - UINT8 Record; - UINT8 Number; -} FDC_RESULT_PACKET; - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.c b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.c deleted file mode 100644 index 765a46dd31..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.c +++ /dev/null @@ -1,1759 +0,0 @@ -/** @file -Floppy Peim to support Recovery function from Floppy device. - -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 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 "FloppyPeim.h" - - -PEI_DMA_TABLE mRegisterTable[] = { - // - // DMA2: Clear Byte Ptr, Enable - // - { - R_8237_DMA_CBPR_CH4_7, - 0 - }, - { - R_8237_DMA_COMMAND_CH4_7, - 0 - }, - // - // DMA1: Clear Byte Ptr, Enable - // - { - R_8237_DMA_CBPR_CH0_3, - 0 - }, - { - R_8237_DMA_COMMAND_CH0_3, - 0 - }, - // - // Configure Channel 4 for Cascade Mode - // Clear DMA Request and enable DREQ - // - { - R_8237_DMA_CHMODE_CH4_7, - V_8237_DMA_CHMODE_CASCADE | 0 - }, - { - R_8237_DMA_STA_CH4_7, - 0 - }, - { - R_8237_DMA_WRSMSK_CH4_7, - 0 - }, - // - // Configure DMA1 (Channels 0-3) for Single Mode - // Clear DMA Request and enable DREQ - // - { - R_8237_DMA_CHMODE_CH0_3, - V_8237_DMA_CHMODE_SINGLE | 0 - }, - { - R_8237_DMA_STA_CH0_3, - 0 - }, - { - R_8237_DMA_WRSMSK_CH0_3, - 0 - }, - { - R_8237_DMA_CHMODE_CH0_3, - V_8237_DMA_CHMODE_SINGLE | 1 - }, - { - R_8237_DMA_STA_CH0_3, - 1 - }, - { - R_8237_DMA_WRSMSK_CH0_3, - 1 - }, - { - R_8237_DMA_CHMODE_CH0_3, - V_8237_DMA_CHMODE_SINGLE | 2 - }, - { - R_8237_DMA_STA_CH0_3, - 2 - }, - { - R_8237_DMA_WRSMSK_CH0_3, - 2 - }, - { - R_8237_DMA_CHMODE_CH0_3, - V_8237_DMA_CHMODE_SINGLE | 3 - }, - { - R_8237_DMA_STA_CH0_3, - 3 - }, - { - R_8237_DMA_WRSMSK_CH0_3, - 3 - }, - // - // Configure DMA2 (Channels 5-7) for Single Mode - // Clear DMA Request and enable DREQ - // - { - R_8237_DMA_CHMODE_CH4_7, - V_8237_DMA_CHMODE_SINGLE | 1 - }, - { - R_8237_DMA_STA_CH4_7, - 1 - }, - { - R_8237_DMA_WRSMSK_CH4_7, - 1 - }, - { - R_8237_DMA_CHMODE_CH4_7, - V_8237_DMA_CHMODE_SINGLE | 2 - }, - { - R_8237_DMA_STA_CH4_7, - 2 - }, - { - R_8237_DMA_WRSMSK_CH4_7, - 2 - }, - { - R_8237_DMA_CHMODE_CH4_7, - V_8237_DMA_CHMODE_SINGLE | 3 - }, - { - R_8237_DMA_STA_CH4_7, - 3 - }, - { - R_8237_DMA_WRSMSK_CH4_7, - 3 - } -}; - -// -// Table of diskette parameters of various diskette types -// -DISKET_PARA_TABLE DiskPara[9] = { - { - 0x09, - 0x50, - 0xff, - 0x2, - 0x27, - 0x4, - 0x25, - 0x14, - 0x80 - }, - { - 0x09, - 0x2a, - 0xff, - 0x2, - 0x27, - 0x4, - 0x25, - 0x0f, - 0x40 - }, - { - 0x0f, - 0x54, - 0xff, - 0x2, - 0x4f, - 0x4, - 0x25, - 0x0f, - 0x0 - }, - { - 0x09, - 0x50, - 0xff, - 0x2, - 0x4f, - 0x4, - 0x25, - 0x0f, - 0x80 - }, - { - 0x09, - 0x2a, - 0xff, - 0x2, - 0x4f, - 0x4, - 0x25, - 0x0f, - 0x80 - }, - { - 0x12, - 0x1b, - 0xff, - 0x2, - 0x4f, - 0x4, - 0x25, - 0x0f, - 0x0 - }, - { - 0x09, - 0x2a, - 0xff, - 0x2, - 0x4f, - 0x4, - 0x25, - 0x0f, - 0x80 - }, - { - 0x12, - 0x1b, - 0xff, - 0x2, - 0x4f, - 0x4, - 0x25, - 0x0f, - 0x0 - }, - { - 0x24, - 0x1b, - 0xff, - 0x2, - 0x4f, - 0x4, - 0x25, - 0x0f, - 0xc0 - } -}; - -// -// Byte per sector corresponding to various device types. -// -UINTN BytePerSector[6] = { 0, 256, 512, 1024, 2048, 4096 }; - -FDC_BLK_IO_DEV mBlockIoDevTemplate = { - FDC_BLK_IO_DEV_SIGNATURE, - { - FdcGetNumberOfBlockDevices, - FdcGetBlockDeviceMediaInfo, - FdcReadBlocks, - }, - { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gEfiPeiVirtualBlockIoPpiGuid, - NULL - }, - 0, - {{0}} -}; - -/** - Wait and check if bits for DIO and RQM of FDC Main Status Register - indicates FDC is ready for read or write. - - Before writing to FDC or reading from FDC, the Host must examine - the bit7(RQM) and bit6(DIO) of the Main Status Register. - That is to say: - Command bytes can not be written to Data Register unless RQM is 1 and DIO is 0. - Result bytes can not be read from Data Register unless RQM is 1 and DIO is 1. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param DataIn Indicates data input or output. - TRUE means input. - FALSE means output. - @param TimeoutInMseconds Timeout value to wait. - - @retval EFI_SUCCESS FDC is ready. - @retval EFI_NOT_READY FDC is not ready within the specified time period. - -**/ -EFI_STATUS -FdcDRQReady ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN BOOLEAN DataIn, - IN UINTN TimeoutInMseconds - ) -{ - UINTN Delay; - UINT8 StatusRegister; - UINT8 BitInOut; - - // - // Check bit6 of Main Status Register. - // - BitInOut = 0; - if (DataIn) { - BitInOut = BIT6; - } - - Delay = ((TimeoutInMseconds * STALL_1_MSECOND) / FDC_CHECK_INTERVAL) + 1; - do { - StatusRegister = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_MSR)); - if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == BitInOut) { - // - // FDC is ready - // - break; - } - - MicroSecondDelay (FDC_SHORT_DELAY); - } while (--Delay > 0); - - if (Delay == 0) { - // - // FDC is not ready within the specified time period - // - return EFI_NOT_READY; - } - - return EFI_SUCCESS; -} - -/** - Read a byte from FDC data register. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param Pointer Pointer to buffer to hold data read from FDC. - - @retval EFI_SUCCESS Byte successfully read. - @retval EFI_DEVICE_ERROR FDC is not ready. - -**/ -EFI_STATUS -DataInByte ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - OUT UINT8 *Pointer - ) -{ - UINT8 Data; - - // - // Wait for 1ms and detect the FDC is ready to be read - // - if (FdcDRQReady (FdcBlkIoDev, TRUE, 1) != EFI_SUCCESS) { - // - // FDC is not ready. - // - return EFI_DEVICE_ERROR; - } - - Data = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DTR)); - MicroSecondDelay (FDC_SHORT_DELAY); - *Pointer = Data; - - return EFI_SUCCESS; -} - -/** - Write a byte to FDC data register. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param Pointer Pointer to data to write. - - @retval EFI_SUCCESS Byte successfully written. - @retval EFI_DEVICE_ERROR FDC is not ready. - -**/ -EFI_STATUS -DataOutByte ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN UINT8 *Pointer - ) -{ - UINT8 Data; - - // - // Wait for 1ms and detect the FDC is ready to be written - // - if (FdcDRQReady (FdcBlkIoDev, FALSE, 1) != EFI_SUCCESS) { - // - // FDC is not ready. - // - return EFI_DEVICE_ERROR; - } - - Data = *Pointer; - IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DTR), Data); - MicroSecondDelay (FDC_SHORT_DELAY); - - return EFI_SUCCESS; -} - -/** - Get Sts0 and Pcn status from FDC - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV - @param Sts0 Value of Sts0 - @param Pcn Value of Pcn - - @retval EFI_SUCCESS Successfully retrieved status value of Sts0 and Pcn. - @retval EFI_DEVICE_ERROR Fail to send SENSE_INT_STATUS_CMD. - @retval EFI_DEVICE_ERROR Fail to read Sts0. - @retval EFI_DEVICE_ERROR Fail to read Pcn. - -**/ -EFI_STATUS -SenseIntStatus ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - OUT UINT8 *Sts0, - OUT UINT8 *Pcn - ) -{ - UINT8 Command; - - Command = SENSE_INT_STATUS_CMD; - - if (DataOutByte (FdcBlkIoDev, &Command) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - if (DataInByte (FdcBlkIoDev, Sts0) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - if (DataInByte (FdcBlkIoDev, Pcn) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Issue Specify command. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - - @retval EFI_SUCCESS Specify command successfully issued. - @retval EFI_DEVICE_ERROR FDC device has errors. - -**/ -EFI_STATUS -Specify ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev - ) -{ - FDC_SPECIFY_CMD Command; - UINTN Index; - UINT8 *Pointer; - - ZeroMem (&Command, sizeof (FDC_SPECIFY_CMD)); - Command.CommandCode = SPECIFY_CMD; - // - // set SRT, HUT - // - Command.SrtHut = 0xdf; - // - // 0xdf; - // set HLT and DMA - // - Command.HltNd = 0x02; - - Pointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDC_SPECIFY_CMD); Index++) { - if (DataOutByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - } - - return EFI_SUCCESS; -} - -/** - Wait until busy bit is cleared. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param DevPos Position of FDC (Driver A or B) - @param TimeoutInMseconds Timeout value to wait. - - @retval EFI_SUCCESS Busy bit has been cleared before timeout. - @retval EFI_TIMEOUT Time goes out before busy bit is cleared. - -**/ -EFI_STATUS -FdcWaitForBSYClear ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN UINT8 DevPos, - IN UINTN TimeoutInMseconds - ) -{ - UINTN Delay; - UINT8 StatusRegister; - UINT8 Mask; - - // - // How to determine drive and command are busy or not: by the bits of Main Status Register - // bit0: Drive 0 busy (drive A) - // bit1: Drive 1 busy (drive B) - // bit4: Command busy - // - // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4 - // - Mask = (UINT8) ((DevPos == 0 ? MSR_DAB : MSR_DBB) | MSR_CB); - - Delay = ((TimeoutInMseconds * STALL_1_MSECOND) / FDC_CHECK_INTERVAL) + 1; - - do { - StatusRegister = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_MSR)); - - if ((StatusRegister & Mask) == 0x00) { - // - // not busy - // - break; - } - - MicroSecondDelay (FDC_SHORT_DELAY); - } while (--Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Reset FDC device. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV - @param DevPos Index of FDC device. - - @retval EFI_SUCCESS FDC device successfully reset. - @retval EFI_DEVICE_ERROR Fail to reset FDC device. - -**/ -EFI_STATUS -FdcReset ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN UINT8 DevPos - ) -{ - UINT8 Data; - UINT8 Sts0; - UINT8 Pcn; - UINTN Index; - - // - // Reset specified Floppy Logic Drive according to Fdd -> Disk - // Set Digital Output Register(DOR) to do reset work - // bit0 & bit1 of DOR : Drive Select - // bit2 : Reset bit - // bit3 : DMA and Int bit - // Reset : A "0" written to bit2 resets the FDC, this reset will remain active until - // a "1" is written to this bit. - // Reset step 1: - // use bit0 & bit1 to select the logic drive - // write "0" to bit2 - // - Data = 0x0; - Data = (UINT8) (Data | (SELECT_DRV & DevPos)); - IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DOR), Data); - - // - // Wait some time, at least 120us. - // - MicroSecondDelay (FDC_RESET_DELAY); - // - // Reset step 2: - // write "1" to bit2 - // write "1" to bit3 : enable DMA - // - Data |= 0x0C; - IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DOR), Data); - - MicroSecondDelay (FDC_RESET_DELAY); - - // - // Wait until specified floppy logic drive is not busy - // - if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // Set the Transfer Data Rate - // - IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_CCR), 0x0); - - MicroSecondDelay (FDC_MEDIUM_DELAY); - - // - // Issue Sense interrupt command for each drive (totally 4 drives) - // - for (Index = 0; Index < 4; Index++) { - if (SenseIntStatus (FdcBlkIoDev, &Sts0, &Pcn) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - } - // - // Issue Specify command - // - if (Specify (FdcBlkIoDev) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Turn on the motor of floppy drive. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param Info Information of floppy device. - - @retval EFI_SUCCESS Motor is successfully turned on. - @retval EFI_SUCCESS Motor is already on. - @retval EFI_DEVICE_ERROR Busy bit of FDC cannot be cleared. - -**/ -EFI_STATUS -MotorOn ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN OUT PEI_FLOPPY_DEVICE_INFO *Info - ) -{ - UINT8 Data; - UINT8 DevPos; - - // - // Control of the floppy drive motors is a big pain. If motor is off, you have to turn it - // on first. But you can not leave the motor on all the time, since that would wear out the - // disk. On the other hand, if you turn the motor off after each operation, the system performance - // will be awful. The compromise used in this driver is to leave the motor on for 2 seconds after - // each operation. If a new operation is started in that interval(2s), the motor need not be - // turned on again. If no new operation is started, a timer goes off and the motor is turned off. - // - DevPos = Info->DevPos; - - // - // If the Motor is already on, just return EFI_SUCCESS. - // - if (Info->MotorOn) { - return EFI_SUCCESS; - } - // - // The drive's motor is off, so need turn it on. - // First check if command and drive are busy or not. - // - if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // for drive A: 1CH, drive B: 2DH - // - Data = 0x0C; - Data = (UINT8) (Data | (SELECT_DRV & DevPos)); - if (DevPos == 0) { - Data |= DRVA_MOTOR_ON; - } else { - Data |= DRVB_MOTOR_ON; - } - - Info->MotorOn = FALSE; - - // - // Turn on the motor and wait for some time to ensure it takes effect. - // - IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DOR), Data); - MicroSecondDelay (FDC_LONG_DELAY); - - Info->MotorOn = TRUE; - - return EFI_SUCCESS; -} - -/** - Turn off the motor of floppy drive. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param Info Information of floppy device. - -**/ -VOID -MotorOff ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN OUT PEI_FLOPPY_DEVICE_INFO *Info - ) -{ - UINT8 Data; - UINT8 DevPos; - - DevPos = Info->DevPos; - - if (!Info->MotorOn) { - return; - } - // - // The motor is on, so need motor off - // - Data = 0x0C; - Data = (UINT8) (Data | (SELECT_DRV & DevPos)); - - IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DOR), Data); - MicroSecondDelay (FDC_SHORT_DELAY); - - Info->MotorOn = FALSE; -} - -/** - Recalibrate the FDC device. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param Info Information of floppy device. - - @retval EFI_SUCCESS FDC successfully recalibrated. - @retval EFI_DEVICE_ERROR Fail to send RECALIBRATE_CMD. - @retval EFI_DEVICE_ERROR Fail to get status value of Sts0 and Pcn. - @retval EFI_DEVICE_ERROR Fail to recalibrate FDC device. - -**/ -EFI_STATUS -Recalibrate ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN OUT PEI_FLOPPY_DEVICE_INFO *Info - ) -{ - FDC_COMMAND_PACKET2 Command; - UINTN Index; - UINT8 Sts0; - UINT8 Pcn; - UINT8 *Pointer; - UINT8 Count; - UINT8 DevPos; - - DevPos = Info->DevPos; - - // - // We would try twice. - // - Count = 2; - while (Count > 0) { - ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET2)); - Command.CommandCode = RECALIBRATE_CMD; - // - // drive select - // - if (DevPos == 0) { - Command.DiskHeadSel = 0; - } else { - Command.DiskHeadSel = 1; - } - - Pointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDC_COMMAND_PACKET2); Index++) { - if (DataOutByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - } - - MicroSecondDelay (FDC_RECALIBRATE_DELAY); - - if (SenseIntStatus (FdcBlkIoDev, &Sts0, &Pcn) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - if ((Sts0 & 0xf0) == BIT5 && Pcn == 0) { - // - // Recalibration is successful. - // - Info->Pcn = 0; - Info->NeedRecalibrate = FALSE; - - return EFI_SUCCESS; - } else { - // - // Recalibration is not successful. Try again. - // If trial is used out, return EFI_DEVICE_ERROR. - // - Count--; - if (Count == 0) { - return EFI_DEVICE_ERROR; - } - } - } - - return EFI_SUCCESS; -} - -/** - Seek for the cylinder according to given LBA. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param Info Information of floppy device. - @param Lba LBA for which to seek for cylinder. - - @retval EFI_SUCCESS Successfully moved to the destination cylinder. - @retval EFI_SUCCESS Destination cylinder is just the present cylinder. - @retval EFI_DEVICE_ERROR Fail to move to the destination cylinder. - -**/ -EFI_STATUS -Seek ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN OUT PEI_FLOPPY_DEVICE_INFO *Info, - IN EFI_PEI_LBA Lba - ) -{ - FDC_SEEK_CMD Command; - DISKET_PARA_TABLE *Para; - UINT8 EndOfTrack; - UINT8 Head; - UINT8 Cylinder; - UINT8 Sts0; - UINT8 *Pointer; - UINT8 Pcn; - UINTN Index; - UINT8 Gap; - UINT8 DevPos; - - DevPos = Info->DevPos; - if (Info->NeedRecalibrate) { - if (Recalibrate (FdcBlkIoDev, Info) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // Recalibrate Success - // - Info->NeedRecalibrate = FALSE; - } - - // - // Get the base of disk parameter information corresponding to its type. - // - Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type); - EndOfTrack = Para->EndOfTrack; - // - // Calculate cylinder based on Lba and EOT - // - Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2); - - // - // If the dest cylinder is the present cylinder, unnecessary to do the seek operation - // - if (Info->Pcn == Cylinder) { - return EFI_SUCCESS; - } - - // - // Calculate the head : 0 or 1 - // - Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); - - ZeroMem (&Command, sizeof (FDC_SEEK_CMD)); - Command.CommandCode = SEEK_CMD; - if (DevPos == 0) { - Command.DiskHeadSel = 0; - } else { - Command.DiskHeadSel = 1; - } - - // - // Send command to move to destination cylinder. - // - Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2)); - Command.NewCylinder = Cylinder; - - Pointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDC_SEEK_CMD); Index++) { - if (DataOutByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - } - - MicroSecondDelay (FDC_SHORT_DELAY); - - // - // Calculate waiting time, which is proportional to the gap between destination - // cylinder and present cylinder. - // - if (Info->Pcn > Cylinder) { - Gap = (UINT8) (Info->Pcn - Cylinder); - } else { - Gap = (UINT8) (Cylinder - Info->Pcn); - } - - MicroSecondDelay ((Gap + 1) * FDC_LONG_DELAY); - - // - // Confirm if the new cylinder is the destination and status is correct. - // - if (SenseIntStatus (FdcBlkIoDev, &Sts0, &Pcn) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - if ((Sts0 & 0xf0) == BIT5) { - Info->Pcn = Command.NewCylinder; - Info->NeedRecalibrate = FALSE; - return EFI_SUCCESS; - } else { - Info->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } -} - -/** - Check if diskette is changed. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV - @param Info Information of floppy device. - - @retval EFI_SUCCESS Diskette is not changed. - @retval EFI_MEDIA_CHANGED Diskette is changed. - @retval EFI_NO_MEDIA No diskette. - @retval EFI_DEVICE_ERROR Fail to do the seek or recalibrate operation. - -**/ -EFI_STATUS -DisketChanged ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN OUT PEI_FLOPPY_DEVICE_INFO *Info - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Check change line - // - Data = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DIR)); - - MicroSecondDelay (FDC_SHORT_DELAY); - - if ((Data & DIR_DCL) == DIR_DCL) { - if (Info->Pcn != 0) { - Status = Recalibrate (FdcBlkIoDev, Info); - } else { - Status = Seek (FdcBlkIoDev, Info, 0x30); - } - - if (Status != EFI_SUCCESS) { - // - // Fail to do the seek or recalibrate operation - // - return EFI_DEVICE_ERROR; - } - - Data = IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_DIR)); - - MicroSecondDelay (FDC_SHORT_DELAY); - - if ((Data & DIR_DCL) == DIR_DCL) { - return EFI_NO_MEDIA; - } - - return EFI_MEDIA_CHANGED; - } - - return EFI_SUCCESS; -} - -/** - Detects if FDC device exists. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV - @param Info Information of floppy device. - @param MediaInfo Information of floppy media. - - @retval TRUE FDC device exists and is working properly. - @retval FALSE FDC device does not exist or cannot work properly. - -**/ -BOOLEAN -DiscoverFdcDevice ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN OUT PEI_FLOPPY_DEVICE_INFO *Info, - OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo - ) -{ - EFI_STATUS Status; - DISKET_PARA_TABLE *Para; - - Status = MotorOn (FdcBlkIoDev, Info); - if (Status != EFI_SUCCESS) { - return FALSE; - } - - Status = Recalibrate (FdcBlkIoDev, Info); - - if (Status != EFI_SUCCESS) { - MotorOff (FdcBlkIoDev, Info); - return FALSE; - } - // - // Set Media Parameter - // - MediaInfo->DeviceType = LegacyFloppy; - MediaInfo->MediaPresent = TRUE; - - // - // Check Media - // - Status = DisketChanged (FdcBlkIoDev, Info); - if (Status == EFI_NO_MEDIA) { - // - // No diskette in floppy. - // - MediaInfo->MediaPresent = FALSE; - } else if (Status != EFI_MEDIA_CHANGED && Status != EFI_SUCCESS) { - // - // EFI_DEVICE_ERROR - // - MotorOff (FdcBlkIoDev, Info); - return FALSE; - } - - MotorOff (FdcBlkIoDev, Info); - - // - // Get the base of disk parameter information corresponding to its type. - // - Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type); - - MediaInfo->BlockSize = BytePerSector[Para->Number]; - MediaInfo->LastBlock = Para->EndOfTrack * 2 * (Para->MaxTrackNum + 1) - 1; - - return TRUE; -} - -/** - Enumerate floppy device - - @param FdcBlkIoDev Instance of floppy device controller - - @return Number of FDC devices. - -**/ -UINT8 -FdcEnumeration ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev - ) -{ - UINT8 DevPos; - UINT8 DevNo; - EFI_PEI_BLOCK_IO_MEDIA MediaInfo; - EFI_STATUS Status; - - DevNo = 0; - - // - // DevPos=0 means Drive A, 1 means Drive B. - // - for (DevPos = 0; DevPos < 2; DevPos++) { - // - // Detecting device presence - // - REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_PRESENCE_DETECT); - - // - // Reset FDC - // - Status = FdcReset (FdcBlkIoDev, DevPos); - - if (EFI_ERROR (Status)) { - continue; - } - - FdcBlkIoDev->DeviceInfo[DevPos].DevPos = DevPos; - FdcBlkIoDev->DeviceInfo[DevPos].Pcn = 0; - FdcBlkIoDev->DeviceInfo[DevPos].MotorOn = FALSE; - FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate = TRUE; - FdcBlkIoDev->DeviceInfo[DevPos].Type = FdcType1440K1440K; - - // - // Discover FDC device - // - if (DiscoverFdcDevice (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DevPos]), &MediaInfo)) { - FdcBlkIoDev->DeviceInfo[DevNo].DevPos = DevPos; - - FdcBlkIoDev->DeviceInfo[DevNo].Pcn = FdcBlkIoDev->DeviceInfo[DevPos].Pcn; - FdcBlkIoDev->DeviceInfo[DevNo].MotorOn = FdcBlkIoDev->DeviceInfo[DevPos].MotorOn; - FdcBlkIoDev->DeviceInfo[DevNo].NeedRecalibrate = FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate; - FdcBlkIoDev->DeviceInfo[DevNo].Type = FdcBlkIoDev->DeviceInfo[DevPos].Type; - - CopyMem ( - &(FdcBlkIoDev->DeviceInfo[DevNo].MediaInfo), - &MediaInfo, - sizeof (EFI_PEI_BLOCK_IO_MEDIA) - ); - - DevNo++; - } else { - // - // Assume controller error - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_EC_CONTROLLER_ERROR - ); - } - } - - FdcBlkIoDev->DeviceCount = DevNo; - return DevNo; -} - -/** - Checks result reflected by FDC_RESULT_PACKET. - - @param Result FDC_RESULT_PACKET read from FDC after certain operation. - @param Info Information of floppy device. - - @retval EFI_SUCCESS Result is healthy. - @retval EFI_DEVICE_ERROR Result is not healthy. - -**/ -EFI_STATUS -CheckResult ( - IN FDC_RESULT_PACKET *Result, - OUT PEI_FLOPPY_DEVICE_INFO *Info - ) -{ - if ((Result->Status0 & STS0_IC) != IC_NT) { - if ((Result->Status0 & STS0_SE) == BIT5) { - // - // Seek error - // - Info->NeedRecalibrate = TRUE; - } - - Info->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } - // - // Check Status Register1 - // - if ((Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) != 0) { - Info->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } - // - // Check Status Register2 - // - if ((Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) != 0) { - Info->NeedRecalibrate = TRUE; - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Fill parameters for command packet. - - @param Info Information of floppy device. - @param Lba Logical block address. - @param Command Command for which for fill parameters. - -**/ -VOID -FillPara ( - IN PEI_FLOPPY_DEVICE_INFO *Info, - IN EFI_PEI_LBA Lba, - OUT FDC_COMMAND_PACKET1 *Command - ) -{ - DISKET_PARA_TABLE *Para; - UINT8 EndOfTrack; - UINT8 DevPos; - - DevPos = Info->DevPos; - - // - // Get the base of disk parameter information corresponding to its type. - // - Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type); - - EndOfTrack = Para->EndOfTrack; - - if (DevPos == 0) { - Command->DiskHeadSel = 0; - } else { - Command->DiskHeadSel = 1; - } - - Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2); - Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); - Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1); - Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2)); - Command->Number = Para->Number; - Command->EndOfTrack = Para->EndOfTrack; - Command->GapLength = Para->GapLength; - Command->DataLength = Para->DataLength; -} - -/** - Setup specifed FDC device. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param DevPos Index of FDC device. - - @retval EFI_SUCCESS FDC device successfully set up. - @retval EFI_DEVICE_ERROR FDC device has errors. - -**/ -EFI_STATUS -Setup ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN UINT8 DevPos - ) -{ - EFI_STATUS Status; - - IoWrite8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_CCR), 0x0); - - MicroSecondDelay (FDC_MEDIUM_DELAY); - - Status = Specify (FdcBlkIoDev); - return Status; -} - -/** - Setup DMA channels to read data. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param Buffer Memory buffer for DMA transfer. - @param BlockSize the number of the bytes in one block. - @param NumberOfBlocks Number of blocks to read. - -**/ -VOID -SetDMA ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN VOID *Buffer, - IN UINTN BlockSize, - IN UINTN NumberOfBlocks - ) -{ - UINT8 Data; - UINTN Count; - - // - // Mask DMA channel 2; - // - IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, B_8237_DMA_WRSMSK_CMS | 2); - - // - // Clear first/last flip flop - // - IoWrite8 (R_8237_DMA_CBPR_CH0_3, B_8237_DMA_WRSMSK_CMS | 2); - - // - // Set mode - // - IoWrite8 (R_8237_DMA_CHMODE_CH0_3, V_8237_DMA_CHMODE_SINGLE | V_8237_DMA_CHMODE_IO2MEM | 2); - - // - // Set base address and page register - // - Data = (UINT8) (UINTN) Buffer; - IoWrite8 (R_8237_DMA_BASE_CA_CH2, Data); - Data = (UINT8) ((UINTN) Buffer >> 8); - IoWrite8 (R_8237_DMA_BASE_CA_CH2, Data); - - Data = (UINT8) ((UINTN) Buffer >> 16); - IoWrite8 (R_8237_DMA_MEM_LP_CH2, Data); - - // - // Set count register - // - Count = BlockSize * NumberOfBlocks - 1; - Data = (UINT8) (Count & 0xff); - IoWrite8 (R_8237_DMA_BASE_CC_CH2, Data); - Data = (UINT8) (Count >> 8); - IoWrite8 (R_8237_DMA_BASE_CC_CH2, Data); - - // - // Clear channel 2 mask - // - IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, 0x02); -} - - -/** - According to the block range specified by Lba and NumberOfBlocks, calculate - the number of blocks in the same sector, which can be transferred in a batch. - - @param Info Information of floppy device. - @param Lba Start address of block range. - @param NumberOfBlocks Number of blocks of the range. - - @return Number of blocks in the same sector. - -**/ -UINTN -GetTransferBlockCount ( - IN PEI_FLOPPY_DEVICE_INFO *Info, - IN EFI_PEI_LBA Lba, - IN UINTN NumberOfBlocks - ) -{ - DISKET_PARA_TABLE *Para; - UINT8 EndOfTrack; - UINT8 Head; - UINT8 SectorsInTrack; - - // - // Get the base of disk parameter information corresponding to its type. - // - Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type); - - EndOfTrack = Para->EndOfTrack; - Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2); - - SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) Lba % EndOfTrack)); - if (SectorsInTrack < NumberOfBlocks) { - // - // Not all the block range locates in the same sector - // - return SectorsInTrack; - } else { - // - // All the block range is in the same sector. - // - return NumberOfBlocks; - } -} - -/** - Read data sector from FDC device. - - @param FdcBlkIoDev Instance of FDC_BLK_IO_DEV. - @param Info Information of floppy device. - @param Buffer Buffer to setup for DMA. - @param Lba The start address to read. - @param NumberOfBlocks Number of blocks to read. - - @retval EFI_SUCCESS Data successfully read out. - @retval EFI_DEVICE_ERROR FDC device has errors. - @retval EFI_TIMEOUT Command does not take effect in time. - -**/ -EFI_STATUS -ReadDataSector ( - IN FDC_BLK_IO_DEV *FdcBlkIoDev, - IN OUT PEI_FLOPPY_DEVICE_INFO *Info, - IN VOID *Buffer, - IN EFI_PEI_LBA Lba, - IN UINTN NumberOfBlocks - ) -{ - EFI_STATUS Status; - FDC_COMMAND_PACKET1 Command; - FDC_RESULT_PACKET Result; - UINTN Index; - UINTN Times; - UINT8 *Pointer; - - Status = Seek (FdcBlkIoDev, Info, Lba); - if (Status != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - // - // Set up DMA - // - SetDMA (FdcBlkIoDev, Buffer, Info->MediaInfo.BlockSize, NumberOfBlocks); - - // - // Allocate Read command packet - // - ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET1)); - Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK; - - // - // Fill parameters for command. - // - FillPara (Info, Lba, &Command); - - // - // Write command bytes to FDC - // - Pointer = (UINT8 *) (&Command); - for (Index = 0; Index < sizeof (FDC_COMMAND_PACKET1); Index++) { - if (DataOutByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - } - - // - // Wait for some time until command takes effect. - // - Times = (STALL_1_SECOND / FDC_CHECK_INTERVAL) + 1; - do { - if ((IoRead8 ((UINT16) (PcdGet16 (PcdFdcBaseAddress) + FDC_REGISTER_MSR)) & 0xc0) == 0xc0) { - break; - } - - MicroSecondDelay (FDC_SHORT_DELAY); - } while (--Times > 0); - - if (Times == 0) { - // - // Command fails to take effect in time, return EFI_TIMEOUT. - // - return EFI_TIMEOUT; - } - - // - // Read result bytes from FDC - // - Pointer = (UINT8 *) (&Result); - for (Index = 0; Index < sizeof (FDC_RESULT_PACKET); Index++) { - if (DataInByte (FdcBlkIoDev, Pointer++) != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - } - - return CheckResult (&Result, Info); -} - -/** - Gets the count of block I/O devices that one specific block driver detects. - - This function is used for getting the count of block I/O devices that one - specific block driver detects. To the PEI ATAPI driver, it returns the number - of all the detected ATAPI devices it detects during the enumeration process. - To the PEI legacy floppy driver, it returns the number of all the legacy - devices it finds during its enumeration process. If no device is detected, - then the function will return zero. - - @param[in] PeiServices General-purpose services that are available - to every PEIM. - @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI - instance. - @param[out] NumberBlockDevices The number of block I/O devices discovered. - - @retval EFI_SUCCESS Operation performed successfully. - -**/ -EFI_STATUS -EFIAPI -FdcGetNumberOfBlockDevices ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, - OUT UINTN *NumberBlockDevices - ) -{ - FDC_BLK_IO_DEV *FdcBlkIoDev; - - FdcBlkIoDev = NULL; - - FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This); - - *NumberBlockDevices = FdcBlkIoDev->DeviceCount; - - return EFI_SUCCESS; -} - -/** - Gets a block device's media information. - - This function will provide the caller with the specified block device's media - information. If the media changes, calling this function will update the media - information accordingly. - - @param[in] PeiServices General-purpose services that are available to every - PEIM - @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. - @param[in] DeviceIndex Specifies the block device to which the function wants - to talk. Because the driver that implements Block I/O - PPIs will manage multiple block devices, the PPIs that - want to talk to a single device must specify the - device index that was assigned during the enumeration - process. This index is a number from one to - NumberBlockDevices. - @param[out] MediaInfo The media information of the specified block media. - The caller is responsible for the ownership of this - data structure. - - @retval EFI_SUCCESS Media information about the specified block device - was obtained successfully. - @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware - error. - @retval Others Other failure occurs. - -**/ -EFI_STATUS -EFIAPI -FdcGetBlockDeviceMediaInfo ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, - IN UINTN DeviceIndex, - OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo - ) -{ - UINTN DeviceCount; - FDC_BLK_IO_DEV *FdcBlkIoDev; - BOOLEAN Healthy; - UINTN Index; - - FdcBlkIoDev = NULL; - - if (This == NULL || MediaInfo == NULL) { - return EFI_INVALID_PARAMETER; - } - - FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This); - - DeviceCount = FdcBlkIoDev->DeviceCount; - - // - // DeviceIndex is a value from 1 to NumberBlockDevices. - // - if ((DeviceIndex < 1) || (DeviceIndex > DeviceCount) || (DeviceIndex > 2)) { - return EFI_INVALID_PARAMETER; - } - - Index = DeviceIndex - 1; - // - // Probe media and retrieve latest media information - // - Healthy = DiscoverFdcDevice ( - FdcBlkIoDev, - &FdcBlkIoDev->DeviceInfo[Index], - MediaInfo - ); - - if (!Healthy) { - return EFI_DEVICE_ERROR; - } - - CopyMem ( - &(FdcBlkIoDev->DeviceInfo[Index].MediaInfo), - MediaInfo, - sizeof (EFI_PEI_BLOCK_IO_MEDIA) - ); - - return EFI_SUCCESS; -} - -/** - Reads the requested number of blocks from the specified block device. - - The function reads the requested number of blocks from the device. All the - blocks are read, or an error is returned. If there is no media in the device, - the function returns EFI_NO_MEDIA. - - @param[in] PeiServices General-purpose services that are available to - every PEIM. - @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. - @param[in] DeviceIndex Specifies the block device to which the function wants - to talk. Because the driver that implements Block I/O - PPIs will manage multiple block devices, the PPIs that - want to talk to a single device must specify the device - index that was assigned during the enumeration process. - This index is a number from one to NumberBlockDevices. - @param[in] StartLBA The starting logical block address (LBA) to read from - on the device - @param[in] BufferSize The size of the Buffer in bytes. This number must be - a multiple of the intrinsic block size of the device. - @param[out] Buffer A pointer to the destination buffer for the data. - The caller is responsible for the 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 attempting - to perform the read operation. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not - valid, or the buffer is not properly aligned. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of - the intrinsic block size of the device. - -**/ -EFI_STATUS -EFIAPI -FdcReadBlocks ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, - IN UINTN DeviceIndex, - IN EFI_PEI_LBA StartLBA, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_PEI_BLOCK_IO_MEDIA MediaInfo; - EFI_STATUS Status; - UINTN Count; - UINTN NumberOfBlocks; - UINTN BlockSize; - FDC_BLK_IO_DEV *FdcBlkIoDev; - VOID *MemPage; - - FdcBlkIoDev = NULL; - ZeroMem (&MediaInfo, sizeof (EFI_PEI_BLOCK_IO_MEDIA)); - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This); - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = FdcGetBlockDeviceMediaInfo (PeiServices, This, DeviceIndex, &MediaInfo); - if (Status != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - if (!MediaInfo.MediaPresent) { - return EFI_NO_MEDIA; - } - - BlockSize = MediaInfo.BlockSize; - - // - // If BufferSize cannot be divided by block size of FDC device, - // return EFI_BAD_BUFFER_SIZE. - // - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - NumberOfBlocks = BufferSize / BlockSize; - - if ((StartLBA + NumberOfBlocks - 1) > FdcBlkIoDev->DeviceInfo[DeviceIndex - 1].MediaInfo.LastBlock) { - return EFI_INVALID_PARAMETER; - } - - MemPage = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize)); - if ((MemPage == NULL) || ((UINTN) MemPage >= ISA_MAX_MEMORY_ADDRESS)) { - // - // If fail to allocate memory under ISA_MAX_MEMORY_ADDRESS, designate the address space for DMA - // - MemPage = (VOID *) ((UINTN) (UINT32) 0x0f00000); - } - Status = MotorOn (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1])); - if (Status != EFI_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - Status = Setup (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex - 1].DevPos); - if (Status != EFI_SUCCESS) { - MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1])); - return EFI_DEVICE_ERROR; - } - // - // Read data in batches. - // Blocks in the same cylinder are read out in a batch. - // - while ((Count = GetTransferBlockCount ( - &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1]), - StartLBA, - NumberOfBlocks - )) != 0 && Status == EFI_SUCCESS) { - Status = ReadDataSector ( - FdcBlkIoDev, - &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1]), - MemPage, - StartLBA, - Count - ); - CopyMem (Buffer, MemPage, BlockSize * Count); - StartLBA += Count; - NumberOfBlocks -= Count; - Buffer = (VOID *) ((UINTN) Buffer + Count * BlockSize); - } - - MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex - 1])); - - switch (Status) { - case EFI_SUCCESS: - return EFI_SUCCESS; - - default: - FdcReset (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex - 1].DevPos); - return EFI_DEVICE_ERROR; - } -} - -/** - Initializes the floppy disk controller and installs FDC Block I/O PPI. - - @param FileHandle Handle of the file being invoked. - @param PeiServices Describes the list of possible PEI Services. - - @retval EFI_SUCCESS Successfully initialized FDC and installed PPI. - @retval EFI_NOT_FOUND Cannot find FDC device. - @retval EFI_OUT_OF_RESOURCES Have no enough memory to create instance or descriptors. - @retval Other Fail to install FDC Block I/O PPI. - -**/ -EFI_STATUS -EFIAPI -FdcPeimEntry ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN CONST EFI_PEI_SERVICES **PeiServices - ) -{ - EFI_STATUS Status; - FDC_BLK_IO_DEV *FdcBlkIoDev; - UINTN DeviceCount; - UINT32 Index; - - Status = PeiServicesRegisterForShadow (FileHandle); - if (!EFI_ERROR (Status)) { - return Status; - } - - // - // Allocate memory for instance of FDC_BLK_IO_DEV and copy initial value - // from template to it. - // - FdcBlkIoDev = AllocatePages (EFI_SIZE_TO_PAGES(sizeof (FDC_BLK_IO_DEV))); - if (FdcBlkIoDev == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem (FdcBlkIoDev, &mBlockIoDevTemplate, sizeof (mBlockIoDevTemplate)); - - // - // Initialize DMA controller to enable all channels. - // - for (Index = 0; Index < sizeof (mRegisterTable) / sizeof (PEI_DMA_TABLE); Index++) { - IoWrite8 (mRegisterTable[Index].Register, mRegisterTable[Index].Value); - } - REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_INIT); - - // - // Enumerate FDC devices. - // - DeviceCount = FdcEnumeration (FdcBlkIoDev); - if (DeviceCount == 0) { - return EFI_NOT_FOUND; - } - - FdcBlkIoDev->PpiDescriptor.Ppi = &FdcBlkIoDev->FdcBlkIo; - - return PeiServicesInstallPpi (&FdcBlkIoDev->PpiDescriptor); -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.h b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.h deleted file mode 100644 index 6477394efc..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/FloppyPeim.h +++ /dev/null @@ -1,246 +0,0 @@ -/** @file -Private include file for IsaFloppyPei PEIM. - -Copyright (c) 2006 - 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 _RECOVERY_FLOPPY_H_ -#define _RECOVERY_FLOPPY_H_ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Fdc.h" - - -// -// Some PC AT Compatible Device definitions -// -// -// 8237 DMA registers -// -#define R_8237_DMA_BASE_CA_CH0 0x00 -#define R_8237_DMA_BASE_CA_CH1 0x02 -#define R_8237_DMA_BASE_CA_CH2 0x04 -#define R_8237_DMA_BASE_CA_CH3 0xd6 -#define R_8237_DMA_BASE_CA_CH5 0xc4 -#define R_8237_DMA_BASE_CA_CH6 0xc8 -#define R_8237_DMA_BASE_CA_CH7 0xcc - -#define R_8237_DMA_BASE_CC_CH0 0x01 -#define R_8237_DMA_BASE_CC_CH1 0x03 -#define R_8237_DMA_BASE_CC_CH2 0x05 -#define R_8237_DMA_BASE_CC_CH3 0xd7 -#define R_8237_DMA_BASE_CC_CH5 0xc6 -#define R_8237_DMA_BASE_CC_CH6 0xca -#define R_8237_DMA_BASE_CC_CH7 0xce - -#define R_8237_DMA_MEM_LP_CH0 0x87 -#define R_8237_DMA_MEM_LP_CH1 0x83 -#define R_8237_DMA_MEM_LP_CH2 0x81 -#define R_8237_DMA_MEM_LP_CH3 0x82 -#define R_8237_DMA_MEM_LP_CH5 0x8B -#define R_8237_DMA_MEM_LP_CH6 0x89 -#define R_8237_DMA_MEM_LP_CH7 0x8A - - -#define R_8237_DMA_COMMAND_CH0_3 0x08 -#define R_8237_DMA_COMMAND_CH4_7 0xd0 -#define B_8237_DMA_COMMAND_GAP 0x10 -#define B_8237_DMA_COMMAND_CGE 0x04 - - -#define R_8237_DMA_STA_CH0_3 0x09 -#define R_8237_DMA_STA_CH4_7 0xd2 - -#define R_8237_DMA_WRSMSK_CH0_3 0x0a -#define R_8237_DMA_WRSMSK_CH4_7 0xd4 -#define B_8237_DMA_WRSMSK_CMS 0x04 - - -#define R_8237_DMA_CHMODE_CH0_3 0x0b -#define R_8237_DMA_CHMODE_CH4_7 0xd6 -#define V_8237_DMA_CHMODE_DEMAND 0x00 -#define V_8237_DMA_CHMODE_SINGLE 0x40 -#define V_8237_DMA_CHMODE_CASCADE 0xc0 -#define B_8237_DMA_CHMODE_DECREMENT 0x20 -#define B_8237_DMA_CHMODE_INCREMENT 0x00 -#define B_8237_DMA_CHMODE_AE 0x10 -#define V_8237_DMA_CHMODE_VERIFY 0 -#define V_8237_DMA_CHMODE_IO2MEM 0x04 -#define V_8237_DMA_CHMODE_MEM2IO 0x08 - -#define R_8237_DMA_CBPR_CH0_3 0x0c -#define R_8237_DMA_CBPR_CH4_7 0xd8 - -#define R_8237_DMA_MCR_CH0_3 0x0d -#define R_8237_DMA_MCR_CH4_7 0xda - -#define R_8237_DMA_CLMSK_CH0_3 0x0e -#define R_8237_DMA_CLMSK_CH4_7 0xdc - -#define R_8237_DMA_WRMSK_CH0_3 0x0f -#define R_8237_DMA_WRMSK_CH4_7 0xde - -/// -/// ISA memory range -/// -#define ISA_MAX_MEMORY_ADDRESS 0x1000000 - -// -// Macro for time delay & interval -// -#define STALL_1_SECOND 1000000 -#define STALL_1_MSECOND 1000 -#define FDC_CHECK_INTERVAL 50 - -#define FDC_SHORT_DELAY 50 -#define FDC_MEDIUM_DELAY 100 -#define FDC_LONG_DELAY 4000 -#define FDC_RESET_DELAY 2000 -#define FDC_RECALIBRATE_DELAY 250000 - -typedef enum { - FdcType360K360K = 0, - FdcType360K1200K, - FdcType1200K1200K, - FdcType720K720K, - FdcType720K1440K, - FdcType1440K1440K, - FdcType720K2880K, - FdcType1440K2880K, - FdcType2880K2880K -} FDC_DISKET_TYPE; - -typedef struct { - UINT8 Register; - UINT8 Value; -} PEI_DMA_TABLE; - -typedef struct { - UINT8 DevPos; - UINT8 Pcn; - BOOLEAN MotorOn; - BOOLEAN NeedRecalibrate; - FDC_DISKET_TYPE Type; - EFI_PEI_BLOCK_IO_MEDIA MediaInfo; -} PEI_FLOPPY_DEVICE_INFO; - -#define FDC_BLK_IO_DEV_SIGNATURE SIGNATURE_32 ('F', 'b', 'i', 'o') - -typedef struct { - UINTN Signature; - EFI_PEI_RECOVERY_BLOCK_IO_PPI FdcBlkIo; - EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; - UINTN DeviceCount; - PEI_FLOPPY_DEVICE_INFO DeviceInfo[2]; -} FDC_BLK_IO_DEV; - -#define PEI_RECOVERY_FDC_FROM_BLKIO_THIS(a) CR (a, FDC_BLK_IO_DEV, FdcBlkIo, FDC_BLK_IO_DEV_SIGNATURE) - -// -// PEI Recovery Block I/O PPI -// - -/** - Get the number of FDC devices. - - This function implements EFI_PEI_RECOVERY_BLOCK_IO_PPI.GetNumberOfBlockDevices. - It get the number of FDC devices in the system. - - @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. - @param This Pointer to this PPI instance. - @param NumberBlockDevices Pointer to the the number of FDC devices for output. - - @retval EFI_SUCCESS Number of FDC devices is retrieved successfully. - @retval EFI_INVALID_PARAMETER Parameter This is NULL. - -**/ -EFI_STATUS -EFIAPI -FdcGetNumberOfBlockDevices ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, - OUT UINTN *NumberBlockDevices - ); - -/** - Get the specified media information. - - This function implements EFI_PEI_RECOVERY_BLOCK_IO_PPI.GetBlockDeviceMediaInfo. - It gets the specified media information. - - @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. - @param This Pointer to this PPI instance. - @param DeviceIndex Index of FDC device to get information. - @param MediaInfo Pointer to the media info buffer for output. - - @retval EFI_SUCCESS Number of FDC devices is retrieved successfully. - @retval EFI_INVALID_PARAMETER Parameter This is NULL. - @retval EFI_INVALID_PARAMETER Parameter MediaInfo is NULL. - @retval EFI_INVALID_PARAMETER DeviceIndex is not valid. - @retval EFI_DEVICE_ERROR FDC device does not exist or has errors. - -**/ -EFI_STATUS -EFIAPI -FdcGetBlockDeviceMediaInfo ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, - IN UINTN DeviceIndex, - OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo - ); - -/** - Get the requested number of blocks from the specified FDC device. - - This function implements EFI_PEI_RECOVERY_BLOCK_IO_PPI.ReadBlocks. - It reads the requested number of blocks from the specified FDC device. - - @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. - @param This Pointer to this PPI instance. - @param DeviceIndex Index of FDC device to get information. - @param StartLba The start LBA to read from. - @param BufferSize The size of range to read. - @param Buffer Buffer to hold the data read from FDC. - - @retval EFI_SUCCESS Number of FDC devices is retrieved successfully. - @retval EFI_INVALID_PARAMETER Parameter This is NULL. - @retval EFI_INVALID_PARAMETER Parameter Buffer is NULL. - @retval EFI_INVALID_PARAMETER Parameter BufferSize cannot be divided by block size of FDC device. - @retval EFI_NO_MEDIA No media present. - @retval EFI_DEVICE_ERROR FDC device has error. - @retval Others Fail to read blocks. - -**/ -EFI_STATUS -EFIAPI -FdcReadBlocks ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, - IN UINTN DeviceIndex, - IN EFI_PEI_LBA StartLba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf deleted file mode 100644 index 8d4db34fbe..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf +++ /dev/null @@ -1,73 +0,0 @@ -## @file -# ISA Floppy PEIM to support recovery boot via floppy disk. -# -# This module detects and supports ISA Floppy drives. If a drive is discovered -# the PEIM will install the BlockIo PPI. This module is only dispatched if it -# is in the Recovery Boot mode. -# -# 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 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 = IsaFloppyPei - MODULE_UNI_FILE = IsaFloppyPei.uni - FILE_GUID = 7F6E0A24-DBFD-43df-9755-0292D7D3DD48 - MODULE_TYPE = PEIM - VERSION_STRING = 1.0 - - ENTRY_POINT = FdcPeimEntry - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only) -# - -[Sources] - FloppyPeim.c - FloppyPeim.h - Fdc.h - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - IoLib - TimerLib - ReportStatusCodeLib - BaseMemoryLib - PeiServicesLib - PeimEntryPoint - DebugLib - MemoryAllocationLib - PcdLib - -[Ppis] - gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES - -[Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFdcBaseAddress ## CONSUMES - -[Depex] - gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid - -[UserExtensions.TianoCore."ExtraFiles"] - IsaFloppyPeiExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni deleted file mode 100644 index 57f64d6e12..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni deleted file mode 100644 index cbef982a66..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPeiExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c deleted file mode 100644 index 97c196037a..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c +++ /dev/null @@ -1,182 +0,0 @@ -/** @file - UEFI Component Name(2) protocol implementation for Isa driver. - -Copyright (c) 2010 - 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 "IsaDriver.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaIoComponentName = { - IsaIoComponentNameGetDriverName, - IsaIoComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaIoComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaIoComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaIoComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaIoDriverNameTable[] = { - { - "eng;en", - L"ISA IO Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -IsaIoComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mIsaIoDriverNameTable, - DriverName, - (BOOLEAN)(This == &gIsaIoComponentName) - ); -} - -/** - 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 -IsaIoComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h deleted file mode 100644 index 8e8178773b..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h +++ /dev/null @@ -1,148 +0,0 @@ -/** @file - Header file for implementation of UEFI Component Name(2) protocol. - -Copyright (c) 2010 - 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 _COMPONENT_NAME_H_ -#define _COMPONENT_NAME_H_ - -extern EFI_COMPONENT_NAME_PROTOCOL gIsaIoComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gIsaIoComponentName2; - -/** - 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 -IsaIoComponentNameGetDriverName ( - 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 -IsaIoComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c deleted file mode 100644 index 8c58b318c6..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c +++ /dev/null @@ -1,326 +0,0 @@ -/** @file - IsaIo UEFI driver. - - Produce an instance of the ISA I/O Protocol for every SIO controller. - -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 "IsaDriver.h" - -// -// IsaIo Driver Global Variables -// -EFI_DRIVER_BINDING_PROTOCOL gIsaIoDriver = { - IsaIoDriverSupported, - IsaIoDriverStart, - IsaIoDriverStop, - 0xa, - NULL, - NULL -}; - -/** - The main entry point for the IsaIo 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 EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. -**/ -EFI_STATUS -EFIAPI -InitializeIsaIo ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gIsaIoDriver, - ImageHandle, - &gIsaIoComponentName, - &gIsaIoComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} - -/** - Tests to see if a controller can be managed by the IsaIo driver. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] Controller The handle of the controller to test. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS The device is supported by this driver. - @retval EFI_ALREADY_STARTED The device is already being managed by this driver. - @retval EFI_ACCESS_DENIED The device is already being managed by a different driver - or an application that requires exclusive access. - @retval EFI_UNSUPPORTED The device is is not supported by this driver. - -**/ -EFI_STATUS -EFIAPI -IsaIoDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_SIO_PROTOCOL *Sio; - EFI_HANDLE PciHandle; - - // - // Try to open EFI DEVICE PATH protocol on the controller - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - if (!EFI_ERROR (Status)) { - // - // Get the PciIo protocol from its parent controller. - // - Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &DevicePath, &PciHandle); - } - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Try to open the Super IO protocol on the controller - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiSioProtocolGuid, - (VOID **) &Sio, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (!EFI_ERROR (Status)) { - gBS->CloseProtocol ( - Controller, - &gEfiSioProtocolGuid, - This->DriverBindingHandle, - Controller - ); - } - - return Status; -} - -/** - Start this driver on ControllerHandle. - - The Start() function is designed to be invoked from the EFI boot service ConnectController(). - As a result, much of the error checking on the parameters to Start() has been moved into this - common boot service. It is legal to call Start() from other locations, but the following calling - restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE. - 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned - EFI_DEVICE_PATH_PROTOCOL. - 3. Prior to calling Start(), the Supported() function for the driver specified by This must - have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - This parameter is ignored by device drivers, and is optional for bus drivers. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error. - Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. -**/ -EFI_STATUS -EFIAPI -IsaIoDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_HANDLE PciHandle; - EFI_SIO_PROTOCOL *Sio; - ACPI_RESOURCE_HEADER_PTR Resources; - EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; - ISA_IO_DEVICE *IsaIoDevice; - - PciIo = NULL; - Sio = NULL; - - // - // Open Device Path Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the PciIo protocol from its parent controller. - // - TempDevicePath = DevicePath; - Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &TempDevicePath, &PciHandle); - if (!EFI_ERROR (Status)) { - Status = gBS->HandleProtocol (PciHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo); - ASSERT_EFI_ERROR (Status); - - // - // Open Super IO Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiSioProtocolGuid, - (VOID **) &Sio, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - } - - if (EFI_ERROR (Status)) { - // - // Fail due to LocateDevicePath(...) or OpenProtocol(Sio, BY_DRIVER) - // - return Status; - } - - Status = Sio->GetResources (Sio, &Resources); - ASSERT_EFI_ERROR (Status); - - IsaIoDevice = AllocatePool (sizeof (ISA_IO_DEVICE)); - ASSERT (IsaIoDevice != NULL); - - IsaIoDevice->Signature = ISA_IO_DEVICE_SIGNATURE; - IsaIoDevice->PciIo = PciIo; - - // - // Initialize the ISA I/O instance structure - // - InitializeIsaIoInstance (IsaIoDevice, DevicePath, Resources); - - // - // Install the ISA I/O protocol on the Controller handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiIsaIoProtocolGuid, - &IsaIoDevice->IsaIo, - NULL - ); - ASSERT_EFI_ERROR (Status); - - return EFI_SUCCESS; -} - -/** - Stop this driver on ControllerHandle. - - The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). - As a result, much of the error checking on the parameters to Stop() has been moved - into this common boot service. It is legal to call Stop() from other locations, - but the following calling restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this - same driver's Start() function. - 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid - EFI_HANDLE. In addition, all of these handles must have been created in this driver's - Start() function, and the Start() function must have called OpenProtocol() on - ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. -**/ -EFI_STATUS -EFIAPI -IsaIoDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL * This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE * ChildHandleBuffer OPTIONAL - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - EFI_ISA_IO_PROTOCOL *IsaIo; - - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo); - - Status = gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiIsaIoProtocolGuid, - &IsaIoDevice->IsaIo, - NULL - ); - if (!EFI_ERROR (Status)) { - Status = gBS->CloseProtocol ( - Controller, - &gEfiSioProtocolGuid, - This->DriverBindingHandle, - Controller - ); - FreePool (IsaIoDevice->IsaIo.ResourceList); - FreePool (IsaIoDevice); - } - - return Status; -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h deleted file mode 100644 index 64f710bcec..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h +++ /dev/null @@ -1,263 +0,0 @@ -/** @file - The header file for ISA driver - -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 _ISA_DRIVER_H_ -#define _ISA_DRIVER_H_ - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ComponentName.h" - -// -// 8237 DMA registers -// -#define R_8237_DMA_BASE_CA_CH0 0x00 -#define R_8237_DMA_BASE_CA_CH1 0x02 -#define R_8237_DMA_BASE_CA_CH2 0x04 -#define R_8237_DMA_BASE_CA_CH3 0xd6 -#define R_8237_DMA_BASE_CA_CH5 0xc4 -#define R_8237_DMA_BASE_CA_CH6 0xc8 -#define R_8237_DMA_BASE_CA_CH7 0xcc - -#define R_8237_DMA_BASE_CC_CH0 0x01 -#define R_8237_DMA_BASE_CC_CH1 0x03 -#define R_8237_DMA_BASE_CC_CH2 0x05 -#define R_8237_DMA_BASE_CC_CH3 0xd7 -#define R_8237_DMA_BASE_CC_CH5 0xc6 -#define R_8237_DMA_BASE_CC_CH6 0xca -#define R_8237_DMA_BASE_CC_CH7 0xce - -#define R_8237_DMA_MEM_LP_CH0 0x87 -#define R_8237_DMA_MEM_LP_CH1 0x83 -#define R_8237_DMA_MEM_LP_CH2 0x81 -#define R_8237_DMA_MEM_LP_CH3 0x82 -#define R_8237_DMA_MEM_LP_CH5 0x8B -#define R_8237_DMA_MEM_LP_CH6 0x89 -#define R_8237_DMA_MEM_LP_CH7 0x8A - - -#define R_8237_DMA_COMMAND_CH0_3 0x08 -#define R_8237_DMA_COMMAND_CH4_7 0xd0 -#define B_8237_DMA_COMMAND_GAP 0x10 -#define B_8237_DMA_COMMAND_CGE 0x04 - - -#define R_8237_DMA_STA_CH0_3 0xd8 -#define R_8237_DMA_STA_CH4_7 0xd0 - -#define R_8237_DMA_WRSMSK_CH0_3 0x0a -#define R_8237_DMA_WRSMSK_CH4_7 0xd4 -#define B_8237_DMA_WRSMSK_CMS 0x04 - - -#define R_8237_DMA_CHMODE_CH0_3 0x0b -#define R_8237_DMA_CHMODE_CH4_7 0xd6 -#define V_8237_DMA_CHMODE_DEMAND 0x00 -#define V_8237_DMA_CHMODE_SINGLE 0x40 -#define V_8237_DMA_CHMODE_CASCADE 0xc0 -#define B_8237_DMA_CHMODE_DECREMENT 0x20 -#define B_8237_DMA_CHMODE_INCREMENT 0x00 -#define B_8237_DMA_CHMODE_AE 0x10 -#define V_8237_DMA_CHMODE_VERIFY 0 -#define V_8237_DMA_CHMODE_IO2MEM 0x04 -#define V_8237_DMA_CHMODE_MEM2IO 0x08 - -#define R_8237_DMA_CBPR_CH0_3 0x0c -#define R_8237_DMA_CBPR_CH4_7 0xd8 - -#define R_8237_DMA_MCR_CH0_3 0x0d -#define R_8237_DMA_MCR_CH4_7 0xda - -#define R_8237_DMA_CLMSK_CH0_3 0x0e -#define R_8237_DMA_CLMSK_CH4_7 0xdc - -#define R_8237_DMA_WRMSK_CH0_3 0x0f -#define R_8237_DMA_WRMSK_CH4_7 0xde - -typedef enum { - IsaAccessTypeUnknown, - IsaAccessTypeIo, - IsaAccessTypeMem, - IsaAccessTypeMaxType -} ISA_ACCESS_TYPE; - -typedef struct { - UINT8 Address; - UINT8 Page; - UINT8 Count; -} EFI_ISA_DMA_REGISTERS; - -// -// ISA I/O Device Structure -// -#define ISA_IO_DEVICE_SIGNATURE SIGNATURE_32 ('i', 's', 'a', 'i') - -typedef struct { - UINT32 Signature; - EFI_HANDLE Handle; - EFI_ISA_IO_PROTOCOL IsaIo; - EFI_PCI_IO_PROTOCOL *PciIo; -} ISA_IO_DEVICE; - -#define ISA_IO_DEVICE_FROM_ISA_IO_THIS(a) CR (a, ISA_IO_DEVICE, IsaIo, ISA_IO_DEVICE_SIGNATURE) - -// -// Mapping structure for performing ISA DMA to a buffer above 16 MB -// -typedef struct { - EFI_ISA_IO_PROTOCOL_OPERATION Operation; - UINTN NumberOfBytes; - UINTN NumberOfPages; - EFI_PHYSICAL_ADDRESS HostAddress; - EFI_PHYSICAL_ADDRESS MappedHostAddress; -} ISA_MAP_INFO; - -// -// EFI Driver Binding Protocol Interface Functions -// - -/** - Tests to see if a controller can be managed by the ISA Driver. - - How the Start() function of a driver is implemented can affect how the Supported() function is implemented. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] Controller The handle of the controller to test. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS The device is supported by this driver. - @retval EFI_ALREADY_STARTED The device is already being managed by this driver. - @retval EFI_ACCESS_DENIED The device is already being managed by a different driver - or an application that requires exclusive access. - @retval EFI_UNSUPPORTED The device is is not supported by this driver. - -**/ -EFI_STATUS -EFIAPI -IsaIoDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ); - -/** - Start this driver on ControllerHandle. - - The Start() function is designed to be invoked from the EFI boot service ConnectController(). - As a result, much of the error checking on the parameters to Start() has been moved into this - common boot service. It is legal to call Start() from other locations, but the following calling - restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE. - 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned - EFI_DEVICE_PATH_PROTOCOL. - 3. Prior to calling Start(), the Supported() function for the driver specified by This must - have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. - This parameter is ignored by device drivers, and is optional for bus drivers. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error. - Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. -**/ -EFI_STATUS -EFIAPI -IsaIoDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ); - -/** - Stop this driver on ControllerHandle. - - The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). - As a result, much of the error checking on the parameters to Stop() has been moved - into this common boot service. It is legal to call Stop() from other locations, - but the following calling restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this - same driver's Start() function. - 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid - EFI_HANDLE. In addition, all of these handles must have been created in this driver's - Start() function, and the Start() function must have called OpenProtocol() on - ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. -**/ -EFI_STATUS -EFIAPI -IsaIoDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL * This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE * ChildHandleBuffer OPTIONAL - ); - -// -// Function Prototypes -// - -/** - Initializes an ISA I/O Instance - - @param[in] IsaIoDevice The isa device to be initialized. - @param[in] DevicePath The device path of the isa device. - @param[in] Resources The ACPI resource list. - -**/ -VOID -InitializeIsaIoInstance ( - IN ISA_IO_DEVICE *IsaIoDevice, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - IN ACPI_RESOURCE_HEADER_PTR Resources - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c deleted file mode 100644 index 2e4361fc0d..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c +++ /dev/null @@ -1,1803 +0,0 @@ -/** @file - The implementation for EFI_ISA_IO_PROTOCOL. - -Copyright (c) 2010 - 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 "IsaIo.h" - -// -// Module Variables -// -EFI_ISA_IO_PROTOCOL mIsaIoInterface = { - { - IsaIoMemRead, - IsaIoMemWrite - }, - { - IsaIoIoRead, - IsaIoIoWrite - }, - IsaIoCopyMem, - IsaIoMap, - IsaIoUnmap, - IsaIoAllocateBuffer, - IsaIoFreeBuffer, - IsaIoFlush, - NULL, - 0, - NULL -}; - -EFI_ISA_DMA_REGISTERS mDmaRegisters[8] = { - { - 0x00, - 0x87, - 0x01 - }, - { - 0x02, - 0x83, - 0x03 - }, - { - 0x04, - 0x81, - 0x05 - }, - { - 0x06, - 0x82, - 0x07 - }, - { - 0x00, - 0x00, - 0x00 - }, // Channel 4 is invalid - { - 0xC4, - 0x8B, - 0xC6 - }, - { - 0xC8, - 0x89, - 0xCA - }, - { - 0xCC, - 0x8A, - 0xCE - }, -}; - -/** - Verifies access to an ISA device - - @param[in] IsaIoDevice The ISA device to be verified. - @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. - @param[in] Width The width of the memory operation. - @param[in] Count The number of memory operations to perform. - @param[in] Offset The offset in ISA memory space to start the memory operation. - - @retval EFI_SUCCESS Verify success. - @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. - @retval EFI_UNSUPPORTED The device ont support the access type. -**/ -EFI_STATUS -IsaIoVerifyAccess ( - IN ISA_IO_DEVICE *IsaIoDevice, - IN ISA_ACCESS_TYPE Type, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINTN Count, - IN UINT32 Offset - ) -{ - EFI_ISA_ACPI_RESOURCE *Item; - EFI_STATUS Status; - - if ((UINT32)Width >= EfiIsaIoWidthMaximum || - Width == EfiIsaIoWidthReserved || - Width == EfiIsaIoWidthFifoReserved || - Width == EfiIsaIoWidthFillReserved - ) { - return EFI_INVALID_PARAMETER; - } - - // - // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX - // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX - // - if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) { - Count = 1; - } - - Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03); - - Status = EFI_UNSUPPORTED; - Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem; - while (Item->Type != EfiIsaAcpiResourceEndOfList) { - if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) || - (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) { - if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) { - return EFI_SUCCESS; - } - - if (Offset >= Item->StartRange && Offset <= Item->EndRange) { - Status = EFI_INVALID_PARAMETER; - } - } - - Item++; - } - - return Status; -} - -/** - Convert the IO Information in ACPI descriptor to IO ISA Attribute. - - @param[in] Information The IO Information in ACPI descriptor - - @return UINT32 The IO ISA Attribute -**/ -UINT32 -IsaIoAttribute ( - IN UINT8 Information - ) -{ - UINT32 Attribute; - - Attribute = 0; - - switch (Information & EFI_ACPI_IO_DECODE_MASK) { - case EFI_ACPI_IO_DECODE_16_BIT: - Attribute |= EFI_ISA_ACPI_IO_DECODE_16_BITS; - break; - - case EFI_ACPI_IO_DECODE_10_BIT: - Attribute |= EFI_ISA_ACPI_IO_DECODE_10_BITS; - break; - } - - return Attribute; -} - -/** - Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute. - - @param[in] Information The IRQ Information in ACPI descriptor - - @return UINT32 The IRQ ISA Attribute -**/ -UINT32 -IsaIrqAttribute ( - IN UINT8 Information - ) -{ - UINT32 Attribute; - - Attribute = 0; - - if ((Information & EFI_ACPI_IRQ_POLARITY_MASK) == EFI_ACPI_IRQ_HIGH_TRUE) { - if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) { - Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE; - } else { - Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE; - } - } else { - if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) { - Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE; - } else { - Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE; - } - } - return Attribute; -} - -/** - Convert the Memory Information in ACPI descriptor to Memory ISA Attribute. - - @param[in] Information The Memory Information in ACPI descriptor - - @return UINT32 The Memory ISA Attribute -**/ -UINT32 -IsaMemoryAttribute ( - IN UINT8 Information - ) -{ - UINT32 Attribute; - - Attribute = 0; - - switch (Information & EFI_ACPI_MEMORY_WRITE_STATUS_MASK) { - case EFI_ACPI_MEMORY_WRITABLE: - Attribute |= EFI_ISA_ACPI_MEMORY_WRITEABLE; - break; - } - - return Attribute; -} - -/** - Convert the DMA Information in ACPI descriptor to DMA ISA Attribute. - - @param[in] Information The DMA Information in ACPI descriptor - - @return UINT32 The DMA ISA Attribute -**/ -UINT32 -IsaDmaAttribute ( - IN UINT8 Information - ) -{ - UINT32 Attribute; - - Attribute = EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE; - - switch (Information & EFI_ACPI_DMA_SPEED_TYPE_MASK) { - case EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY: - Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE; - break; - case EFI_ACPI_DMA_SPEED_TYPE_A: - Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A; - break; - case EFI_ACPI_DMA_SPEED_TYPE_B: - Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B; - break; - case EFI_ACPI_DMA_SPEED_TYPE_F: - Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C; - break; - } - - switch (Information & EFI_ACPI_DMA_TRANSFER_TYPE_MASK) { - case EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT: - Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8; - break; - case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT: - Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16; - break; - } - - return Attribute; -} - -/** - Convert the ACPI resource descriptor to ISA resource descriptor. - - @param[in] AcpiResource Pointer to the ACPI resource descriptor - @param[out] IsaResource The optional pointer to the buffer to - store the converted ISA resource descriptor - - @return UINTN Number of ISA resource descriptor needed -**/ -UINTN -AcpiResourceToIsaResource ( - IN ACPI_RESOURCE_HEADER_PTR AcpiResource, - OUT EFI_ISA_ACPI_RESOURCE *IsaResource OPTIONAL - ) -{ - UINT32 Index; - UINTN Count; - UINT32 LastIndex; - EFI_ACPI_IO_PORT_DESCRIPTOR *Io; - EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIo; - EFI_ACPI_IRQ_DESCRIPTOR *Irq; - EFI_ACPI_DMA_DESCRIPTOR *Dma; - EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *Memory; - EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *FixedMemory; - - Count = 0; - LastIndex = 0; - - switch (AcpiResource.SmallHeader->Byte) { - case ACPI_DMA_DESCRIPTOR: - Dma = (EFI_ACPI_DMA_DESCRIPTOR *) AcpiResource.SmallHeader; - for (Index = 0; Index < sizeof (Dma->ChannelMask) * 8; Index++) { - if (Dma->ChannelMask & (1 << Index)) { - if ((Count > 0) && (LastIndex + 1 == Index)) { - if (IsaResource != NULL) { - IsaResource[Count - 1].EndRange ++; - } - } else { - if (IsaResource != NULL) { - IsaResource[Count].Type = EfiIsaAcpiResourceDma; - IsaResource[Count].Attribute = IsaDmaAttribute (Dma->Information); - IsaResource[Count].StartRange = Index; - IsaResource[Count].EndRange = Index; - } - Count ++; - } - - LastIndex = Index; - } - } - break; - - case ACPI_IO_PORT_DESCRIPTOR: - Io = (EFI_ACPI_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader; - if (Io->Length != 0) { - if (IsaResource != NULL) { - IsaResource[Count].Type = EfiIsaAcpiResourceIo; - IsaResource[Count].Attribute = IsaIoAttribute (Io->Information); - IsaResource[Count].StartRange = Io->BaseAddressMin; - IsaResource[Count].EndRange = Io->BaseAddressMin + Io->Length - 1; - } - Count ++; - } - break; - - case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR: - FixedIo = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader; - if (FixedIo->Length != 0) { - if (IsaResource != NULL) { - IsaResource[Count].Type = EfiIsaAcpiResourceIo; - IsaResource[Count].Attribute = EFI_ISA_ACPI_IO_DECODE_10_BITS; - IsaResource[Count].StartRange = FixedIo->BaseAddress; - IsaResource[Count].EndRange = FixedIo->BaseAddress + FixedIo->Length - 1; - } - Count ++; - } - break; - - case ACPI_IRQ_DESCRIPTOR: - case ACPI_IRQ_NOFLAG_DESCRIPTOR: - Irq = (EFI_ACPI_IRQ_DESCRIPTOR *) AcpiResource.SmallHeader; - for (Index = 0; Index < sizeof (Irq->Mask) * 8; Index++) { - if (Irq->Mask & (1 << Index)) { - if ((Count > 0) && (LastIndex + 1 == Index)) { - if (IsaResource != NULL) { - IsaResource[Count - 1].EndRange ++; - } - } else { - if (IsaResource != NULL) { - IsaResource[Count].Type = EfiIsaAcpiResourceInterrupt; - if (AcpiResource.SmallHeader->Byte == ACPI_IRQ_DESCRIPTOR) { - IsaResource[Count].Attribute = IsaIrqAttribute (Irq->Information); - } else { - IsaResource[Count].Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE; - } - IsaResource[Count].StartRange = Index; - IsaResource[Count].EndRange = Index; - } - Count++; - } - - LastIndex = Index; - } - } - break; - - case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR: - Memory = (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader; - if (Memory->Length != 0) { - if (IsaResource != NULL) { - IsaResource[Count].Type = EfiIsaAcpiResourceMemory; - IsaResource[Count].Attribute = IsaMemoryAttribute (Memory->Information); - IsaResource[Count].StartRange = Memory->BaseAddressMin; - IsaResource[Count].EndRange = Memory->BaseAddressMin + Memory->Length - 1; - } - Count ++; - } - break; - - case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR: - FixedMemory = (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader; - if (FixedMemory->Length != 0) { - if (IsaResource != NULL) { - IsaResource[Count].Type = EfiIsaAcpiResourceMemory; - IsaResource[Count].Attribute = IsaMemoryAttribute (FixedMemory->Information); - IsaResource[Count].StartRange = FixedMemory->BaseAddress; - IsaResource[Count].EndRange = FixedMemory->BaseAddress + FixedMemory->Length - 1; - } - Count ++; - } - break; - - case ACPI_END_TAG_DESCRIPTOR: - if (IsaResource != NULL) { - IsaResource[Count].Type = EfiIsaAcpiResourceEndOfList; - IsaResource[Count].Attribute = 0; - IsaResource[Count].StartRange = 0; - IsaResource[Count].EndRange = 0; - } - Count ++; - break; - } - - return Count; -} - -/** - Initializes an ISA I/O Instance - - @param[in] IsaIoDevice The isa device to be initialized. - @param[in] DevicePath The device path of the isa device. - @param[in] Resources The ACPI resource list. - -**/ -VOID -InitializeIsaIoInstance ( - IN ISA_IO_DEVICE *IsaIoDevice, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - IN ACPI_RESOURCE_HEADER_PTR Resources - ) -{ - UINTN Index; - ACPI_HID_DEVICE_PATH *AcpiNode; - ACPI_RESOURCE_HEADER_PTR ResourcePtr; - - // - // Use the ISA IO Protocol structure template to initialize the ISA IO instance - // - CopyMem ( - &IsaIoDevice->IsaIo, - &mIsaIoInterface, - sizeof (EFI_ISA_IO_PROTOCOL) - ); - - // - // Count the resources including the ACPI End Tag - // - ResourcePtr = Resources; - Index = 0; - while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) { - - Index += AcpiResourceToIsaResource (ResourcePtr, NULL); - - if (ResourcePtr.SmallHeader->Bits.Type == 0) { - ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader - + ResourcePtr.SmallHeader->Bits.Length - + sizeof (*ResourcePtr.SmallHeader)); - } else { - ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader - + ResourcePtr.LargeHeader->Length - + sizeof (*ResourcePtr.LargeHeader)); - } - - } - // - // Get the Isa Resource count for ACPI End Tag - // - Index += AcpiResourceToIsaResource (ResourcePtr, NULL); - - // - // Initialize the ResourceList - // - IsaIoDevice->IsaIo.ResourceList = AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST) + Index * sizeof (EFI_ISA_ACPI_RESOURCE)); - ASSERT (IsaIoDevice->IsaIo.ResourceList != NULL); - IsaIoDevice->IsaIo.ResourceList->ResourceItem = (EFI_ISA_ACPI_RESOURCE *) (IsaIoDevice->IsaIo.ResourceList + 1); - - AcpiNode = (ACPI_HID_DEVICE_PATH *) ((UINT8 *) DevicePath + GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH - sizeof (ACPI_HID_DEVICE_PATH)); - IsaIoDevice->IsaIo.ResourceList->Device.HID = AcpiNode->HID; - IsaIoDevice->IsaIo.ResourceList->Device.UID = AcpiNode->UID; - - ResourcePtr = Resources; - Index = 0; - while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) { - - Index += AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]); - - if (ResourcePtr.SmallHeader->Bits.Type == 0) { - ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader - + ResourcePtr.SmallHeader->Bits.Length - + sizeof (*ResourcePtr.SmallHeader)); - } else { - ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader - + ResourcePtr.LargeHeader->Length - + sizeof (*ResourcePtr.LargeHeader)); - } - } - - // - // Convert the ACPI End Tag - // - AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]); -} - -/** - Performs an ISA I/O Read Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O operation. - @param[in] Offset The offset in ISA I/O space to start the I/O operation. - @param[in] Count The number of I/O operations to perform. - @param[out] Buffer The destination buffer to store the results - - @retval EFI_SUCCESS The data was read from the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoIoRead ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - OUT VOID *Buffer - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify Isa IO Access - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeIo, - Width, - Count, - Offset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->Io.Read ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - Count, - Buffer - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Performs an ISA I/O Write Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O operation. - @param[in] Offset The offset in ISA I/O space to start the I/O operation. - @param[in] Count The number of I/O operations to perform. - @param[in] Buffer The source buffer to write data from - - @retval EFI_SUCCESS The data was writen to the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoIoWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN VOID *Buffer - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify Isa IO Access - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeIo, - Width, - Count, - Offset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->Io.Write ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - Count, - Buffer - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Writes an 8-bit I/O Port - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Offset The offset in ISA IO space to start the IO operation. - @param[in] Value The data to write port. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Parameter is invalid. - @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -WritePort ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINT32 Offset, - IN UINT8 Value - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - Status = IsaIoDevice->PciIo->Io.Write ( - IsaIoDevice->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - 1, - &Value - ); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - return Status; - } - - // - // Wait for 50 microseconds to take affect. - // - gBS->Stall (50); - - return EFI_SUCCESS; -} - -/** - Writes I/O operation base address and count number to a 8 bit I/O Port. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] AddrOffset The address' offset. - @param[in] PageOffset The page's offest. - @param[in] CountOffset The count's offset. - @param[in] BaseAddress The base address. - @param[in] Count The number of I/O operations to perform. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Parameter is invalid. - @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -WriteDmaPort ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINT32 AddrOffset, - IN UINT32 PageOffset, - IN UINT32 CountOffset, - IN UINT32 BaseAddress, - IN UINT16 Count - ) -{ - EFI_STATUS Status; - - Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff)); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff)); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff)); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff)); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff)); - return Status; -} - -/** - Unmaps a memory region for DMA - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). - - @retval EFI_SUCCESS The range was unmapped. - @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. -**/ -EFI_STATUS -EFIAPI -IsaIoUnmap ( - IN EFI_ISA_IO_PROTOCOL *This, - IN VOID *Mapping - ) -{ - ISA_MAP_INFO *IsaMapInfo; - - // - // Check if DMA is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { - return EFI_UNSUPPORTED; - } - - // - // See if the Map() operation associated with this Unmap() required a mapping - // buffer.If a mapping buffer was not required, then this function simply - // returns EFI_SUCCESS. - // - if (Mapping != NULL) { - // - // Get the MAP_INFO structure from Mapping - // - IsaMapInfo = (ISA_MAP_INFO *) Mapping; - - // - // If this is a write operation from the Agent's point of view, - // then copy the contents of the mapped buffer into the real buffer - // so the processor can read the contents of the real buffer. - // - if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) { - CopyMem ( - (VOID *) (UINTN) IsaMapInfo->HostAddress, - (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, - IsaMapInfo->NumberOfBytes - ); - } - // - // Free the mapped buffer and the MAP_INFO structure. - // - gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages); - FreePool (IsaMapInfo); - } - - return EFI_SUCCESS; -} - -/** - Flushes any posted write data to the system memory. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - - @retval EFI_SUCCESS The buffers were flushed. - @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. -**/ -EFI_STATUS -EFIAPI -IsaIoFlush ( - IN EFI_ISA_IO_PROTOCOL *This - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Performs an ISA Memory Read Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory operation. - @param[in] Offset The offset in ISA memory space to start the memory operation. - @param[in] Count The number of memory operations to perform. - @param[out] Buffer The destination buffer to store the results - - @retval EFI_SUCCESS The data was read from the device successfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoMemRead ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - OUT VOID *Buffer - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - // - // Check if ISA memory is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { - return EFI_UNSUPPORTED; - } - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify the Isa Io Access - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeMem, - Width, - Count, - Offset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->Mem.Read ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - Count, - Buffer - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Performs an ISA Memory Write Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory operation. - @param[in] Offset The offset in ISA memory space to start the memory operation. - @param[in] Count The number of memory operations to perform. - @param[in] Buffer The source buffer to write data from - - @retval EFI_SUCCESS The data was written to the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoMemWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN VOID *Buffer - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - // - // Check if ISA memory is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { - return EFI_UNSUPPORTED; - } - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify Isa IO Access - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeMem, - Width, - Count, - Offset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->Mem.Write ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - Offset, - Count, - Buffer - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory copy operation. - @param[in] DestOffset The offset of the destination - @param[in] SrcOffset The offset of the source - @param[in] Count The number of memory copy operations to perform - - @retval EFI_SUCCESS The data was copied sucessfully. - @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoCopyMem ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 DestOffset, - IN UINT32 SrcOffset, - IN UINTN Count - ) -{ - EFI_STATUS Status; - ISA_IO_DEVICE *IsaIoDevice; - - // - // Check if ISA memory is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { - return EFI_UNSUPPORTED; - } - - IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); - - // - // Verify Isa IO Access for destination and source - // - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeMem, - Width, - Count, - DestOffset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoVerifyAccess ( - IsaIoDevice, - IsaAccessTypeMem, - Width, - Count, - SrcOffset - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IsaIoDevice->PciIo->CopyMem ( - IsaIoDevice->PciIo, - (EFI_PCI_IO_PROTOCOL_WIDTH) Width, - EFI_PCI_IO_PASS_THROUGH_BAR, - DestOffset, - EFI_PCI_IO_PASS_THROUGH_BAR, - SrcOffset, - Count - ); - - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - -/** - Maps a memory region for DMA, note this implementation - only supports slave read/write operation to save code size. - - @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param Operation Indicates the type of DMA (slave or bus master), and if - the DMA operation is going to read or write to system memory. - @param ChannelNumber The slave channel number to use for this DMA operation. - If Operation and ChannelAttributes shows that this device - performs bus mastering DMA, then this field is ignored. - The legal range for this field is 0..7. - @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation - @param HostAddress The system memory address to map to the device. - @param NumberOfBytes On input the number of bytes to map. On output the number - of bytes that were mapped. - @param DeviceAddress The resulting map address for the bus master device to use - to access the hosts HostAddress. - @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). - - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. - @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -IsaIoMapOnlySupportSlaveReadWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - ISA_MAP_INFO *IsaMapInfo; - UINT8 DmaMode; - UINTN MaxNumberOfBytes; - UINT32 BaseAddress; - UINT16 Count; - UINT8 DmaMask; - UINT8 DmaClear; - UINT8 DmaChannelMode; - - if ((NULL == This) || - (NULL == HostAddress) || - (NULL == NumberOfBytes) || - (NULL == DeviceAddress) || - (NULL == Mapping) - ) { - return EFI_INVALID_PARAMETER; - } - - // - // Initialize the return values to their defaults - // - *Mapping = NULL; - - // - // Make sure the Operation parameter is valid. - // Light IsaIo only supports two operations. - // - if (!(Operation == EfiIsaIoOperationSlaveRead || - Operation == EfiIsaIoOperationSlaveWrite)) { - return EFI_INVALID_PARAMETER; - } - - if (ChannelNumber >= 4) { - // - // The Light IsaIo doesn't support channelNumber larger than 4. - // - return EFI_INVALID_PARAMETER; - } - - // - // Map the HostAddress to a DeviceAddress. - // - PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; - if ((PhysicalAddress + *NumberOfBytes) > BASE_16MB) { - // - // Common Buffer operations can not be remapped. If the common buffer - // is above 16MB, then it is not possible to generate a mapping, so return - // an error. - // - if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { - return EFI_UNSUPPORTED; - } - // - // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() - // is called later. - // - IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); - if (IsaMapInfo == NULL) { - *NumberOfBytes = 0; - return EFI_OUT_OF_RESOURCES; - } - // - // Return a pointer to the MAP_INFO structure in Mapping - // - *Mapping = IsaMapInfo; - - // - // Initialize the MAP_INFO structure - // - IsaMapInfo->Operation = Operation; - IsaMapInfo->NumberOfBytes = *NumberOfBytes; - IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); - IsaMapInfo->HostAddress = PhysicalAddress; - IsaMapInfo->MappedHostAddress = BASE_16MB - 1; - - // - // Allocate a buffer below 16MB to map the transfer to. - // - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiBootServicesData, - IsaMapInfo->NumberOfPages, - &IsaMapInfo->MappedHostAddress - ); - if (EFI_ERROR (Status)) { - FreePool (IsaMapInfo); - *NumberOfBytes = 0; - *Mapping = NULL; - return Status; - } - // - // If this is a read operation from the DMA agents's point of view, - // then copy the contents of the real buffer into the mapped buffer - // so the DMA agent can read the contents of the real buffer. - // - if (Operation == EfiIsaIoOperationSlaveRead) { - CopyMem ( - (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, - (VOID *) (UINTN) IsaMapInfo->HostAddress, - IsaMapInfo->NumberOfBytes - ); - } - // - // The DeviceAddress is the address of the maped buffer below 16 MB - // - *DeviceAddress = IsaMapInfo->MappedHostAddress; - } else { - // - // The transfer is below 16 MB, so the DeviceAddress is simply the - // HostAddress - // - *DeviceAddress = PhysicalAddress; - } - - // - // Figure out what to program into the DMA Channel Mode Register - // - DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); - if (Operation == EfiIsaIoOperationSlaveRead) { - DmaMode |= V_8237_DMA_CHMODE_MEM2IO; - } else { - DmaMode |= V_8237_DMA_CHMODE_IO2MEM; - } - // - // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo - // - DmaMode |= V_8237_DMA_CHMODE_SINGLE; - - // - // A Slave DMA transfer can not cross a 64K boundary. - // Compute *NumberOfBytes based on this restriction. - // - MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); - if (*NumberOfBytes > MaxNumberOfBytes) { - *NumberOfBytes = MaxNumberOfBytes; - } - // - // Compute the values to program into the BaseAddress and Count registers - // of the Slave DMA controller - // - BaseAddress = (UINT32) (*DeviceAddress); - Count = (UINT16) (*NumberOfBytes - 1); - // - // Program the DMA Write Single Mask Register for ChannelNumber - // Clear the DMA Byte Pointer Register - // - DmaMask = R_8237_DMA_WRSMSK_CH0_3; - DmaClear = R_8237_DMA_CBPR_CH0_3; - DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; - - Status = WritePort ( - This, - DmaMask, - (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort ( - This, - DmaClear, - (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, DmaChannelMode, DmaMode); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WriteDmaPort ( - This, - mDmaRegisters[ChannelNumber].Address, - mDmaRegisters[ChannelNumber].Page, - mDmaRegisters[ChannelNumber].Count, - BaseAddress, - Count - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort ( - This, - DmaMask, - (UINT8) (ChannelNumber & 0x03) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - Maps a memory region for DMA. This implementation implement the - the full mapping support. - - @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param Operation Indicates the type of DMA (slave or bus master), and if - the DMA operation is going to read or write to system memory. - @param ChannelNumber The slave channel number to use for this DMA operation. - If Operation and ChannelAttributes shows that this device - performs bus mastering DMA, then this field is ignored. - The legal range for this field is 0..7. - @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation - @param HostAddress The system memory address to map to the device. - @param NumberOfBytes On input the number of bytes to map. On output the number - of bytes that were mapped. - @param DeviceAddress The resulting map address for the bus master device to use - to access the hosts HostAddress. - @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). - - @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. - @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. -**/ -EFI_STATUS -IsaIoMapFullSupport ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ) -{ - EFI_STATUS Status; - BOOLEAN Master; - BOOLEAN Read; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - ISA_MAP_INFO *IsaMapInfo; - UINT8 DmaMode; - UINTN MaxNumberOfBytes; - UINT32 BaseAddress; - UINT16 Count; - UINT8 DmaMask; - UINT8 DmaClear; - UINT8 DmaChannelMode; - - if ((NULL == This) || - (NULL == HostAddress) || - (NULL == NumberOfBytes) || - (NULL == DeviceAddress) || - (NULL == Mapping) - ) { - return EFI_INVALID_PARAMETER; - } - - // - // Initialize the return values to their defaults - // - *Mapping = NULL; - - // - // Make sure the Operation parameter is valid - // - if ((UINT32)Operation >= EfiIsaIoOperationMaximum) { - return EFI_INVALID_PARAMETER; - } - - if (ChannelNumber >= 8) { - return EFI_INVALID_PARAMETER; - } - - // - // See if this is a Slave DMA Operation - // - Master = TRUE; - Read = FALSE; - if (Operation == EfiIsaIoOperationSlaveRead) { - Operation = EfiIsaIoOperationBusMasterRead; - Master = FALSE; - Read = TRUE; - } - - if (Operation == EfiIsaIoOperationSlaveWrite) { - Operation = EfiIsaIoOperationBusMasterWrite; - Master = FALSE; - Read = FALSE; - } - - if (!Master) { - // - // Make sure that ChannelNumber is a valid channel number - // Channel 4 is used to cascade, so it is illegal. - // - if (ChannelNumber == 4 || ChannelNumber > 7) { - return EFI_INVALID_PARAMETER; - } - // - // This implementation only support COMPATIBLE DMA Transfers - // - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) { - return EFI_INVALID_PARAMETER; - } - - if ((ChannelAttributes & - (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A | - EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B | - EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) { - return EFI_INVALID_PARAMETER; - } - - if (ChannelNumber < 4) { - // - // If this is Channel 0..3, then the width must be 8 bit - // - if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) || - ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0) - ) { - return EFI_INVALID_PARAMETER; - } - } else { - // - // If this is Channel 4..7, then the width must be 16 bit - // - if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) || - ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) { - return EFI_INVALID_PARAMETER; - } - } - // - // Either Demand Mode or Single Mode must be selected, but not both - // - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { - return EFI_INVALID_PARAMETER; - } - } else { - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) { - return EFI_INVALID_PARAMETER; - } - } - } - // - // Map the HostAddress to a DeviceAddress. - // - PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; - if ((PhysicalAddress +*NumberOfBytes) > BASE_16MB) { - // - // Common Buffer operations can not be remapped. If the common buffer - // is above 16MB, then it is not possible to generate a mapping, so return - // an error. - // - if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { - return EFI_UNSUPPORTED; - } - // - // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() - // is called later. - // - IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); - if (IsaMapInfo == NULL) { - *NumberOfBytes = 0; - return EFI_OUT_OF_RESOURCES; - } - // - // Return a pointer to the MAP_INFO structure in Mapping - // - *Mapping = IsaMapInfo; - - // - // Initialize the MAP_INFO structure - // - IsaMapInfo->Operation = Operation; - IsaMapInfo->NumberOfBytes = *NumberOfBytes; - IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); - IsaMapInfo->HostAddress = PhysicalAddress; - IsaMapInfo->MappedHostAddress = BASE_16MB - 1; - - // - // Allocate a buffer below 16MB to map the transfer to. - // - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiBootServicesData, - IsaMapInfo->NumberOfPages, - &IsaMapInfo->MappedHostAddress - ); - if (EFI_ERROR (Status)) { - FreePool (IsaMapInfo); - *NumberOfBytes = 0; - *Mapping = NULL; - return Status; - } - // - // If this is a read operation from the DMA agents's point of view, - // then copy the contents of the real buffer into the mapped buffer - // so the DMA agent can read the contents of the real buffer. - // - if (Operation == EfiIsaIoOperationBusMasterRead) { - CopyMem ( - (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, - (VOID *) (UINTN) IsaMapInfo->HostAddress, - IsaMapInfo->NumberOfBytes - ); - } - // - // The DeviceAddress is the address of the maped buffer below 16 MB - // - *DeviceAddress = IsaMapInfo->MappedHostAddress; - } else { - // - // The transfer is below 16 MB, so the DeviceAddress is simply the - // HostAddress - // - *DeviceAddress = PhysicalAddress; - } - // - // If this is a Bus Master operation then return - // - if (Master) { - return EFI_SUCCESS; - } - // - // Figure out what to program into the DMA Channel Mode Register - // - DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); - if (Read) { - DmaMode |= V_8237_DMA_CHMODE_MEM2IO; - } else { - DmaMode |= V_8237_DMA_CHMODE_IO2MEM; - } - - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) { - DmaMode |= B_8237_DMA_CHMODE_AE; - } - - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { - DmaMode |= V_8237_DMA_CHMODE_DEMAND; - } - - if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { - DmaMode |= V_8237_DMA_CHMODE_SINGLE; - } - // - // A Slave DMA transfer can not cross a 64K boundary. - // Compute *NumberOfBytes based on this restriction. - // - MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); - if (*NumberOfBytes > MaxNumberOfBytes) { - *NumberOfBytes = MaxNumberOfBytes; - } - // - // Compute the values to program into the BaseAddress and Count registers - // of the Slave DMA controller - // - if (ChannelNumber < 4) { - BaseAddress = (UINT32) (*DeviceAddress); - Count = (UINT16) (*NumberOfBytes - 1); - } else { - BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1)); - Count = (UINT16) ((*NumberOfBytes - 1) >> 1); - } - // - // Program the DMA Write Single Mask Register for ChannelNumber - // Clear the DMA Byte Pointer Register - // - if (ChannelNumber < 4) { - DmaMask = R_8237_DMA_WRSMSK_CH0_3; - DmaClear = R_8237_DMA_CBPR_CH0_3; - DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; - } else { - DmaMask = R_8237_DMA_WRSMSK_CH4_7; - DmaClear = R_8237_DMA_CBPR_CH4_7; - DmaChannelMode = R_8237_DMA_CHMODE_CH4_7; - } - - Status = WritePort ( - This, - DmaMask, - (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort ( - This, - DmaClear, - (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort (This, DmaChannelMode, DmaMode); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WriteDmaPort ( - This, - mDmaRegisters[ChannelNumber].Address, - mDmaRegisters[ChannelNumber].Page, - mDmaRegisters[ChannelNumber].Count, - BaseAddress, - Count - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = WritePort ( - This, - DmaMask, - (UINT8) (ChannelNumber & 0x03) - ); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - Maps a memory region for DMA - - @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param Operation Indicates the type of DMA (slave or bus master), and if - the DMA operation is going to read or write to system memory. - @param ChannelNumber The slave channel number to use for this DMA operation. - If Operation and ChannelAttributes shows that this device - performs bus mastering DMA, then this field is ignored. - The legal range for this field is 0..7. - @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation - @param HostAddress The system memory address to map to the device. - @param NumberOfBytes On input the number of bytes to map. On output the number - of bytes that were mapped. - @param DeviceAddress The resulting map address for the bus master device to use - to access the hosts HostAddress. - @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). - - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. - @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -EFIAPI -IsaIoMap ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ) -{ - // - // Check if DMA is supported. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { - return EFI_UNSUPPORTED; - } - // - // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for - // ISA Bus Master. - // - // So we just return EFI_UNSUPPORTED for these functions. - // - if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) { - return IsaIoMapOnlySupportSlaveReadWrite ( - This, - Operation, - ChannelNumber, - ChannelAttributes, - HostAddress, - NumberOfBytes, - DeviceAddress, - Mapping - ); - - } else { - return IsaIoMapFullSupport ( - This, - Operation, - ChannelNumber, - ChannelAttributes, - HostAddress, - NumberOfBytes, - DeviceAddress, - Mapping - ); - } -} - -/** - Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Type The type allocation to perform. - @param[in] MemoryType The type of memory to allocate. - @param[in] Pages The number of pages to allocate. - @param[out] HostAddress A pointer to store the base address of the allocated range. - @param[in] Attributes The requested bit mask of attributes for the allocated range. - - @retval EFI_SUCCESS The requested memory pages were allocated. - @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL - @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified - by HostAddress, Pages, and Type is not available for common buffer use. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -EFIAPI -IsaIoAllocateBuffer ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ALLOCATE_TYPE Type, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Pages, - OUT VOID **HostAddress, - IN UINT64 Attributes - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - - // - // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for - // ISA Bus Master. - // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. - // - if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || - ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { - return EFI_UNSUPPORTED; - } - - if (HostAddress == NULL) { - return EFI_INVALID_PARAMETER; - } - - if ((UINT32)Type >= MaxAllocateType) { - return EFI_INVALID_PARAMETER; - } - // - // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData - // - if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { - return EFI_INVALID_PARAMETER; - } - - if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) { - return EFI_UNSUPPORTED; - } - - PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (BASE_16MB - 1); - if (Type == AllocateAddress) { - if ((UINTN) (*HostAddress) >= BASE_16MB) { - return EFI_UNSUPPORTED; - } else { - PhysicalAddress = (UINTN) (*HostAddress); - } - } - - if (Type == AllocateAnyPages) { - Type = AllocateMaxAddress; - } - - Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - return Status; - } - - *HostAddress = (VOID *) (UINTN) PhysicalAddress; - return Status; -} - -/** - Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Pages The number of pages to free. - @param[in] HostAddress The base address of the allocated range. - - @retval EFI_SUCCESS The requested memory pages were freed. - @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). -**/ -EFI_STATUS -EFIAPI -IsaIoFreeBuffer ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINTN Pages, - IN VOID *HostAddress - ) -{ - EFI_STATUS Status; - - // - // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for - // ISA Bus Master. - // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. - // - if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || - ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { - return EFI_UNSUPPORTED; - } - - Status = gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, - Pages - ); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR - ); - } - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h deleted file mode 100644 index cc4a1f8b80..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h +++ /dev/null @@ -1,331 +0,0 @@ -/** @file - The header file for EFI_ISA_IO protocol implementation. - -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 _ISA_IO_H_ -#define _ISA_IO_H_ - -#include "IsaDriver.h" - -// -// Bits definition of PcdIsaBusSupportedFeatures -// -#define PCD_ISA_BUS_SUPPORT_DMA BIT0 -#define PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA BIT1 -#define PCD_ISA_BUS_SUPPORT_ISA_MEMORY BIT2 - -// -// ISA I/O Support Function Prototypes -// - -/** - Verifies access to an ISA device - - @param[in] IsaIoDevice The ISA device to be verified. - @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. - @param[in] Width The width of the memory operation. - @param[in] Count The number of memory operations to perform. - @param[in] Offset The offset in ISA memory space to start the memory operation. - - @retval EFI_SUCCESS Verify success. - @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. - @retval EFI_UNSUPPORTED The device ont support the access type. -**/ -EFI_STATUS -IsaIoVerifyAccess ( - IN ISA_IO_DEVICE *IsaIoDevice, - IN ISA_ACCESS_TYPE Type, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINTN Count, - IN UINT32 Offset - ); - -/** - Performs an ISA I/O Read Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O operation. - @param[in] Offset The offset in ISA I/O space to start the I/O operation. - @param[in] Count The number of I/O operations to perform. - @param[out] Buffer The destination buffer to store the results - - @retval EFI_SUCCESS The data was read from the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoIoRead ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - OUT VOID *Buffer - ); - -/** - Performs an ISA I/O Write Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O operation. - @param[in] Offset The offset in ISA I/O space to start the I/O operation. - @param[in] Count The number of I/O operations to perform. - @param[in] Buffer The source buffer to write data from - - @retval EFI_SUCCESS The data was writen to the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoIoWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN VOID *Buffer - ); - -/** - Maps a memory region for DMA - - @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param Operation Indicates the type of DMA (slave or bus master), and if - the DMA operation is going to read or write to system memory. - @param ChannelNumber The slave channel number to use for this DMA operation. - If Operation and ChannelAttributes shows that this device - performs bus mastering DMA, then this field is ignored. - The legal range for this field is 0..7. - @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation - @param HostAddress The system memory address to map to the device. - @param NumberOfBytes On input the number of bytes to map. On output the number - of bytes that were mapped. - @param DeviceAddress The resulting map address for the bus master device to use - to access the hosts HostAddress. - @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). - - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. - @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -EFIAPI -IsaIoMap ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ); - -/** - Unmaps a memory region for DMA - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). - - @retval EFI_SUCCESS The range was unmapped. - @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. -**/ -EFI_STATUS -EFIAPI -IsaIoUnmap ( - IN EFI_ISA_IO_PROTOCOL *This, - IN VOID *Mapping - ); - -/** - Flushes any posted write data to the system memory. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - - @retval EFI_SUCCESS The buffers were flushed. - @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. -**/ -EFI_STATUS -EFIAPI -IsaIoFlush ( - IN EFI_ISA_IO_PROTOCOL *This - ); - -/** - Writes I/O operation base address and count number to a 8 bit I/O Port. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] AddrOffset The address' offset. - @param[in] PageOffset The page's offest. - @param[in] CountOffset The count's offset. - @param[in] BaseAddress The base address. - @param[in] Count The number of I/O operations to perform. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Parameter is invalid. - @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -WriteDmaPort ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINT32 AddrOffset, - IN UINT32 PageOffset, - IN UINT32 CountOffset, - IN UINT32 BaseAddress, - IN UINT16 Count - ); - -/** - Writes an 8-bit I/O Port - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Offset The offset in ISA IO space to start the IO operation. - @param[in] Value The data to write port. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Parameter is invalid. - @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -WritePort ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINT32 Offset, - IN UINT8 Value - ); - -/** - Performs an ISA Memory Read Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory operation. - @param[in] Offset The offset in ISA memory space to start the memory operation. - @param[in] Count The number of memory operations to perform. - @param[out] Buffer The destination buffer to store the results - - @retval EFI_SUCCESS The data was read from the device successfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoMemRead ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - OUT VOID *Buffer - ); - - -/** - Performs an ISA Memory Write Cycle - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory operation. - @param[in] Offset The offset in ISA memory space to start the memory operation. - @param[in] Count The number of memory operations to perform. - @param[in] Buffer The source buffer to write data from - - @retval EFI_SUCCESS The data was written to the device sucessfully. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoMemWrite ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN VOID *Buffer - ); - -/** - Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the memory copy operation. - @param[in] DestOffset The offset of the destination - @param[in] SrcOffset The offset of the source - @param[in] Count The number of memory copy operations to perform - - @retval EFI_SUCCESS The data was copied sucessfully. - @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -IsaIoCopyMem ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 DestOffset, - IN UINT32 SrcOffset, - IN UINTN Count - ); - -/** - Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Type The type allocation to perform. - @param[in] MemoryType The type of memory to allocate. - @param[in] Pages The number of pages to allocate. - @param[out] HostAddress A pointer to store the base address of the allocated range. - @param[in] Attributes The requested bit mask of attributes for the allocated range. - - @retval EFI_SUCCESS The requested memory pages were allocated. - @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL - @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified - by HostAddress, Pages, and Type is not available for common buffer use. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -**/ -EFI_STATUS -EFIAPI -IsaIoAllocateBuffer ( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ALLOCATE_TYPE Type, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Pages, - OUT VOID **HostAddress, - IN UINT64 Attributes - ); - -/** - Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Pages The number of pages to free. - @param[in] HostAddress The base address of the allocated range. - - @retval EFI_SUCCESS The requested memory pages were freed. - @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). -**/ -EFI_STATUS -EFIAPI -IsaIoFreeBuffer ( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINTN Pages, - IN VOID *HostAddress - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf deleted file mode 100644 index 499cf434f5..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf +++ /dev/null @@ -1,71 +0,0 @@ -## @file -# Produces an instance of the ISA I/O Protocol for every SIO controller. -# -# Produces an instance of the ISA I/O Protocol for every SIO controller. The ISA -# I/O protocols are installed based off of the information provided by each -# instance of the SIO Protocol found. -# -# 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 -# 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 = IsaIoDxe - MODULE_UNI_FILE = IsaIoDxe.uni - FILE_GUID = 61AD3083-DCAD-4850-A50C-73B23B3B14F9 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializeIsaIo - -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# DRIVER_BINDING = gIsaIoDriver -# COMPONENT_NAME = gIsaIoComponentName; -# COMPONENT_NAME2 = gIsaIoComponentName2; -# - -[Sources] - ComponentName.h - ComponentName.c - IsaIo.h - IsaIo.c - IsaDriver.h - IsaDriver.c - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - PcdLib - ReportStatusCodeLib - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - DevicePathLib - UefiLib - UefiDriverEntryPoint - DebugLib - -[Protocols] - gEfiIsaIoProtocolGuid ## BY_START - gEfiSioProtocolGuid ## TO_START - gEfiPciIoProtocolGuid ## TO_START - gEfiDevicePathProtocolGuid ## TO_START - gEfiGenericMemTestProtocolGuid ## TO_START - -[Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures ## CONSUMES - -[UserExtensions.TianoCore."ExtraFiles"] - IsaIoDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.uni deleted file mode 100644 index 9cfecb2395..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni deleted file mode 100644 index 6b6dc83e89..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/ComponentName.c deleted file mode 100644 index ef24008f6b..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/ComponentName.c +++ /dev/null @@ -1,272 +0,0 @@ -/** @file - UEFI Component Name and Name2 protocol for Isa serial driver. - -Copyright (c) 2006 - 2015, Intel 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 "Serial.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaSerialComponentName = { - IsaSerialComponentNameGetDriverName, - IsaSerialComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaSerialComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaSerialComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaSerialComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaSerialDriverNameTable[] = { - { - "eng;en", - L"ISA Serial Driver" - }, - { - NULL, - NULL - } -}; - -GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 mSerialPortName[] = L"ISA Serial Port # "; - -/** - 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 -IsaSerialComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mIsaSerialDriverNameTable, - DriverName, - (BOOLEAN)(This == &gIsaSerialComponentName) - ); -} - -/** - 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 -IsaSerialComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - EFI_SERIAL_IO_PROTOCOL *SerialIo; - SERIAL_DEV *SerialDevice; - EFI_UNICODE_STRING_TABLE *ControllerNameTable; - - // - // Make sure this driver is currently managing ControllerHandle - // - Status = EfiTestManagedDevice ( - ControllerHandle, - gSerialControllerDriver.DriverBindingHandle, - &gEfiIsaIoProtocolGuid - ); - if (EFI_ERROR (Status)) { - return Status; - } - - ControllerNameTable = NULL; - if (ChildHandle != NULL) { - Status = EfiTestChildHandle ( - ControllerHandle, - ChildHandle, - &gEfiIsaIoProtocolGuid - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the Serial I/O Protocol from the child handle - // - Status = gBS->OpenProtocol ( - ChildHandle, - &gEfiSerialIoProtocolGuid, - (VOID **) &SerialIo, - gSerialControllerDriver.DriverBindingHandle, - ChildHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the Serial Controller's Device structure - // - SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo); - ControllerNameTable = SerialDevice->ControllerNameTable; - } - - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - ControllerNameTable, - ControllerName, - (BOOLEAN)(This == &gIsaSerialComponentName) - ); -} - -/** - Add the ISO639-2 and RFC4646 component name both for the Serial IO device - - @param SerialDevice A pointer to the SERIAL_DEV instance. - - @param IsaIo A pointer to the EFI_ISA_IO_PROTOCOL instance. - -**/ -VOID -AddName ( - IN SERIAL_DEV *SerialDevice, - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - mSerialPortName[(sizeof (mSerialPortName) / 2) - 2] = (CHAR16) (L'0' + (UINT8) IsaIo->ResourceList->Device.UID); - AddUnicodeString2 ( - "eng", - gIsaSerialComponentName.SupportedLanguages, - &SerialDevice->ControllerNameTable, - mSerialPortName, - TRUE - ); - AddUnicodeString2 ( - "en", - gIsaSerialComponentName2.SupportedLanguages, - &SerialDevice->ControllerNameTable, - mSerialPortName, - FALSE - ); - -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf b/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf deleted file mode 100644 index 4abaac9ff8..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf +++ /dev/null @@ -1,80 +0,0 @@ -## @file -# Serial driver for standard UARTS on an ISA bus. -# -# Produces the Serial I/O protocol for standard UARTS using ISA I/O. This driver -# supports the 8250, 16450, 16550 and 16550A UART types. -# -# Copyright (c) 2007 - 2015, Intel 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 = IsaSerialDxe - MODULE_UNI_FILE = IsaSerialDxe.uni - FILE_GUID = 93B80003-9FB3-11d4-9A3A-0090273FC14D - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializeIsaSerial - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# -# DRIVER_BINDING = gSerialControllerDriver -# COMPONENT_NAME = gIsaSerialComponentName -# COMPONENT_NAME2 = gIsaSerialComponentName2 -# - -[Sources] - ComponentName.c - Serial.h - Serial.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - PcdLib - ReportStatusCodeLib - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - DevicePathLib - UefiLib - UefiDriverEntryPoint - DebugLib - -[Guids] - gEfiUartDevicePathGuid ## SOMETIMES_CONSUMES ## GUID - -[Protocols] - gEfiIsaIoProtocolGuid ## TO_START - gEfiDevicePathProtocolGuid ## TO_START - gEfiSerialIoProtocolGuid ## BY_START - gEfiDevicePathProtocolGuid ## BY_START - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE ## CONSUMES - -[Pcd] - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 ## CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8 ## CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1 ## CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1 ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|1843200 ## CONSUMES - -[UserExtensions.TianoCore."ExtraFiles"] - IsaSerialDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni deleted file mode 100644 index 6b99f490e5..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni b/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni deleted file mode 100644 index 47bc80b42b..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c b/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c deleted file mode 100644 index 57ee669d14..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c +++ /dev/null @@ -1,2038 +0,0 @@ -/** @file - Serial driver for standard UARTS on an ISA bus. - -Copyright (c) 2006 - 2015, Intel 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 "Serial.h" - -// -// ISA Serial Driver Global Variables -// -EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = { - SerialControllerDriverSupported, - SerialControllerDriverStart, - SerialControllerDriverStop, - 0xa, - NULL, - NULL -}; - - -SERIAL_DEV gSerialDevTempate = { - SERIAL_DEV_SIGNATURE, - NULL, - { // SerialIo - SERIAL_IO_INTERFACE_REVISION, - IsaSerialReset, - IsaSerialSetAttributes, - IsaSerialSetControl, - IsaSerialGetControl, - IsaSerialWrite, - IsaSerialRead, - NULL - }, - { // SerialMode - SERIAL_PORT_SUPPORT_CONTROL_MASK, - SERIAL_PORT_DEFAULT_TIMEOUT, - 0, - SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH, - 0, - 0, - 0 - }, - NULL, - NULL, - { // UartDevicePath - { - MESSAGING_DEVICE_PATH, - MSG_UART_DP, - { - (UINT8) (sizeof (UART_DEVICE_PATH)), - (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) - } - }, - 0, - 0, - 0, - 0, - 0 - }, - NULL, - 0, //BaseAddress - { - 0, - 0, - SERIAL_MAX_BUFFER_SIZE, - { 0 } - }, - { - 0, - 0, - SERIAL_MAX_BUFFER_SIZE, - { 0 } - }, - FALSE, - FALSE, - Uart16550A, - NULL -}; - -/** - Check the device path node whether it's the Flow Control node or not. - - @param[in] FlowControl The device path node to be checked. - - @retval TRUE It's the Flow Control node. - @retval FALSE It's not. - -**/ -BOOLEAN -IsUartFlowControlNode ( - IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl - ) -{ - return (BOOLEAN) ( - (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) && - (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) && - (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid)) - ); -} - -/** - Check the device path node whether it contains Flow Control node or not. - - @param[in] DevicePath The device path to be checked. - - @retval TRUE It contains the Flow Control node. - @retval FALSE It doesn't. - -**/ -BOOLEAN -ContainsFlowControl ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - while (!IsDevicePathEnd (DevicePath)) { - if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) { - return TRUE; - } - DevicePath = NextDevicePathNode (DevicePath); - } - - return FALSE; -} - -/** - The user Entry Point for module IsaSerial. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -InitializeIsaSerial ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gSerialControllerDriver, - ImageHandle, - &gIsaSerialComponentName, - &gIsaSerialComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - // - // Initialize UART default setting in gSerialDevTempate - // - gSerialDevTempate.SerialMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); - gSerialDevTempate.SerialMode.DataBits = PcdGet8 (PcdUartDefaultDataBits); - gSerialDevTempate.SerialMode.Parity = PcdGet8 (PcdUartDefaultParity); - gSerialDevTempate.SerialMode.StopBits = PcdGet8 (PcdUartDefaultStopBits); - gSerialDevTempate.UartDevicePath.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); - gSerialDevTempate.UartDevicePath.DataBits = PcdGet8 (PcdUartDefaultDataBits); - gSerialDevTempate.UartDevicePath.Parity = PcdGet8 (PcdUartDefaultParity); - gSerialDevTempate.UartDevicePath.StopBits = PcdGet8 (PcdUartDefaultStopBits); - - return Status; -} - -/** - Check to see if this driver supports the given controller - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @return EFI_SUCCESS This driver can support the given controller - -**/ -EFI_STATUS -EFIAPI -SerialControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) - -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_ISA_IO_PROTOCOL *IsaIo; - UART_DEVICE_PATH *UartNode; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; - UINTN EntryCount; - UINTN Index; - BOOLEAN HasFlowControl; - - // - // Check RemainingDevicePath validation - // - if (RemainingDevicePath != NULL) { - // - // Check if RemainingDevicePath is the End of Device Path Node, - // if yes, go on checking other conditions - // - if (!IsDevicePathEnd (RemainingDevicePath)) { - // - // If RemainingDevicePath isn't the End of Device Path Node, - // check its validation - // - Status = EFI_UNSUPPORTED; - - UartNode = (UART_DEVICE_PATH *) RemainingDevicePath; - if (UartNode->Header.Type != MESSAGING_DEVICE_PATH || - UartNode->Header.SubType != MSG_UART_DP || - sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UartNode) - ) { - goto Error; - } - - if (UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) { - goto Error; - } - - if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) { - goto Error; - } - - if (UartNode->DataBits < 5 || UartNode->DataBits > 8) { - goto Error; - } - - if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) { - goto Error; - } - - if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) { - goto Error; - } - - if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) { - goto Error; - } - - FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode); - if (IsUartFlowControlNode (FlowControlNode)) { - // - // If the second node is Flow Control Node, - // return error when it request other than hardware flow control. - // - if ((ReadUnaligned32 (&FlowControlNode->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) { - goto Error; - } - } - } - } - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (Status == EFI_ALREADY_STARTED) { - if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) { - // - // If RemainingDevicePath is NULL or is the End of Device Path Node - // - return EFI_SUCCESS; - } - // - // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node, - // return unsupported, and vice versa. - // - Status = gBS->OpenProtocolInformation ( - Controller, - &gEfiIsaIoProtocolGuid, - &OpenInfoBuffer, - &EntryCount - ); - if (EFI_ERROR (Status)) { - return Status; - } - - for (Index = 0; Index < EntryCount; Index++) { - if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { - Status = gBS->OpenProtocol ( - OpenInfoBuffer[Index].ControllerHandle, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - HasFlowControl = ContainsFlowControl (RemainingDevicePath); - if (HasFlowControl ^ ContainsFlowControl (DevicePath)) { - Status = EFI_UNSUPPORTED; - } - } - break; - } - } - FreePool (OpenInfoBuffer); - return Status; - } - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Close the I/O Abstraction(s) used to perform the supported test - // - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Open the EFI Device Path protocol needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Use the ISA I/O Protocol to see if Controller is standard ISA UART that - // can be managed by this driver. - // - Status = EFI_SUCCESS; - if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x501)) { - Status = EFI_UNSUPPORTED; - goto Error; - } - -Error: - // - // Close protocol, don't use device path protocol in the Support() function - // - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Start to management the controller passed in - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @return EFI_SUCCESS Driver is started successfully - -**/ -EFI_STATUS -EFIAPI -SerialControllerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) - -{ - EFI_STATUS Status; - EFI_ISA_IO_PROTOCOL *IsaIo; - SERIAL_DEV *SerialDevice; - UINTN Index; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; - UINTN EntryCount; - EFI_SERIAL_IO_PROTOCOL *SerialIo; - UART_DEVICE_PATH *Uart; - UINT32 FlowControlMap; - UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; - EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; - UINT32 Control; - - SerialDevice = NULL; - // - // Get the Parent Device Path - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { - return Status; - } - // - // Report status code enable the serial - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT, - ParentDevicePath - ); - - // - // Grab the IO abstraction we need to get any work done - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { - goto Error; - } - - if (Status == EFI_ALREADY_STARTED) { - - if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) { - // - // If RemainingDevicePath is NULL or is the End of Device Path Node - // - return EFI_SUCCESS; - } - - // - // Make sure a child handle does not already exist. This driver can only - // produce one child per serial port. - // - Status = gBS->OpenProtocolInformation ( - Controller, - &gEfiIsaIoProtocolGuid, - &OpenInfoBuffer, - &EntryCount - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = EFI_ALREADY_STARTED; - for (Index = 0; Index < EntryCount; Index++) { - if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { - Status = gBS->OpenProtocol ( - OpenInfoBuffer[Index].ControllerHandle, - &gEfiSerialIoProtocolGuid, - (VOID **) &SerialIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - Uart = (UART_DEVICE_PATH *) RemainingDevicePath; - Status = SerialIo->SetAttributes ( - SerialIo, - Uart->BaudRate, - SerialIo->Mode->ReceiveFifoDepth, - SerialIo->Mode->Timeout, - (EFI_PARITY_TYPE) Uart->Parity, - Uart->DataBits, - (EFI_STOP_BITS_TYPE) Uart->StopBits - ); - - FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); - if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) { - Status = SerialIo->GetControl (SerialIo, &Control); - if (!EFI_ERROR (Status)) { - if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) { - Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; - } else { - Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; - } - // - // Clear the bits that are not allowed to pass to SetControl - // - Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | - EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | - EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE); - Status = SerialIo->SetControl (SerialIo, Control); - } - } - } - break; - } - } - - FreePool (OpenInfoBuffer); - return Status; - } - - if (RemainingDevicePath != NULL) { - if (IsDevicePathEnd (RemainingDevicePath)) { - // - // If RemainingDevicePath is the End of Device Path Node, - // skip enumerate any device and return EFI_SUCESSS - // - return EFI_SUCCESS; - } - } - - // - // Initialize the serial device instance - // - SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTempate); - if (SerialDevice == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Error; - } - - SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode); - SerialDevice->IsaIo = IsaIo; - SerialDevice->ParentDevicePath = ParentDevicePath; - FlowControl = NULL; - FlowControlMap = 0; - - // - // Check if RemainingDevicePath is NULL, - // if yes, use the values from the gSerialDevTempate as no remaining device path was - // passed in. - // - if (RemainingDevicePath != NULL) { - // - // If RemainingDevicePath isn't NULL, - // match the configuration of the RemainingDevicePath. IsHandleSupported() - // already checked to make sure the RemainingDevicePath contains settings - // that we can support. - // - CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); - FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath); - if (IsUartFlowControlNode (FlowControl)) { - FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap); - } else { - FlowControl = NULL; - } - } - - AddName (SerialDevice, IsaIo); - - for (Index = 0; SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) { - if (SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) { - SerialDevice->BaseAddress = (UINT16) SerialDevice->IsaIo->ResourceList->ResourceItem[Index].StartRange; - } - } - - SerialDevice->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE); - - // - // Report status code the serial present - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT, - ParentDevicePath - ); - - if (!IsaSerialPortPresent (SerialDevice)) { - Status = EFI_DEVICE_ERROR; - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE, - EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT, - ParentDevicePath - ); - goto Error; - } - - // - // Build the device path by appending the UART node to the ParentDevicePath. - // The Uart setings are zero here, since SetAttribute() will update them to match - // the default setings. - // - SerialDevice->DevicePath = AppendDevicePathNode ( - ParentDevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath - ); - // - // Only produce the Flow Control node when remaining device path has it - // - if (FlowControl != NULL) { - TempDevicePath = SerialDevice->DevicePath; - if (TempDevicePath != NULL) { - SerialDevice->DevicePath = AppendDevicePathNode ( - TempDevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) FlowControl - ); - FreePool (TempDevicePath); - } - } - if (SerialDevice->DevicePath == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Error; - } - - // - // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. - // - SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate; - SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits; - SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity; - SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits; - - // - // Issue a reset to initialize the COM port - // - Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE, - EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT, - ParentDevicePath - ); - goto Error; - } - // - // Install protocol interfaces for the serial device. - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &SerialDevice->Handle, - &gEfiDevicePathProtocolGuid, - SerialDevice->DevicePath, - &gEfiSerialIoProtocolGuid, - &SerialDevice->SerialIo, - NULL - ); - if (EFI_ERROR (Status)) { - goto Error; - } - // - // Open For Child Device - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - SerialDevice->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - -Error: - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - if (SerialDevice != NULL) { - if (SerialDevice->DevicePath != NULL) { - gBS->FreePool (SerialDevice->DevicePath); - } - - FreeUnicodeStringTable (SerialDevice->ControllerNameTable); - gBS->FreePool (SerialDevice); - } - } - - return Status; -} - -/** - Disconnect this driver with the controller, uninstall related protocol instance - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param NumberOfChildren Number of child device. - @param ChildHandleBuffer A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS Operation successfully - @retval EFI_DEVICE_ERROR Cannot stop the driver successfully - -**/ -EFI_STATUS -EFIAPI -SerialControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) - -{ - EFI_STATUS Status; - UINTN Index; - BOOLEAN AllChildrenStopped; - EFI_SERIAL_IO_PROTOCOL *SerialIo; - SERIAL_DEV *SerialDevice; - EFI_ISA_IO_PROTOCOL *IsaIo; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - - Status = gBS->HandleProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath - ); - - // - // Report the status code disable the serial - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT, - DevicePath - ); - - // - // Complete all outstanding transactions to Controller. - // Don't allow any new transaction to Controller to be started. - // - if (NumberOfChildren == 0) { - // - // Close the bus driver - // - Status = gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - Status = gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - return Status; - } - - AllChildrenStopped = TRUE; - - for (Index = 0; Index < NumberOfChildren; Index++) { - - Status = gBS->OpenProtocol ( - ChildHandleBuffer[Index], - &gEfiSerialIoProtocolGuid, - (VOID **) &SerialIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - - SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo); - - Status = gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - ChildHandleBuffer[Index] - ); - - Status = gBS->UninstallMultipleProtocolInterfaces ( - ChildHandleBuffer[Index], - &gEfiDevicePathProtocolGuid, - SerialDevice->DevicePath, - &gEfiSerialIoProtocolGuid, - &SerialDevice->SerialIo, - NULL - ); - if (EFI_ERROR (Status)) { - gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - ChildHandleBuffer[Index], - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - } else { - if (SerialDevice->DevicePath != NULL) { - gBS->FreePool (SerialDevice->DevicePath); - } - - FreeUnicodeStringTable (SerialDevice->ControllerNameTable); - gBS->FreePool (SerialDevice); - } - } - - if (EFI_ERROR (Status)) { - AllChildrenStopped = FALSE; - } - } - - if (!AllChildrenStopped) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Detect whether specific FIFO is full or not. - - @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO - - @return whether specific FIFO is full or not - -**/ -BOOLEAN -IsaSerialFifoFull ( - IN SERIAL_DEV_FIFO *Fifo - ) - -{ - if (Fifo->Surplus == 0) { - return TRUE; - } - - return FALSE; -} - -/** - Detect whether specific FIFO is empty or not. - - @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO - - @return whether specific FIFO is empty or not - -**/ -BOOLEAN -IsaSerialFifoEmpty ( - IN SERIAL_DEV_FIFO *Fifo - ) - -{ - if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) { - return TRUE; - } - - return FALSE; -} - -/** - Add data to specific FIFO. - - @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO - @param Data the data added to FIFO - - @retval EFI_SUCCESS Add data to specific FIFO successfully - @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full - -**/ -EFI_STATUS -IsaSerialFifoAdd ( - IN SERIAL_DEV_FIFO *Fifo, - IN UINT8 Data - ) - -{ - // - // if FIFO full can not add data - // - if (IsaSerialFifoFull (Fifo)) { - return EFI_OUT_OF_RESOURCES; - } - // - // FIFO is not full can add data - // - Fifo->Data[Fifo->Last] = Data; - Fifo->Surplus--; - Fifo->Last++; - if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) { - Fifo->Last = 0; - } - - return EFI_SUCCESS; -} - -/** - Remove data from specific FIFO. - - @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO - @param Data the data removed from FIFO - - @retval EFI_SUCCESS Remove data from specific FIFO successfully - @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty - -**/ -EFI_STATUS -IsaSerialFifoRemove ( - IN SERIAL_DEV_FIFO *Fifo, - OUT UINT8 *Data - ) - -{ - // - // if FIFO is empty, no data can remove - // - if (IsaSerialFifoEmpty (Fifo)) { - return EFI_OUT_OF_RESOURCES; - } - // - // FIFO is not empty, can remove data - // - *Data = Fifo->Data[Fifo->First]; - Fifo->Surplus++; - Fifo->First++; - if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) { - Fifo->First = 0; - } - - return EFI_SUCCESS; -} - -/** - Reads and writes all avaliable data. - - @param SerialDevice The device to flush - - @retval EFI_SUCCESS Data was read/written successfully. - @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when - this happens, pending writes are not done. - -**/ -EFI_STATUS -IsaSerialReceiveTransmit ( - IN SERIAL_DEV *SerialDevice - ) - -{ - SERIAL_PORT_LSR Lsr; - UINT8 Data; - BOOLEAN ReceiveFifoFull; - SERIAL_PORT_MSR Msr; - SERIAL_PORT_MCR Mcr; - UINTN TimeOut; - - Data = 0; - - // - // Begin the read or write - // - if (SerialDevice->SoftwareLoopbackEnable) { - do { - ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive); - if (!IsaSerialFifoEmpty (&SerialDevice->Transmit)) { - IsaSerialFifoRemove (&SerialDevice->Transmit, &Data); - if (ReceiveFifoFull) { - return EFI_OUT_OF_RESOURCES; - } - - IsaSerialFifoAdd (&SerialDevice->Receive, Data); - } - } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit)); - } else { - ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive); - // - // For full handshake flow control, tell the peer to send data - // if receive buffer is available. - // - if (SerialDevice->HardwareFlowControl && - !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)&& - !ReceiveFifoFull - ) { - Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Mcr.Bits.Rts = 1; - WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); - } - do { - Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - - // - // Flush incomming data to prevent a an overrun during a long write - // - if ((Lsr.Bits.Dr == 1) && !ReceiveFifoFull) { - ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive); - if (!ReceiveFifoFull) { - if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Oe == 1 || Lsr.Bits.Pe == 1 || Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE, - EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT, - SerialDevice->DevicePath - ); - if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Pe == 1|| Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) { - Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - continue; - } - } - - Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - - IsaSerialFifoAdd (&SerialDevice->Receive, Data); - - // - // For full handshake flow control, if receive buffer full - // tell the peer to stop sending data. - // - if (SerialDevice->HardwareFlowControl && - !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake) && - IsaSerialFifoFull (&SerialDevice->Receive) - ) { - Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Mcr.Bits.Rts = 0; - WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); - } - - - continue; - } else { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT, - SerialDevice->DevicePath - ); - } - } - // - // Do the write - // - if (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) { - // - // Make sure the transmit data will not be missed - // - if (SerialDevice->HardwareFlowControl) { - // - // For half handshake flow control assert RTS before sending. - // - if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) { - Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Mcr.Bits.Rts= 0; - WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); - } - // - // Wait for CTS - // - TimeOut = 0; - Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - while ((Msr.Bits.Dcd == 1) && ((Msr.Bits.Cts == 0) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) { - gBS->Stall (TIMEOUT_STALL_INTERVAL); - TimeOut++; - if (TimeOut > 5) { - break; - } - - Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - } - - if ((Msr.Bits.Dcd == 0) || ((Msr.Bits.Cts == 1) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) { - IsaSerialFifoRemove (&SerialDevice->Transmit, &Data); - WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data); - } - - // - // For half handshake flow control, tell DCE we are done. - // - if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) { - Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Mcr.Bits.Rts = 1; - WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); - } - } else { - IsaSerialFifoRemove (&SerialDevice->Transmit, &Data); - WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data); - } - } - } while (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)); - } - - return EFI_SUCCESS; -} - -// -// Interface Functions -// -/** - Reset serial device. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - - @retval EFI_SUCCESS Reset successfully - @retval EFI_DEVICE_ERROR Failed to reset - -**/ -EFI_STATUS -EFIAPI -IsaSerialReset ( - IN EFI_SERIAL_IO_PROTOCOL *This - ) -{ - EFI_STATUS Status; - SERIAL_DEV *SerialDevice; - SERIAL_PORT_LCR Lcr; - SERIAL_PORT_IER Ier; - SERIAL_PORT_MCR Mcr; - SERIAL_PORT_FCR Fcr; - EFI_TPL Tpl; - UINT32 Control; - - SerialDevice = SERIAL_DEV_FROM_THIS (This); - - // - // Report the status code reset the serial - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT, - SerialDevice->DevicePath - ); - - Tpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Make sure DLAB is 0. - // - Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Lcr.Bits.DLab = 0; - WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data); - - // - // Turn off all interrupts - // - Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Ier.Bits.Ravie = 0; - Ier.Bits.Theie = 0; - Ier.Bits.Rie = 0; - Ier.Bits.Mie = 0; - WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data); - - // - // Disable the FIFO. - // - Fcr.Bits.TrFIFOE = 0; - WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data); - - // - // Turn off loopback and disable device interrupt. - // - Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Mcr.Bits.Out1 = 0; - Mcr.Bits.Out2 = 0; - Mcr.Bits.Lme = 0; - WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); - - // - // Clear the scratch pad register - // - WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0); - - // - // Go set the current attributes - // - Status = This->SetAttributes ( - This, - This->Mode->BaudRate, - This->Mode->ReceiveFifoDepth, - This->Mode->Timeout, - (EFI_PARITY_TYPE) This->Mode->Parity, - (UINT8) This->Mode->DataBits, - (EFI_STOP_BITS_TYPE) This->Mode->StopBits - ); - - if (EFI_ERROR (Status)) { - gBS->RestoreTPL (Tpl); - return EFI_DEVICE_ERROR; - } - // - // Go set the current control bits - // - Control = 0; - if (SerialDevice->HardwareFlowControl) { - Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; - } - if (SerialDevice->SoftwareLoopbackEnable) { - Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE; - } - Status = This->SetControl ( - This, - Control - ); - - if (EFI_ERROR (Status)) { - gBS->RestoreTPL (Tpl); - return EFI_DEVICE_ERROR; - } - // - // for 16550A enable FIFO, 16550 disable FIFO - // - Fcr.Bits.TrFIFOE = 1; - Fcr.Bits.ResetRF = 1; - Fcr.Bits.ResetTF = 1; - WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data); - - // - // Reset the software FIFO - // - SerialDevice->Receive.First = 0; - SerialDevice->Receive.Last = 0; - SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE; - SerialDevice->Transmit.First = 0; - SerialDevice->Transmit.Last = 0; - SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE; - - gBS->RestoreTPL (Tpl); - - // - // Device reset is complete - // - return EFI_SUCCESS; -} - -/** - Set new attributes to a serial device. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param BaudRate The baudrate of the serial device - @param ReceiveFifoDepth The depth of receive FIFO buffer - @param Timeout The request timeout for a single char - @param Parity The type of parity used in serial device - @param DataBits Number of databits used in serial device - @param StopBits Number of stopbits used in serial device - - @retval EFI_SUCCESS The new attributes were set - @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value - @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6 - @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return) - -**/ -EFI_STATUS -EFIAPI -IsaSerialSetAttributes ( - IN EFI_SERIAL_IO_PROTOCOL *This, - IN UINT64 BaudRate, - IN UINT32 ReceiveFifoDepth, - IN UINT32 Timeout, - IN EFI_PARITY_TYPE Parity, - IN UINT8 DataBits, - IN EFI_STOP_BITS_TYPE StopBits - ) -{ - EFI_STATUS Status; - SERIAL_DEV *SerialDevice; - UINT32 Divisor; - UINT32 Remained; - SERIAL_PORT_LCR Lcr; - UART_DEVICE_PATH *Uart; - EFI_TPL Tpl; - - SerialDevice = SERIAL_DEV_FROM_THIS (This); - - // - // Check for default settings and fill in actual values. - // - if (BaudRate == 0) { - BaudRate = PcdGet64 (PcdUartDefaultBaudRate); - } - - if (ReceiveFifoDepth == 0) { - ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH; - } - - if (Timeout == 0) { - Timeout = SERIAL_PORT_DEFAULT_TIMEOUT; - } - - if (Parity == DefaultParity) { - Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity); - } - - if (DataBits == 0) { - DataBits = PcdGet8 (PcdUartDefaultDataBits); - } - - if (StopBits == DefaultStopBits) { - StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits); - } - // - // 5 and 6 data bits can not be verified on a 16550A UART - // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings. - // - if ((DataBits == 5) || (DataBits == 6)) { - return EFI_INVALID_PARAMETER; - } - // - // Make sure all parameters are valid - // - if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) { - return EFI_INVALID_PARAMETER; - } - // - // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200, - // 38400,57600,115200 - // - if (BaudRate < 75) { - BaudRate = 50; - } else if (BaudRate < 110) { - BaudRate = 75; - } else if (BaudRate < 134) { - BaudRate = 110; - } else if (BaudRate < 150) { - BaudRate = 134; - } else if (BaudRate < 300) { - BaudRate = 150; - } else if (BaudRate < 600) { - BaudRate = 300; - } else if (BaudRate < 1200) { - BaudRate = 600; - } else if (BaudRate < 1800) { - BaudRate = 1200; - } else if (BaudRate < 2000) { - BaudRate = 1800; - } else if (BaudRate < 2400) { - BaudRate = 2000; - } else if (BaudRate < 3600) { - BaudRate = 2400; - } else if (BaudRate < 4800) { - BaudRate = 3600; - } else if (BaudRate < 7200) { - BaudRate = 4800; - } else if (BaudRate < 9600) { - BaudRate = 7200; - } else if (BaudRate < 19200) { - BaudRate = 9600; - } else if (BaudRate < 38400) { - BaudRate = 19200; - } else if (BaudRate < 57600) { - BaudRate = 38400; - } else if (BaudRate < 115200) { - BaudRate = 57600; - } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) { - BaudRate = 115200; - } - - if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) { - return EFI_INVALID_PARAMETER; - } - - if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) { - return EFI_INVALID_PARAMETER; - } - - if ((Parity < NoParity) || (Parity > SpaceParity)) { - return EFI_INVALID_PARAMETER; - } - - if ((DataBits < 5) || (DataBits > 8)) { - return EFI_INVALID_PARAMETER; - } - - if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) { - return EFI_INVALID_PARAMETER; - } - - // - // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits - // - if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) { - return EFI_INVALID_PARAMETER; - } - - // - // Compute divisor use to program the baud rate using a round determination - // - Divisor = (UINT32) DivU64x32Remainder ( - PcdGet32 (PcdSerialClockRate), - ((UINT32) BaudRate * 16), - &Remained - ); - if (Remained != 0) { - Divisor += 1; - } - - if ((Divisor == 0) || ((Divisor & 0xffff0000) != 0)) { - return EFI_INVALID_PARAMETER; - } - - Tpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Compute the actual baud rate that the serial port will be programmed for. - // - BaudRate = PcdGet32 (PcdSerialClockRate) / Divisor / 16; - - // - // Put serial port on Divisor Latch Mode - // - Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Lcr.Bits.DLab = 1; - WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data); - - // - // Write the divisor to the serial port - // - WRITE_DLL (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) (Divisor & 0xff)); - WRITE_DLM (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) ((Divisor >> 8) & 0xff)); - - // - // Put serial port back in normal mode and set remaining attributes. - // - Lcr.Bits.DLab = 0; - - switch (Parity) { - case NoParity: - Lcr.Bits.ParEn = 0; - Lcr.Bits.EvenPar = 0; - Lcr.Bits.SticPar = 0; - break; - - case EvenParity: - Lcr.Bits.ParEn = 1; - Lcr.Bits.EvenPar = 1; - Lcr.Bits.SticPar = 0; - break; - - case OddParity: - Lcr.Bits.ParEn = 1; - Lcr.Bits.EvenPar = 0; - Lcr.Bits.SticPar = 0; - break; - - case SpaceParity: - Lcr.Bits.ParEn = 1; - Lcr.Bits.EvenPar = 1; - Lcr.Bits.SticPar = 1; - break; - - case MarkParity: - Lcr.Bits.ParEn = 1; - Lcr.Bits.EvenPar = 0; - Lcr.Bits.SticPar = 1; - break; - - default: - break; - } - - switch (StopBits) { - case OneStopBit: - Lcr.Bits.StopB = 0; - break; - - case OneFiveStopBits: - case TwoStopBits: - Lcr.Bits.StopB = 1; - break; - - default: - break; - } - // - // DataBits - // - Lcr.Bits.SerialDB = (UINT8) ((DataBits - 5) & 0x03); - WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data); - - // - // Set the Serial I/O mode - // - This->Mode->BaudRate = BaudRate; - This->Mode->ReceiveFifoDepth = ReceiveFifoDepth; - This->Mode->Timeout = Timeout; - This->Mode->Parity = Parity; - This->Mode->DataBits = DataBits; - This->Mode->StopBits = StopBits; - - // - // See if Device Path Node has actually changed - // - if (SerialDevice->UartDevicePath.BaudRate == BaudRate && - SerialDevice->UartDevicePath.DataBits == DataBits && - SerialDevice->UartDevicePath.Parity == Parity && - SerialDevice->UartDevicePath.StopBits == StopBits - ) { - gBS->RestoreTPL (Tpl); - return EFI_SUCCESS; - } - // - // Update the device path - // - SerialDevice->UartDevicePath.BaudRate = BaudRate; - SerialDevice->UartDevicePath.DataBits = DataBits; - SerialDevice->UartDevicePath.Parity = (UINT8) Parity; - SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits; - - Status = EFI_SUCCESS; - if (SerialDevice->Handle != NULL) { - Uart = (UART_DEVICE_PATH *) ( - (UINTN) SerialDevice->DevicePath - + GetDevicePathSize (SerialDevice->ParentDevicePath) - - END_DEVICE_PATH_LENGTH - ); - CopyMem (Uart, &SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH)); - Status = gBS->ReinstallProtocolInterface ( - SerialDevice->Handle, - &gEfiDevicePathProtocolGuid, - SerialDevice->DevicePath, - SerialDevice->DevicePath - ); - } - - gBS->RestoreTPL (Tpl); - - return Status; -} - -/** - Set Control Bits. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param Control Control bits that can be settable - - @retval EFI_SUCCESS New Control bits were set successfully - @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported - -**/ -EFI_STATUS -EFIAPI -IsaSerialSetControl ( - IN EFI_SERIAL_IO_PROTOCOL *This, - IN UINT32 Control - ) -{ - SERIAL_DEV *SerialDevice; - SERIAL_PORT_MCR Mcr; - EFI_TPL Tpl; - UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; - EFI_STATUS Status; - - // - // The control bits that can be set are : - // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO - // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO - // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW - // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW - // EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE: 0x4000 // RW - // - SerialDevice = SERIAL_DEV_FROM_THIS (This); - - // - // first determine the parameter is invalid - // - if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | - EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | - EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) { - return EFI_UNSUPPORTED; - } - - Tpl = gBS->RaiseTPL (TPL_NOTIFY); - - Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - Mcr.Bits.DtrC = 0; - Mcr.Bits.Rts = 0; - Mcr.Bits.Lme = 0; - SerialDevice->SoftwareLoopbackEnable = FALSE; - SerialDevice->HardwareFlowControl = FALSE; - - if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { - Mcr.Bits.DtrC = 1; - } - - if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { - Mcr.Bits.Rts = 1; - } - - if ((Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) { - Mcr.Bits.Lme = 1; - } - - if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) { - SerialDevice->HardwareFlowControl = TRUE; - } - - WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); - - if ((Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) { - SerialDevice->SoftwareLoopbackEnable = TRUE; - } - - Status = EFI_SUCCESS; - if (SerialDevice->Handle != NULL) { - FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) ( - (UINTN) SerialDevice->DevicePath - + GetDevicePathSize (SerialDevice->ParentDevicePath) - - END_DEVICE_PATH_LENGTH - + sizeof (UART_DEVICE_PATH) - ); - if (IsUartFlowControlNode (FlowControl) && - ((ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) ^ SerialDevice->HardwareFlowControl)) { - // - // Flow Control setting is changed, need to reinstall device path protocol - // - WriteUnaligned32 (&FlowControl->FlowControlMap, SerialDevice->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0); - Status = gBS->ReinstallProtocolInterface ( - SerialDevice->Handle, - &gEfiDevicePathProtocolGuid, - SerialDevice->DevicePath, - SerialDevice->DevicePath - ); - } - } - - gBS->RestoreTPL (Tpl); - - return Status; -} - -/** - Get ControlBits. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param Control Control signals of the serial device - - @retval EFI_SUCCESS Get Control signals successfully - -**/ -EFI_STATUS -EFIAPI -IsaSerialGetControl ( - IN EFI_SERIAL_IO_PROTOCOL *This, - OUT UINT32 *Control - ) -{ - SERIAL_DEV *SerialDevice; - SERIAL_PORT_MSR Msr; - SERIAL_PORT_MCR Mcr; - EFI_TPL Tpl; - - Tpl = gBS->RaiseTPL (TPL_NOTIFY); - - SerialDevice = SERIAL_DEV_FROM_THIS (This); - - *Control = 0; - - // - // Read the Modem Status Register - // - Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - - if (Msr.Bits.Cts == 1) { - *Control |= EFI_SERIAL_CLEAR_TO_SEND; - } - - if (Msr.Bits.Dsr == 1) { - *Control |= EFI_SERIAL_DATA_SET_READY; - } - - if (Msr.Bits.Ri == 1) { - *Control |= EFI_SERIAL_RING_INDICATE; - } - - if (Msr.Bits.Dcd == 1) { - *Control |= EFI_SERIAL_CARRIER_DETECT; - } - // - // Read the Modem Control Register - // - Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - - if (Mcr.Bits.DtrC == 1) { - *Control |= EFI_SERIAL_DATA_TERMINAL_READY; - } - - if (Mcr.Bits.Rts == 1) { - *Control |= EFI_SERIAL_REQUEST_TO_SEND; - } - - if (Mcr.Bits.Lme == 1) { - *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE; - } - - if (SerialDevice->HardwareFlowControl) { - *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; - } - // - // See if the Transmit FIFO is empty - // - IsaSerialReceiveTransmit (SerialDevice); - - if (IsaSerialFifoEmpty (&SerialDevice->Transmit)) { - *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; - } - // - // See if the Receive FIFO is empty. - // - IsaSerialReceiveTransmit (SerialDevice); - - if (IsaSerialFifoEmpty (&SerialDevice->Receive)) { - *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; - } - - if (SerialDevice->SoftwareLoopbackEnable) { - *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE; - } - - gBS->RestoreTPL (Tpl); - - return EFI_SUCCESS; -} - -/** - Write the specified number of bytes to serial device. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param BufferSize On input the size of Buffer, on output the amount of - data actually written - @param Buffer The buffer of data to write - - @retval EFI_SUCCESS The data were written successfully - @retval EFI_DEVICE_ERROR The device reported an error - @retval EFI_TIMEOUT The write operation was stopped due to timeout - -**/ -EFI_STATUS -EFIAPI -IsaSerialWrite ( - IN EFI_SERIAL_IO_PROTOCOL *This, - IN OUT UINTN *BufferSize, - IN VOID *Buffer - ) -{ - SERIAL_DEV *SerialDevice; - UINT8 *CharBuffer; - UINT32 Index; - UINTN Elapsed; - UINTN ActualWrite; - EFI_TPL Tpl; - UINTN Timeout; - UINTN BitsPerCharacter; - - SerialDevice = SERIAL_DEV_FROM_THIS (This); - Elapsed = 0; - ActualWrite = 0; - - if (*BufferSize == 0) { - return EFI_SUCCESS; - } - - if (Buffer == NULL) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE, - EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT, - SerialDevice->DevicePath - ); - - return EFI_DEVICE_ERROR; - } - - Tpl = gBS->RaiseTPL (TPL_NOTIFY); - - CharBuffer = (UINT8 *) Buffer; - - // - // Compute the number of bits in a single character. This is a start bit, - // followed by the number of data bits, followed by the number of stop bits. - // The number of stop bits is specified by an enumeration that includes - // support for 1.5 stop bits. Treat 1.5 stop bits as 2 stop bits. - // - BitsPerCharacter = - 1 + - This->Mode->DataBits + - ((This->Mode->StopBits == TwoStopBits) ? 2 : This->Mode->StopBits); - - // - // Compute the timeout in microseconds to wait for a single byte to be - // transmitted. The Mode structure contans a Timeout field that is the - // maximum time to transmit or receive a character. However, many UARTs - // have a FIFO for transmits, so the time required to add one new character - // to the transmit FIFO may be the time required to flush a full FIFO. If - // the Timeout in the Mode structure is smaller than the time required to - // flush a full FIFO at the current baud rate, then use a timeout value that - // is required to flush a full transmit FIFO. - // - Timeout = MAX ( - This->Mode->Timeout, - (UINTN)DivU64x64Remainder ( - BitsPerCharacter * (SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH + 1) * 1000000, - This->Mode->BaudRate, - NULL - ) - ); - - for (Index = 0; Index < *BufferSize; Index++) { - IsaSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]); - - while (IsaSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !IsaSerialFifoEmpty (&SerialDevice->Transmit)) { - // - // Unsuccessful write so check if timeout has expired, if not, - // stall for a bit, increment time elapsed, and try again - // - if (Elapsed >= Timeout) { - *BufferSize = ActualWrite; - gBS->RestoreTPL (Tpl); - return EFI_TIMEOUT; - } - - gBS->Stall (TIMEOUT_STALL_INTERVAL); - - Elapsed += TIMEOUT_STALL_INTERVAL; - } - - ActualWrite++; - // - // Successful write so reset timeout - // - Elapsed = 0; - } - - gBS->RestoreTPL (Tpl); - - return EFI_SUCCESS; -} - -/** - Read the specified number of bytes from serial device. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param BufferSize On input the size of Buffer, on output the amount of - data returned in buffer - @param Buffer The buffer to return the data into - - @retval EFI_SUCCESS The data were read successfully - @retval EFI_DEVICE_ERROR The device reported an error - @retval EFI_TIMEOUT The read operation was stopped due to timeout - -**/ -EFI_STATUS -EFIAPI -IsaSerialRead ( - IN EFI_SERIAL_IO_PROTOCOL *This, - IN OUT UINTN *BufferSize, - OUT VOID *Buffer - ) -{ - SERIAL_DEV *SerialDevice; - UINT32 Index; - UINT8 *CharBuffer; - UINTN Elapsed; - EFI_STATUS Status; - EFI_TPL Tpl; - - SerialDevice = SERIAL_DEV_FROM_THIS (This); - Elapsed = 0; - - if (*BufferSize == 0) { - return EFI_SUCCESS; - } - - if (Buffer == NULL) { - return EFI_DEVICE_ERROR; - } - - Tpl = gBS->RaiseTPL (TPL_NOTIFY); - - Status = IsaSerialReceiveTransmit (SerialDevice); - - if (EFI_ERROR (Status)) { - *BufferSize = 0; - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE, - EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT, - SerialDevice->DevicePath - ); - - gBS->RestoreTPL (Tpl); - - return EFI_DEVICE_ERROR; - } - - CharBuffer = (UINT8 *) Buffer; - for (Index = 0; Index < *BufferSize; Index++) { - while (IsaSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) { - // - // Unsuccessful read so check if timeout has expired, if not, - // stall for a bit, increment time elapsed, and try again - // Need this time out to get conspliter to work. - // - if (Elapsed >= This->Mode->Timeout) { - *BufferSize = Index; - gBS->RestoreTPL (Tpl); - return EFI_TIMEOUT; - } - - gBS->Stall (TIMEOUT_STALL_INTERVAL); - Elapsed += TIMEOUT_STALL_INTERVAL; - - Status = IsaSerialReceiveTransmit (SerialDevice); - if (Status == EFI_DEVICE_ERROR) { - *BufferSize = Index; - gBS->RestoreTPL (Tpl); - return EFI_DEVICE_ERROR; - } - } - // - // Successful read so reset timeout - // - Elapsed = 0; - } - - IsaSerialReceiveTransmit (SerialDevice); - - gBS->RestoreTPL (Tpl); - - return EFI_SUCCESS; -} - -/** - Use scratchpad register to test if this serial port is present. - - @param SerialDevice Pointer to serial device structure - - @return if this serial port is present -**/ -BOOLEAN -IsaSerialPortPresent ( - IN SERIAL_DEV *SerialDevice - ) - -{ - UINT8 Temp; - BOOLEAN Status; - - Status = TRUE; - - // - // Save SCR reg - // - Temp = READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); - WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0xAA); - - if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0xAA) { - Status = FALSE; - } - - WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0x55); - - if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0x55) { - Status = FALSE; - } - // - // Restore SCR - // - WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Temp); - return Status; -} - -/** - Use IsaIo protocol to read serial port. - - @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance - @param BaseAddress Serial port register group base address - @param Offset Offset in register group - - @return Data read from serial port - -**/ -UINT8 -IsaSerialReadPort ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT16 BaseAddress, - IN UINT32 Offset - ) -{ - UINT8 Data; - - // - // Use IsaIo to access IO - // - IsaIo->Io.Read ( - IsaIo, - EfiIsaIoWidthUint8, - BaseAddress + Offset, - 1, - &Data - ); - return Data; -} - -/** - Use IsaIo protocol to write serial port. - - @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance - @param BaseAddress Serial port register group base address - @param Offset Offset in register group - @param Data data which is to be written to some serial port register - -**/ -VOID -IsaSerialWritePort ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT16 BaseAddress, - IN UINT32 Offset, - IN UINT8 Data - ) -{ - // - // Use IsaIo to access IO - // - IsaIo->Io.Write ( - IsaIo, - EfiIsaIoWidthUint8, - BaseAddress + Offset, - 1, - &Data - ); -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.h b/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.h deleted file mode 100644 index 9d50ca9e27..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.h +++ /dev/null @@ -1,842 +0,0 @@ -/** @file - Include for Serial Driver - -Copyright (c) 2006 - 2015, Intel 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 _SERIAL_H_ -#define _SERIAL_H_ - - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Driver Binding Externs -// -extern EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver; -extern EFI_COMPONENT_NAME_PROTOCOL gIsaSerialComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gIsaSerialComponentName2; - -// -// Internal Data Structures -// -#define SERIAL_DEV_SIGNATURE SIGNATURE_32 ('s', 'e', 'r', 'd') -#define SERIAL_MAX_BUFFER_SIZE 16 -#define TIMEOUT_STALL_INTERVAL 10 - -// -// Name: SERIAL_DEV_FIFO -// Purpose: To define Receive FIFO and Transmit FIFO -// Context: Used by serial data transmit and receive -// Fields: -// First UINT32: The index of the first data in array Data[] -// Last UINT32: The index, which you can put a new data into array Data[] -// Surplus UINT32: Identify how many data you can put into array Data[] -// Data[] UINT8 : An array, which used to store data -// -typedef struct { - UINT32 First; - UINT32 Last; - UINT32 Surplus; - UINT8 Data[SERIAL_MAX_BUFFER_SIZE]; -} SERIAL_DEV_FIFO; - -typedef enum { - Uart8250 = 0, - Uart16450 = 1, - Uart16550 = 2, - Uart16550A= 3 -} EFI_UART_TYPE; - -// -// Name: SERIAL_DEV -// Purpose: To provide device specific information -// Context: -// Fields: -// Signature UINTN: The identity of the serial device -// SerialIo SERIAL_IO_PROTOCOL: Serial I/O protocol interface -// SerialMode SERIAL_IO_MODE: -// DevicePath EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device -// Handle EFI_HANDLE: The handle instance attached to serial device -// BaseAddress UINT16: The base address of specific serial device -// Receive SERIAL_DEV_FIFO: The FIFO used to store data, -// which is received by UART -// Transmit SERIAL_DEV_FIFO: The FIFO used to store data, -// which you want to transmit by UART -// SoftwareLoopbackEnable BOOLEAN: -// Type EFI_UART_TYPE: Specify the UART type of certain serial device -// -typedef struct { - UINTN Signature; - - EFI_HANDLE Handle; - EFI_SERIAL_IO_PROTOCOL SerialIo; - EFI_SERIAL_IO_MODE SerialMode; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - UART_DEVICE_PATH UartDevicePath; - EFI_ISA_IO_PROTOCOL *IsaIo; - - UINT16 BaseAddress; - SERIAL_DEV_FIFO Receive; - SERIAL_DEV_FIFO Transmit; - BOOLEAN SoftwareLoopbackEnable; - BOOLEAN HardwareFlowControl; - EFI_UART_TYPE Type; - EFI_UNICODE_STRING_TABLE *ControllerNameTable; -} SERIAL_DEV; - -#define SERIAL_DEV_FROM_THIS(a) CR (a, SERIAL_DEV, SerialIo, SERIAL_DEV_SIGNATURE) - -// -// Serial Driver Defaults -// -#define SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH 1 -#define SERIAL_PORT_DEFAULT_TIMEOUT 1000000 -#define SERIAL_PORT_SUPPORT_CONTROL_MASK (EFI_SERIAL_CLEAR_TO_SEND | \ - EFI_SERIAL_DATA_SET_READY | \ - EFI_SERIAL_RING_INDICATE | \ - EFI_SERIAL_CARRIER_DETECT | \ - EFI_SERIAL_REQUEST_TO_SEND | \ - EFI_SERIAL_DATA_TERMINAL_READY | \ - EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | \ - EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \ - EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE | \ - EFI_SERIAL_OUTPUT_BUFFER_EMPTY | \ - EFI_SERIAL_INPUT_BUFFER_EMPTY) - -// -// 115200 baud with rounding errors -// -#define SERIAL_PORT_MAX_BAUD_RATE 115400 -#define SERIAL_PORT_MIN_BAUD_RATE 50 - -#define SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH 16 -#define SERIAL_PORT_MIN_TIMEOUT 1 // 1 uS -#define SERIAL_PORT_MAX_TIMEOUT 100000000 // 100 seconds -// -// UART Registers -// -#define SERIAL_REGISTER_THR 0 // WO Transmit Holding Register -#define SERIAL_REGISTER_RBR 0 // RO Receive Buffer Register -#define SERIAL_REGISTER_DLL 0 // R/W Divisor Latch LSB -#define SERIAL_REGISTER_DLM 1 // R/W Divisor Latch MSB -#define SERIAL_REGISTER_IER 1 // R/W Interrupt Enable Register -#define SERIAL_REGISTER_IIR 2 // RO Interrupt Identification Register -#define SERIAL_REGISTER_FCR 2 // WO FIFO Cotrol Register -#define SERIAL_REGISTER_LCR 3 // R/W Line Control Register -#define SERIAL_REGISTER_MCR 4 // R/W Modem Control Register -#define SERIAL_REGISTER_LSR 5 // R/W Line Status Register -#define SERIAL_REGISTER_MSR 6 // R/W Modem Status Register -#define SERIAL_REGISTER_SCR 7 // R/W Scratch Pad Register -#pragma pack(1) -// -// Name: SERIAL_PORT_IER_BITS -// Purpose: Define each bit in Interrupt Enable Register -// Context: -// Fields: -// Ravie Bit0: Receiver Data Available Interrupt Enable -// Theie Bit1: Transmistter Holding Register Empty Interrupt Enable -// Rie Bit2: Receiver Interrupt Enable -// Mie Bit3: Modem Interrupt Enable -// Reserved Bit4-Bit7: Reserved -// -typedef struct { - UINT8 Ravie : 1; - UINT8 Theie : 1; - UINT8 Rie : 1; - UINT8 Mie : 1; - UINT8 Reserved : 4; -} SERIAL_PORT_IER_BITS; - -// -// Name: SERIAL_PORT_IER -// Purpose: -// Context: -// Fields: -// Bits SERIAL_PORT_IER_BITS: Bits of the IER -// Data UINT8: the value of the IER -// -typedef union { - SERIAL_PORT_IER_BITS Bits; - UINT8 Data; -} SERIAL_PORT_IER; - -// -// Name: SERIAL_PORT_FCR_BITS -// Purpose: Define each bit in FIFO Control Register -// Context: -// Fields: -// TrFIFOE Bit0: Transmit and Receive FIFO Enable -// ResetRF Bit1: Reset Reciever FIFO -// ResetTF Bit2: Reset Transmistter FIFO -// Dms Bit3: DMA Mode Select -// Reserved Bit4-Bit5: Reserved -// Rtb Bit6-Bit7: Receive Trigger Bits -// -typedef struct { - UINT8 TrFIFOE : 1; - UINT8 ResetRF : 1; - UINT8 ResetTF : 1; - UINT8 Dms : 1; - UINT8 Reserved : 2; - UINT8 Rtb : 2; -} SERIAL_PORT_FCR_BITS; - -// -// Name: SERIAL_PORT_FCR -// Purpose: -// Context: -// Fields: -// Bits SERIAL_PORT_FCR_BITS: Bits of the FCR -// Data UINT8: the value of the FCR -// -typedef union { - SERIAL_PORT_FCR_BITS Bits; - UINT8 Data; -} SERIAL_PORT_FCR; - -// -// Name: SERIAL_PORT_LCR_BITS -// Purpose: Define each bit in Line Control Register -// Context: -// Fields: -// SerialDB Bit0-Bit1: Number of Serial Data Bits -// StopB Bit2: Number of Stop Bits -// ParEn Bit3: Parity Enable -// EvenPar Bit4: Even Parity Select -// SticPar Bit5: Sticky Parity -// BrCon Bit6: Break Control -// DLab Bit7: Divisor Latch Access Bit -// -typedef struct { - UINT8 SerialDB : 2; - UINT8 StopB : 1; - UINT8 ParEn : 1; - UINT8 EvenPar : 1; - UINT8 SticPar : 1; - UINT8 BrCon : 1; - UINT8 DLab : 1; -} SERIAL_PORT_LCR_BITS; - -// -// Name: SERIAL_PORT_LCR -// Purpose: -// Context: -// Fields: -// Bits SERIAL_PORT_LCR_BITS: Bits of the LCR -// Data UINT8: the value of the LCR -// -typedef union { - SERIAL_PORT_LCR_BITS Bits; - UINT8 Data; -} SERIAL_PORT_LCR; - -// -// Name: SERIAL_PORT_MCR_BITS -// Purpose: Define each bit in Modem Control Register -// Context: -// Fields: -// DtrC Bit0: Data Terminal Ready Control -// Rts Bit1: Request To Send Control -// Out1 Bit2: Output1 -// Out2 Bit3: Output2, used to disable interrupt -// Lme; Bit4: Loopback Mode Enable -// Reserved Bit5-Bit7: Reserved -// -typedef struct { - UINT8 DtrC : 1; - UINT8 Rts : 1; - UINT8 Out1 : 1; - UINT8 Out2 : 1; - UINT8 Lme : 1; - UINT8 Reserved : 3; -} SERIAL_PORT_MCR_BITS; - -// -// Name: SERIAL_PORT_MCR -// Purpose: -// Context: -// Fields: -// Bits SERIAL_PORT_MCR_BITS: Bits of the MCR -// Data UINT8: the value of the MCR -// -typedef union { - SERIAL_PORT_MCR_BITS Bits; - UINT8 Data; -} SERIAL_PORT_MCR; - -// -// Name: SERIAL_PORT_LSR_BITS -// Purpose: Define each bit in Line Status Register -// Context: -// Fields: -// Dr Bit0: Receiver Data Ready Status -// Oe Bit1: Overrun Error Status -// Pe Bit2: Parity Error Status -// Fe Bit3: Framing Error Status -// Bi Bit4: Break Interrupt Status -// Thre Bit5: Transmistter Holding Register Status -// Temt Bit6: Transmitter Empty Status -// FIFOe Bit7: FIFO Error Status -// -typedef struct { - UINT8 Dr : 1; - UINT8 Oe : 1; - UINT8 Pe : 1; - UINT8 Fe : 1; - UINT8 Bi : 1; - UINT8 Thre : 1; - UINT8 Temt : 1; - UINT8 FIFOe : 1; -} SERIAL_PORT_LSR_BITS; - -// -// Name: SERIAL_PORT_LSR -// Purpose: -// Context: -// Fields: -// Bits SERIAL_PORT_LSR_BITS: Bits of the LSR -// Data UINT8: the value of the LSR -// -typedef union { - SERIAL_PORT_LSR_BITS Bits; - UINT8 Data; -} SERIAL_PORT_LSR; - -// -// Name: SERIAL_PORT_MSR_BITS -// Purpose: Define each bit in Modem Status Register -// Context: -// Fields: -// DeltaCTS Bit0: Delta Clear To Send Status -// DeltaDSR Bit1: Delta Data Set Ready Status -// TrailingEdgeRI Bit2: Trailing Edge of Ring Indicator Status -// DeltaDCD Bit3: Delta Data Carrier Detect Status -// Cts Bit4: Clear To Send Status -// Dsr Bit5: Data Set Ready Status -// Ri Bit6: Ring Indicator Status -// Dcd Bit7: Data Carrier Detect Status -// -typedef struct { - UINT8 DeltaCTS : 1; - UINT8 DeltaDSR : 1; - UINT8 TrailingEdgeRI : 1; - UINT8 DeltaDCD : 1; - UINT8 Cts : 1; - UINT8 Dsr : 1; - UINT8 Ri : 1; - UINT8 Dcd : 1; -} SERIAL_PORT_MSR_BITS; - -// -// Name: SERIAL_PORT_MSR -// Purpose: -// Context: -// Fields: -// Bits SERIAL_PORT_MSR_BITS: Bits of the MSR -// Data UINT8: the value of the MSR -// -typedef union { - SERIAL_PORT_MSR_BITS Bits; - UINT8 Data; -} SERIAL_PORT_MSR; - -#pragma pack() -// -// Define serial register I/O macros -// -#define READ_RBR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_RBR) -#define READ_DLL(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_DLL) -#define READ_DLM(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_DLM) -#define READ_IER(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_IER) -#define READ_IIR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_IIR) -#define READ_LCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_LCR) -#define READ_MCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_MCR) -#define READ_LSR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_LSR) -#define READ_MSR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_MSR) -#define READ_SCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_SCR) - -#define WRITE_THR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_THR, D) -#define WRITE_DLL(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_DLL, D) -#define WRITE_DLM(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_DLM, D) -#define WRITE_IER(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_IER, D) -#define WRITE_FCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_FCR, D) -#define WRITE_LCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_LCR, D) -#define WRITE_MCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_MCR, D) -#define WRITE_LSR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_LSR, D) -#define WRITE_MSR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_MSR, D) -#define WRITE_SCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_SCR, D) - -// -// Prototypes -// Driver model protocol interface -// -/** - Check to see if this driver supports the given controller - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @return EFI_SUCCESS This driver can support the given controller - -**/ -EFI_STATUS -EFIAPI -SerialControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Start to management the controller passed in - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @return EFI_SUCCESS Driver is started successfully -**/ -EFI_STATUS -EFIAPI -SerialControllerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Disconnect this driver with the controller, uninstall related protocol instance - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param NumberOfChildren Number of child device. - @param ChildHandleBuffer A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS Operation successfully - @retval EFI_DEVICE_ERROR Cannot stop the driver successfully - -**/ -EFI_STATUS -EFIAPI -SerialControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// Serial I/O Protocol Interface -// -/** - Reset serial device. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - - @retval EFI_SUCCESS Reset successfully - @retval EFI_DEVICE_ERROR Failed to reset - -**/ -EFI_STATUS -EFIAPI -IsaSerialReset ( - IN EFI_SERIAL_IO_PROTOCOL *This - ); - -/** - Set new attributes to a serial device. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param BaudRate The baudrate of the serial device - @param ReceiveFifoDepth The depth of receive FIFO buffer - @param Timeout The request timeout for a single char - @param Parity The type of parity used in serial device - @param DataBits Number of databits used in serial device - @param StopBits Number of stopbits used in serial device - - @retval EFI_SUCCESS The new attributes were set - @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value - @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6 - @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return) - -**/ -EFI_STATUS -EFIAPI -IsaSerialSetAttributes ( - IN EFI_SERIAL_IO_PROTOCOL *This, - IN UINT64 BaudRate, - IN UINT32 ReceiveFifoDepth, - IN UINT32 Timeout, - IN EFI_PARITY_TYPE Parity, - IN UINT8 DataBits, - IN EFI_STOP_BITS_TYPE StopBits - ); - -/** - Set Control Bits. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param Control Control bits that can be settable - - @retval EFI_SUCCESS New Control bits were set successfully - @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported - -**/ -EFI_STATUS -EFIAPI -IsaSerialSetControl ( - IN EFI_SERIAL_IO_PROTOCOL *This, - IN UINT32 Control - ); - -/** - Get ControlBits. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param Control Control signals of the serial device - - @retval EFI_SUCCESS Get Control signals successfully - -**/ -EFI_STATUS -EFIAPI -IsaSerialGetControl ( - IN EFI_SERIAL_IO_PROTOCOL *This, - OUT UINT32 *Control - ); - -/** - Write the specified number of bytes to serial device. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param BufferSize On input the size of Buffer, on output the amount of - data actually written - @param Buffer The buffer of data to write - - @retval EFI_SUCCESS The data were written successfully - @retval EFI_DEVICE_ERROR The device reported an error - @retval EFI_TIMEOUT The write operation was stopped due to timeout - -**/ -EFI_STATUS -EFIAPI -IsaSerialWrite ( - IN EFI_SERIAL_IO_PROTOCOL *This, - IN OUT UINTN *BufferSize, - IN VOID *Buffer - ); - -/** - Read the specified number of bytes from serial device. - - @param This Pointer to EFI_SERIAL_IO_PROTOCOL - @param BufferSize On input the size of Buffer, on output the amount of - data returned in buffer - @param Buffer The buffer to return the data into - - @retval EFI_SUCCESS The data were read successfully - @retval EFI_DEVICE_ERROR The device reported an error - @retval EFI_TIMEOUT The read operation was stopped due to timeout - -**/ -EFI_STATUS -EFIAPI -IsaSerialRead ( - IN EFI_SERIAL_IO_PROTOCOL *This, - IN OUT UINTN *BufferSize, - OUT VOID *Buffer - ); - -// -// Internal Functions -// -/** - Use scratchpad register to test if this serial port is present. - - @param SerialDevice Pointer to serial device structure - - @return if this serial port is present -**/ -BOOLEAN -IsaSerialPortPresent ( - IN SERIAL_DEV *SerialDevice - ); - -/** - Detect whether specific FIFO is full or not. - - @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO - - @return whether specific FIFO is full or not - -**/ -BOOLEAN -IsaSerialFifoFull ( - IN SERIAL_DEV_FIFO *Fifo - ); - -/** - Detect whether specific FIFO is empty or not. - - @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO - - @return whether specific FIFO is empty or not - -**/ -BOOLEAN -IsaSerialFifoEmpty ( - IN SERIAL_DEV_FIFO *Fifo - ); - -/** - Add data to specific FIFO. - - @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO - @param Data the data added to FIFO - - @retval EFI_SUCCESS Add data to specific FIFO successfully - @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full - -**/ -EFI_STATUS -IsaSerialFifoAdd ( - IN SERIAL_DEV_FIFO *Fifo, - IN UINT8 Data - ); - -/** - Remove data from specific FIFO. - - @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO - @param Data the data removed from FIFO - - @retval EFI_SUCCESS Remove data from specific FIFO successfully - @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty - -**/ -EFI_STATUS -IsaSerialFifoRemove ( - IN SERIAL_DEV_FIFO *Fifo, - OUT UINT8 *Data - ); - -/** - Reads and writes all avaliable data. - - @param SerialDevice The device to flush - - @retval EFI_SUCCESS Data was read/written successfully. - @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when - this happens, pending writes are not done. - -**/ -EFI_STATUS -IsaSerialReceiveTransmit ( - IN SERIAL_DEV *SerialDevice - ); - -/** - Use IsaIo protocol to read serial port. - - @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance - @param BaseAddress Serial port register group base address - @param Offset Offset in register group - - @return Data read from serial port - -**/ -UINT8 -IsaSerialReadPort ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT16 BaseAddress, - IN UINT32 Offset - ); - -/** - Use IsaIo protocol to write serial port. - - @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance - @param BaseAddress Serial port register group base address - @param Offset Offset in register group - @param Data data which is to be written to some serial port register - -**/ -VOID -IsaSerialWritePort ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT16 BaseAddress, - IN UINT32 Offset, - IN UINT8 Data - ); - - -// -// EFI Component Name Functions -// -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -IsaSerialComponentNameGetDriverName ( - 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 -IsaSerialComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -/** - Add the component name for the serial io device - - @param SerialDevice A pointer to the SERIAL_DEV instance. - - @param IsaIo A pointer to the EFI_ISA_IO_PROTOCOL instance. - -**/ -VOID -AddName ( - IN SERIAL_DEV *SerialDevice, - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c deleted file mode 100644 index e6c739e2ba..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c +++ /dev/null @@ -1,372 +0,0 @@ -/** @file - Routines related Component Name protocol. - -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 "Ps2Keyboard.h" - -// -// EFI Component Name Functions -// -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -Ps2KeyboardComponentNameGetDriverName ( - 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 -Ps2KeyboardComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPs2KeyboardComponentName = { - Ps2KeyboardComponentNameGetDriverName, - Ps2KeyboardComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPs2KeyboardComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ps2KeyboardComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ps2KeyboardComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPs2KeyboardDriverNameTable[] = { - { - "eng;en", - L"PS/2 Keyboard Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -Ps2KeyboardComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mPs2KeyboardDriverNameTable, - DriverName, - (BOOLEAN)(This == &gPs2KeyboardComponentName) - ); -} - -/** - 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 -Ps2KeyboardComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; - KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; - EFI_ISA_IO_PROTOCOL *IsaIoProtocol; - - // - // This is a device driver, so ChildHandle must be NULL. - // - if (ChildHandle != NULL) { - return EFI_UNSUPPORTED; - } - // - // Check Controller's handle - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIoProtocol, - gKeyboardControllerDriver.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - - if (!EFI_ERROR (Status)) { - gBS->CloseProtocol ( - ControllerHandle, - &gEfiIsaIoProtocolGuid, - gKeyboardControllerDriver.DriverBindingHandle, - ControllerHandle - ); - - return EFI_UNSUPPORTED; - } - - if (Status != EFI_ALREADY_STARTED) { - return EFI_UNSUPPORTED; - } - // - // Get the device context - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiSimpleTextInProtocolGuid, - (VOID **) &ConIn, - gKeyboardControllerDriver.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn); - - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - ConsoleIn->ControllerNameTable, - ControllerName, - (BOOLEAN)(This == &gPs2KeyboardComponentName) - ); -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c deleted file mode 100644 index 2a20b789a7..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c +++ /dev/null @@ -1,1908 +0,0 @@ -/** @file - Routines that access 8042 keyboard controller - -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 "Ps2Keyboard.h" - -struct { - UINT8 ScanCode; ///< follows value defined in Scan Code Set1 - UINT16 EfiScanCode; - CHAR16 UnicodeChar; - CHAR16 ShiftUnicodeChar; -} -ConvertKeyboardScanCodeToEfiKey[] = { - - { - 0x01, // Escape - SCAN_ESC, - 0x0000, - 0x0000 - }, - { - 0x02, - SCAN_NULL, - L'1', - L'!' - }, - { - 0x03, - SCAN_NULL, - L'2', - L'@' - }, - { - 0x04, - SCAN_NULL, - L'3', - L'#' - }, - { - 0x05, - SCAN_NULL, - L'4', - L'$' - }, - { - 0x06, - SCAN_NULL, - L'5', - L'%' - }, - { - 0x07, - SCAN_NULL, - L'6', - L'^' - }, - { - 0x08, - SCAN_NULL, - L'7', - L'&' - }, - { - 0x09, - SCAN_NULL, - L'8', - L'*' - }, - { - 0x0A, - SCAN_NULL, - L'9', - L'(' - }, - { - 0x0B, - SCAN_NULL, - L'0', - L')' - }, - { - 0x0C, - SCAN_NULL, - L'-', - L'_' - }, - { - 0x0D, - SCAN_NULL, - L'=', - L'+' - }, - { - 0x0E, // BackSpace - SCAN_NULL, - 0x0008, - 0x0008 - }, - { - 0x0F, // Tab - SCAN_NULL, - 0x0009, - 0x0009 - }, - { - 0x10, - SCAN_NULL, - L'q', - L'Q' - }, - { - 0x11, - SCAN_NULL, - L'w', - L'W' - }, - { - 0x12, - SCAN_NULL, - L'e', - L'E' - }, - { - 0x13, - SCAN_NULL, - L'r', - L'R' - }, - { - 0x14, - SCAN_NULL, - L't', - L'T' - }, - { - 0x15, - SCAN_NULL, - L'y', - L'Y' - }, - { - 0x16, - SCAN_NULL, - L'u', - L'U' - }, - { - 0x17, - SCAN_NULL, - L'i', - L'I' - }, - { - 0x18, - SCAN_NULL, - L'o', - L'O' - }, - { - 0x19, - SCAN_NULL, - L'p', - L'P' - }, - { - 0x1a, - SCAN_NULL, - L'[', - L'{' - }, - { - 0x1b, - SCAN_NULL, - L']', - L'}' - }, - { - 0x1c, // Enter - SCAN_NULL, - 0x000d, - 0x000d - }, - { - 0x1d, - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x1e, - SCAN_NULL, - L'a', - L'A' - }, - { - 0x1f, - SCAN_NULL, - L's', - L'S' - }, - { - 0x20, - SCAN_NULL, - L'd', - L'D' - }, - { - 0x21, - SCAN_NULL, - L'f', - L'F' - }, - { - 0x22, - SCAN_NULL, - L'g', - L'G' - }, - { - 0x23, - SCAN_NULL, - L'h', - L'H' - }, - { - 0x24, - SCAN_NULL, - L'j', - L'J' - }, - { - 0x25, - SCAN_NULL, - L'k', - L'K' - }, - { - 0x26, - SCAN_NULL, - L'l', - L'L' - }, - { - 0x27, - SCAN_NULL, - L';', - L':' - }, - { - 0x28, - SCAN_NULL, - L'\'', - L'"' - }, - { - 0x29, - SCAN_NULL, - L'`', - L'~' - }, - { - 0x2a, // Left Shift - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x2b, - SCAN_NULL, - L'\\', - L'|' - }, - { - 0x2c, - SCAN_NULL, - L'z', - L'Z' - }, - { - 0x2d, - SCAN_NULL, - L'x', - L'X' - }, - { - 0x2e, - SCAN_NULL, - L'c', - L'C' - }, - { - 0x2f, - SCAN_NULL, - L'v', - L'V' - }, - { - 0x30, - SCAN_NULL, - L'b', - L'B' - }, - { - 0x31, - SCAN_NULL, - L'n', - L'N' - }, - { - 0x32, - SCAN_NULL, - L'm', - L'M' - }, - { - 0x33, - SCAN_NULL, - L',', - L'<' - }, - { - 0x34, - SCAN_NULL, - L'.', - L'>' - }, - { - 0x35, - SCAN_NULL, - L'/', - L'?' - }, - { - 0x36, //Right Shift - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x37, // Numeric Keypad * - SCAN_NULL, - L'*', - L'*' - }, - { - 0x38, //Left Alt/Extended Right Alt - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x39, - SCAN_NULL, - L' ', - L' ' - }, - { - 0x3A, //CapsLock - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x3B, - SCAN_F1, - 0x0000, - 0x0000 - }, - { - 0x3C, - SCAN_F2, - 0x0000, - 0x0000 - }, - { - 0x3D, - SCAN_F3, - 0x0000, - 0x0000 - }, - { - 0x3E, - SCAN_F4, - 0x0000, - 0x0000 - }, - { - 0x3F, - SCAN_F5, - 0x0000, - 0x0000 - }, - { - 0x40, - SCAN_F6, - 0x0000, - 0x0000 - }, - { - 0x41, - SCAN_F7, - 0x0000, - 0x0000 - }, - { - 0x42, - SCAN_F8, - 0x0000, - 0x0000 - }, - { - 0x43, - SCAN_F9, - 0x0000, - 0x0000 - }, - { - 0x44, - SCAN_F10, - 0x0000, - 0x0000 - }, - { - 0x45, // NumLock - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x46, // ScrollLock - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x47, - SCAN_HOME, - L'7', - L'7' - }, - { - 0x48, - SCAN_UP, - L'8', - L'8' - }, - { - 0x49, - SCAN_PAGE_UP, - L'9', - L'9' - }, - { - 0x4a, - SCAN_NULL, - L'-', - L'-' - }, - { - 0x4b, - SCAN_LEFT, - L'4', - L'4' - }, - { - 0x4c, // Numeric Keypad 5 - SCAN_NULL, - L'5', - L'5' - }, - { - 0x4d, - SCAN_RIGHT, - L'6', - L'6' - }, - { - 0x4e, - SCAN_NULL, - L'+', - L'+' - }, - { - 0x4f, - SCAN_END, - L'1', - L'1' - }, - { - 0x50, - SCAN_DOWN, - L'2', - L'2' - }, - { - 0x51, - SCAN_PAGE_DOWN, - L'3', - L'3' - }, - { - 0x52, - SCAN_INSERT, - L'0', - L'0' - }, - { - 0x53, - SCAN_DELETE, - L'.', - L'.' - }, - { - 0x57, - SCAN_F11, - 0x0000, - 0x0000 - }, - { - 0x58, - SCAN_F12, - 0x0000, - 0x0000 - }, - { - 0x5B, //Left LOGO - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x5C, //Right LOGO - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - 0x5D, //Menu key - SCAN_NULL, - 0x0000, - 0x0000 - }, - { - TABLE_END, - TABLE_END, - SCAN_NULL, - SCAN_NULL - }, -}; - -// -// The WaitForValue time out -// -UINTN mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT; - -BOOLEAN mEnableMouseInterface; - - - -/** - Return the count of scancode in the queue. - - @param Queue Pointer to instance of SCAN_CODE_QUEUE. - - @return Count of the scancode. -**/ -UINTN -GetScancodeBufCount ( - IN SCAN_CODE_QUEUE *Queue - ) -{ - if (Queue->Head <= Queue->Tail) { - return Queue->Tail - Queue->Head; - } else { - return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head; - } -} - -/** - Read several bytes from the scancode buffer without removing them. - This function is called to see if there are enough bytes of scancode - representing a single key. - - @param Queue Pointer to instance of SCAN_CODE_QUEUE. - @param Count Number of bytes to be read - @param Buf Store the results - - @retval EFI_SUCCESS success to scan the keyboard code - @retval EFI_NOT_READY invalid parameter -**/ -EFI_STATUS -GetScancodeBufHead ( - IN SCAN_CODE_QUEUE *Queue, - IN UINTN Count, - OUT UINT8 *Buf - ) -{ - UINTN Index; - UINTN Pos; - - // - // check the valid range of parameter 'Count' - // - if (GetScancodeBufCount (Queue) < Count) { - return EFI_NOT_READY; - } - // - // retrieve the values - // - for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) { - Buf[Index] = Queue->Buffer[Pos]; - } - - return EFI_SUCCESS; -} - -/** - - Read & remove several bytes from the scancode buffer. - This function is usually called after GetScancodeBufHead() - - @param Queue Pointer to instance of SCAN_CODE_QUEUE. - @param Count Number of bytes to be read - @param Buf Store the results - - @retval EFI_SUCCESS success to scan the keyboard code - @retval EFI_NOT_READY invalid parameter -**/ -EFI_STATUS -PopScancodeBufHead ( - IN SCAN_CODE_QUEUE *Queue, - IN UINTN Count, - OUT UINT8 *Buf OPTIONAL - ) -{ - UINTN Index; - - // - // Check the valid range of parameter 'Count' - // - if (GetScancodeBufCount (Queue) < Count) { - return EFI_NOT_READY; - } - // - // Retrieve and remove the values - // - for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) { - if (Buf != NULL) { - Buf[Index] = Queue->Buffer[Queue->Head]; - } - } - - return EFI_SUCCESS; -} - -/** - Push one byte to the scancode buffer. - - @param Queue Pointer to instance of SCAN_CODE_QUEUE. - @param Scancode The byte to push. -**/ -VOID -PushScancodeBufTail ( - IN SCAN_CODE_QUEUE *Queue, - IN UINT8 Scancode - ) -{ - if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) { - PopScancodeBufHead (Queue, 1, NULL); - } - - Queue->Buffer[Queue->Tail] = Scancode; - Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT; -} - -/** - Read data register . - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - - @return return the value - -**/ -UINT8 -KeyReadDataRegister ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ) - -{ - EFI_ISA_IO_PROTOCOL *IsaIo; - UINT8 Data; - - // - // Use IsaIo protocol to perform IO operations - // - IsaIo = ConsoleIn->IsaIo; - - IsaIo->Io.Read ( - IsaIo, - EfiIsaIoWidthUint8, - ConsoleIn->DataRegisterAddress, - 1, - &Data - ); - - return Data; -} - -/** - Write data register. - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - @param Data value wanted to be written - -**/ -VOID -KeyWriteDataRegister ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - IN UINT8 Data - ) -{ - ConsoleIn->IsaIo->Io.Write ( - ConsoleIn->IsaIo, - EfiIsaIoWidthUint8, - ConsoleIn->DataRegisterAddress, - 1, - &Data - ); -} - -/** - Read status register. - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - - @return value in status register - -**/ -UINT8 -KeyReadStatusRegister ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ) -{ - UINT8 Data; - ConsoleIn->IsaIo->Io.Read ( - ConsoleIn->IsaIo, - EfiIsaIoWidthUint8, - ConsoleIn->StatusRegisterAddress, - 1, - &Data - ); - return Data; -} - -/** - Write command register . - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - @param Data The value wanted to be written - -**/ -VOID -KeyWriteCommandRegister ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - IN UINT8 Data - ) -{ - ConsoleIn->IsaIo->Io.Write ( - ConsoleIn->IsaIo, - EfiIsaIoWidthUint8, - ConsoleIn->CommandRegisterAddress, - 1, - &Data - ); -} - -/** - Display error message. - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - @param ErrMsg Unicode string of error message - -**/ -VOID -KeyboardError ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - IN CHAR16 *ErrMsg - ) -{ - ConsoleIn->KeyboardErr = TRUE; -} - -/** - Timer event handler: read a series of scancodes from 8042 - and put them into memory scancode buffer. - it read as much scancodes to either fill - the memory buffer or empty the keyboard buffer. - It is registered as running under TPL_NOTIFY - - @param Event The timer event - @param Context A KEYBOARD_CONSOLE_IN_DEV pointer - -**/ -VOID -EFIAPI -KeyboardTimerHandler ( - IN EFI_EVENT Event, - IN VOID *Context - ) - -{ - UINT8 Data; - EFI_TPL OldTpl; - KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; - - ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context; - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) { - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - return ; - } - - // - // To let KB driver support Hot plug, here should skip the 'resend' command for the case that - // KB is not connected to system. If KB is not connected to system, driver will find there's something - // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since - // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected. - // Just skip the 'resend' process simply. - // - - while ((KeyReadStatusRegister (ConsoleIn) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) == - KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA - ) { - // - // Read one byte of the scan code and store it into the memory buffer - // - Data = KeyReadDataRegister (ConsoleIn); - PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data); - } - KeyGetchar (ConsoleIn); - - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); -} - -/** - Read key value . - - @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - @param Data - Pointer to outof buffer for keeping key value - - @retval EFI_TIMEOUT Status resigter time out - @retval EFI_SUCCESS Success to read keyboard - -**/ -EFI_STATUS -KeyboardRead ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - OUT UINT8 *Data - ) - -{ - UINT32 TimeOut; - UINT32 RegFilled; - - TimeOut = 0; - RegFilled = 0; - - // - // wait till output buffer full then perform the read - // - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if (KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) { - RegFilled = 1; - *Data = KeyReadDataRegister (ConsoleIn); - break; - } - - MicroSecondDelay (30); - } - - if (RegFilled == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - write key to keyboard - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - @param Data value wanted to be written - - @retval EFI_TIMEOUT The input buffer register is full for putting new value util timeout - @retval EFI_SUCCESS The new value is sucess put into input buffer register. - -**/ -EFI_STATUS -KeyboardWrite ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - IN UINT8 Data - ) -{ - UINT32 TimeOut; - UINT32 RegEmptied; - - TimeOut = 0; - RegEmptied = 0; - - // - // wait for input buffer empty - // - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) { - RegEmptied = 1; - break; - } - - MicroSecondDelay (30); - } - - if (RegEmptied == 0) { - return EFI_TIMEOUT; - } - // - // Write it - // - KeyWriteDataRegister (ConsoleIn, Data); - - return EFI_SUCCESS; -} - -/** - Issue keyboard command. - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - @param Data The buff holding the command - - @retval EFI_TIMEOUT Keyboard is not ready to issuing - @retval EFI_SUCCESS Success to issue keyboard command - -**/ -EFI_STATUS -KeyboardCommand ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - IN UINT8 Data - ) -{ - UINT32 TimeOut; - UINT32 RegEmptied; - - TimeOut = 0; - RegEmptied = 0; - - // - // Wait For Input Buffer Empty - // - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) { - RegEmptied = 1; - break; - } - - MicroSecondDelay (30); - } - - if (RegEmptied == 0) { - return EFI_TIMEOUT; - } - // - // issue the command - // - KeyWriteCommandRegister (ConsoleIn, Data); - - // - // Wait For Input Buffer Empty again - // - RegEmptied = 0; - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) { - RegEmptied = 1; - break; - } - - MicroSecondDelay (30); - } - - if (RegEmptied == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - wait for a specific value to be presented on - 8042 Data register by keyboard and then read it, - used in keyboard commands ack - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - @param Value the value wanted to be waited. - - @retval EFI_TIMEOUT Fail to get specific value in given time - @retval EFI_SUCCESS Success to get specific value in given time. - -**/ -EFI_STATUS -KeyboardWaitForValue ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - IN UINT8 Value - ) -{ - UINT8 Data; - UINT32 TimeOut; - UINT32 SumTimeOut; - UINT32 GotIt; - - GotIt = 0; - TimeOut = 0; - SumTimeOut = 0; - - // - // Make sure the initial value of 'Data' is different from 'Value' - // - Data = 0; - if (Data == Value) { - Data = 1; - } - // - // Read from 8042 (multiple times if needed) - // until the expected value appears - // use SumTimeOut to control the iteration - // - while (1) { - // - // Perform a read - // - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if (KeyReadStatusRegister (ConsoleIn) & 0x01) { - Data = KeyReadDataRegister (ConsoleIn); - break; - } - - MicroSecondDelay (30); - } - - SumTimeOut += TimeOut; - - if (Data == Value) { - GotIt = 1; - break; - } - - if (SumTimeOut >= mWaitForValueTimeOut) { - break; - } - } - // - // Check results - // - if (GotIt == 1) { - return EFI_SUCCESS; - } else { - return EFI_TIMEOUT; - } - -} - -/** - Show keyboard status lights according to - indicators in ConsoleIn. - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - - @return status of updating keyboard register - -**/ -EFI_STATUS -UpdateStatusLights ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ) -{ - EFI_STATUS Status; - UINT8 Command; - - // - // Send keyboard command - // - Status = KeyboardWrite (ConsoleIn, 0xed); - if (EFI_ERROR (Status)) { - return Status; - } - - KeyboardWaitForValue (ConsoleIn, 0xfa); - - // - // Light configuration - // - Command = 0; - if (ConsoleIn->CapsLock) { - Command |= 4; - } - - if (ConsoleIn->NumLock) { - Command |= 2; - } - - if (ConsoleIn->ScrollLock) { - Command |= 1; - } - - Status = KeyboardWrite (ConsoleIn, Command); - - if (EFI_ERROR (Status)) { - return Status; - } - - KeyboardWaitForValue (ConsoleIn, 0xfa); - return Status; -} - -/** - Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec. - - The function is always called in TPL_NOTIFY. - - @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer - -**/ -VOID -KeyGetchar ( - IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ) -{ - EFI_STATUS Status; - UINT16 ScanCode; - BOOLEAN Extend0; - BOOLEAN Extend1; - UINTN Index; - EFI_KEY_DATA KeyData; - LIST_ENTRY *Link; - KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; - // - // 3 bytes most - // - UINT8 ScancodeArr[3]; - UINT32 ScancodeArrPos; - - // - // Check if there are enough bytes of scancode representing a single key - // available in the buffer - // - while (TRUE) { - Extend0 = FALSE; - Extend1 = FALSE; - ScancodeArrPos = 0; - Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr); - if (EFI_ERROR (Status)) { - return ; - } - - if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) { - // - // E0 to look ahead 2 bytes - // - Extend0 = TRUE; - ScancodeArrPos = 1; - Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr); - if (EFI_ERROR (Status)) { - return ; - } - } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) { - // - // E1 to look ahead 3 bytes - // - Extend1 = TRUE; - ScancodeArrPos = 2; - Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr); - if (EFI_ERROR (Status)) { - return ; - } - } - // - // if we reach this position, scancodes for a key is in buffer now,pop them - // - Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr); - ASSERT_EFI_ERROR (Status); - - // - // store the last available byte, this byte of scancode will be checked - // - ScanCode = ScancodeArr[ScancodeArrPos]; - - if (!Extend1) { - // - // Check for special keys and update the driver state. - // - switch (ScanCode) { - - case SCANCODE_CTRL_MAKE: - if (Extend0) { - ConsoleIn->RightCtrl = TRUE; - } else { - ConsoleIn->LeftCtrl = TRUE; - } - break; - case SCANCODE_CTRL_BREAK: - if (Extend0) { - ConsoleIn->RightCtrl = FALSE; - } else { - ConsoleIn->LeftCtrl = FALSE; - } - break; - - case SCANCODE_ALT_MAKE: - if (Extend0) { - ConsoleIn->RightAlt = TRUE; - } else { - ConsoleIn->LeftAlt = TRUE; - } - break; - case SCANCODE_ALT_BREAK: - if (Extend0) { - ConsoleIn->RightAlt = FALSE; - } else { - ConsoleIn->LeftAlt = FALSE; - } - break; - - case SCANCODE_LEFT_SHIFT_MAKE: - // - // To avoid recognize PRNT_SCRN key as a L_SHIFT key - // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code. - // If it the second byte of the PRNT_ScRN skip it. - // - if (!Extend0) { - ConsoleIn->LeftShift = TRUE; - break; - } - continue; - - case SCANCODE_LEFT_SHIFT_BREAK: - if (!Extend0) { - ConsoleIn->LeftShift = FALSE; - } - break; - - case SCANCODE_RIGHT_SHIFT_MAKE: - ConsoleIn->RightShift = TRUE; - break; - case SCANCODE_RIGHT_SHIFT_BREAK: - ConsoleIn->RightShift = FALSE; - break; - - case SCANCODE_LEFT_LOGO_MAKE: - ConsoleIn->LeftLogo = TRUE; - break; - case SCANCODE_LEFT_LOGO_BREAK: - ConsoleIn->LeftLogo = FALSE; - break; - - case SCANCODE_RIGHT_LOGO_MAKE: - ConsoleIn->RightLogo = TRUE; - break; - case SCANCODE_RIGHT_LOGO_BREAK: - ConsoleIn->RightLogo = FALSE; - break; - - case SCANCODE_MENU_MAKE: - ConsoleIn->Menu = TRUE; - break; - case SCANCODE_MENU_BREAK: - ConsoleIn->Menu = FALSE; - break; - - case SCANCODE_SYS_REQ_MAKE: - if (Extend0) { - ConsoleIn->SysReq = TRUE; - } - break; - case SCANCODE_SYS_REQ_BREAK: - if (Extend0) { - ConsoleIn->SysReq = FALSE; - } - break; - - case SCANCODE_SYS_REQ_MAKE_WITH_ALT: - ConsoleIn->SysReq = TRUE; - break; - case SCANCODE_SYS_REQ_BREAK_WITH_ALT: - ConsoleIn->SysReq = FALSE; - break; - - case SCANCODE_CAPS_LOCK_MAKE: - ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock; - UpdateStatusLights (ConsoleIn); - break; - case SCANCODE_NUM_LOCK_MAKE: - ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock; - UpdateStatusLights (ConsoleIn); - break; - case SCANCODE_SCROLL_LOCK_MAKE: - if (!Extend0) { - ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock; - UpdateStatusLights (ConsoleIn); - } - break; - } - } - - // - // If this is above the valid range, ignore it - // - if (ScanCode >= SCANCODE_MAX_MAKE) { - continue; - } else { - break; - } - } - - // - // Handle Ctrl+Alt+Del hotkey - // - if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) && - (ConsoleIn->LeftAlt || ConsoleIn->RightAlt ) && - ScanCode == SCANCODE_DELETE_MAKE - ) { - gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); - } - - // - // Save the Shift/Toggle state - // - KeyData.KeyState.KeyShiftState = (UINT32) (EFI_SHIFT_STATE_VALID - | (ConsoleIn->LeftCtrl ? EFI_LEFT_CONTROL_PRESSED : 0) - | (ConsoleIn->RightCtrl ? EFI_RIGHT_CONTROL_PRESSED : 0) - | (ConsoleIn->LeftAlt ? EFI_LEFT_ALT_PRESSED : 0) - | (ConsoleIn->RightAlt ? EFI_RIGHT_ALT_PRESSED : 0) - | (ConsoleIn->LeftShift ? EFI_LEFT_SHIFT_PRESSED : 0) - | (ConsoleIn->RightShift ? EFI_RIGHT_SHIFT_PRESSED : 0) - | (ConsoleIn->LeftLogo ? EFI_LEFT_LOGO_PRESSED : 0) - | (ConsoleIn->RightLogo ? EFI_RIGHT_LOGO_PRESSED : 0) - | (ConsoleIn->Menu ? EFI_MENU_KEY_PRESSED : 0) - | (ConsoleIn->SysReq ? EFI_SYS_REQ_PRESSED : 0) - ); - KeyData.KeyState.KeyToggleState = (EFI_KEY_TOGGLE_STATE) (EFI_TOGGLE_STATE_VALID - | (ConsoleIn->CapsLock ? EFI_CAPS_LOCK_ACTIVE : 0) - | (ConsoleIn->NumLock ? EFI_NUM_LOCK_ACTIVE : 0) - | (ConsoleIn->ScrollLock ? EFI_SCROLL_LOCK_ACTIVE : 0) - | (ConsoleIn->IsSupportPartialKey ? EFI_KEY_STATE_EXPOSED : 0) - ); - - KeyData.Key.ScanCode = SCAN_NULL; - KeyData.Key.UnicodeChar = CHAR_NULL; - - // - // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" has E0 prefix - // - if (Extend0 && ScanCode == 0x35) { - KeyData.Key.UnicodeChar = L'/'; - KeyData.Key.ScanCode = SCAN_NULL; - - // - // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix - // - } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) { - KeyData.Key.UnicodeChar = CHAR_NULL; - KeyData.Key.ScanCode = SCAN_PAUSE; - - // - // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL pressed) has E0 prefix - // - } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) { - KeyData.Key.UnicodeChar = CHAR_NULL; - KeyData.Key.ScanCode = SCAN_PAUSE; - - // - // PRNT_SCRN shares the same scancode as that of Key Pad "*" except PRNT_SCRN has E0 prefix - // - } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) { - KeyData.Key.UnicodeChar = CHAR_NULL; - KeyData.Key.ScanCode = SCAN_NULL; - - // - // Except the above special case, all others can be handled by convert table - // - } else { - for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index++) { - if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) { - KeyData.Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode; - KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar; - - if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) && - (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) { - KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar; - // - // Need not return associated shift state if a class of printable characters that - // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F' - // - KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED); - } - // - // alphabetic key is affected by CapsLock State - // - if (ConsoleIn->CapsLock) { - if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { - KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A'); - } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { - KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a'); - } - } - break; - } - } - } - - // - // distinguish numeric key pad keys' 'up symbol' and 'down symbol' - // - if (ScanCode >= 0x47 && ScanCode <= 0x53) { - if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) && !Extend0) { - KeyData.Key.ScanCode = SCAN_NULL; - } else if (ScanCode != 0x4a && ScanCode != 0x4e) { - KeyData.Key.UnicodeChar = CHAR_NULL; - } - } - - // - // If the key can not be converted then just return. - // - if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { - if (!ConsoleIn->IsSupportPartialKey) { - return ; - } - } - - // - // Invoke notification functions if exist - // - for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) { - CurrentNotify = CR ( - Link, - KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, - KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { - CurrentNotify->KeyNotificationFn (&KeyData); - } - } - - PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData); -} - -/** - Perform 8042 controller and keyboard Initialization. - If ExtendedVerification is TRUE, do additional test for - the keyboard interface - - @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer - @param ExtendedVerification - indicates a thorough initialization - - @retval EFI_DEVICE_ERROR Fail to init keyboard - @retval EFI_SUCCESS Success to init keyboard -**/ -EFI_STATUS -InitKeyboard ( - IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - IN BOOLEAN ExtendedVerification - ) -{ - EFI_STATUS Status; - EFI_STATUS Status1; - UINT8 CommandByte; - EFI_PS2_POLICY_PROTOCOL *Ps2Policy; - UINT32 TryTime; - - Status = EFI_SUCCESS; - mEnableMouseInterface = TRUE; - TryTime = 0; - - // - // Get Ps2 policy to set this - // - gBS->LocateProtocol ( - &gEfiPs2PolicyProtocolGuid, - NULL, - (VOID **) &Ps2Policy - ); - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER, - ConsoleIn->DevicePath - ); - - // - // Perform a read to cleanup the Status Register's - // output buffer full bits within MAX TRY times - // - if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) { - while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) { - Status = KeyboardRead (ConsoleIn, &CommandByte); - TryTime ++; - } - // - // Exceed the max try times. The device may be error. - // - if (TryTime == KEYBOARD_MAX_TRY) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - } - // - // We should disable mouse interface during the initialization process - // since mouse device output could block keyboard device output in the - // 60H port of 8042 controller. - // - // So if we are not initializing 8042 controller for the - // first time, we have to remember the previous mouse interface - // enabling state - // - // Test the system flag in to determine whether this is the first - // time initialization - // - if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) { - if (!PcdGetBool (PcdFastPS2Detection)) { - // - // 8042 controller is already setup (by myself or by mouse driver): - // See whether mouse interface is already enabled - // which determines whether we should enable it later - // - // - // Read the command byte of 8042 controller - // - Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"\n\r"); - goto Done; - } - - Status = KeyboardRead (ConsoleIn, &CommandByte); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"\n\r"); - goto Done; - } - // - // Test the mouse enabling bit - // - if ((CommandByte & 0x20) != 0) { - mEnableMouseInterface = FALSE; - } else { - mEnableMouseInterface = TRUE; - } - } else { - mEnableMouseInterface = FALSE; - } - } else { - // - // 8042 controller is not setup yet: - // 8042 controller selftest; - // Don't enable mouse interface later. - // - // - // Disable keyboard and mouse interfaces - // - if (!PcdGetBool (PcdFastPS2Detection)) { - Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"\n\r"); - goto Done; - } - - Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"\n\r"); - goto Done; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST, - ConsoleIn->DevicePath - ); - // - // 8042 Controller Self Test - // - Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); - goto Done; - } - - Status = KeyboardWaitForValue (ConsoleIn, 0x55); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r"); - goto Done; - } - } - // - // Don't enable mouse interface later - // - mEnableMouseInterface = FALSE; - - } - - if (Ps2Policy != NULL) { - Ps2Policy->Ps2InitHardware (ConsoleIn->Handle); - } - // - // Write 8042 Command Byte, set System Flag - // While at the same time: - // 1. disable mouse interface, - // 2. enable kbd interface, - // 3. enable PC/XT kbd translation mode - // 4. enable mouse and kbd interrupts - // - // ( Command Byte bits: - // 7: Reserved - // 6: PC/XT translation mode - // 5: Disable Auxiliary device interface - // 4: Disable keyboard interface - // 3: Reserved - // 2: System Flag - // 1: Enable Auxiliary device interrupt - // 0: Enable Keyboard interrupt ) - // - Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); - goto Done; - } - - Status = KeyboardWrite (ConsoleIn, 0x67); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); - goto Done; - } - - // - // Clear Memory Scancode Buffer - // - ConsoleIn->ScancodeQueue.Head = 0; - ConsoleIn->ScancodeQueue.Tail = 0; - ConsoleIn->EfiKeyQueue.Head = 0; - ConsoleIn->EfiKeyQueue.Tail = 0; - - // - // Reset the status indicators - // - ConsoleIn->CapsLock = FALSE; - ConsoleIn->NumLock = FALSE; - ConsoleIn->ScrollLock = FALSE; - ConsoleIn->LeftCtrl = FALSE; - ConsoleIn->RightCtrl = FALSE; - ConsoleIn->LeftAlt = FALSE; - ConsoleIn->RightAlt = FALSE; - ConsoleIn->LeftShift = FALSE; - ConsoleIn->RightShift = FALSE; - ConsoleIn->LeftLogo = FALSE; - ConsoleIn->RightLogo = FALSE; - ConsoleIn->Menu = FALSE; - ConsoleIn->SysReq = FALSE; - - ConsoleIn->IsSupportPartialKey = FALSE; - // - // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow, - // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected - // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system, - // and normally during booting an OS, it's skipped. - // - if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) { - // - // Additional verifications for keyboard interface - // - // - // Keyboard Interface Test - // - Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); - goto Done; - } - - Status = KeyboardWaitForValue (ConsoleIn, 0x00); - if (EFI_ERROR (Status)) { - KeyboardError ( - ConsoleIn, - L"Some specific value not aquired from 8042 controller!\n\r" - ); - goto Done; - } - // - // Keyboard reset with a BAT(Basic Assurance Test) - // - Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); - goto Done; - } - - Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); - goto Done; - } - // - // wait for BAT completion code - // - mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT; - - Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r"); - goto Done; - } - - mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT; - - // - // Set Keyboard to use Scan Code Set 2 - // - Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); - goto Done; - } - - Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); - goto Done; - } - - Status = KeyboardWrite (ConsoleIn, 0x02); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r"); - goto Done; - } - - Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); - goto Done; - } - - // - // Clear Keyboard Scancode Buffer - // - Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); - goto Done; - } - - Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); - goto Done; - } - // - if (Ps2Policy != NULL) { - if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) { - ConsoleIn->CapsLock = TRUE; - } - - if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) { - ConsoleIn->NumLock = TRUE; - } - - if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) { - ConsoleIn->ScrollLock = TRUE; - } - } - // - // Update Keyboard Lights - // - Status = UpdateStatusLights (ConsoleIn); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r"); - goto Done; - } - } - // - // At last, we can now enable the mouse interface if appropriate - // -Done: - - if (mEnableMouseInterface) { - // - // Enable mouse interface - // - Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE); - if (EFI_ERROR (Status1)) { - KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); - return EFI_DEVICE_ERROR; - } - } - - if (!EFI_ERROR (Status)) { - return EFI_SUCCESS; - } else { - return EFI_DEVICE_ERROR; - } - -} - -/** - Disable the keyboard interface of the 8042 controller. - - @param ConsoleIn The device instance - - @return status of issuing disable command - -**/ -EFI_STATUS -DisableKeyboard ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ) -{ - EFI_STATUS Status; - - // - // Disable keyboard interface - // - Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE); - if (EFI_ERROR (Status)) { - KeyboardError (ConsoleIn, L"\n\r"); - return EFI_DEVICE_ERROR; - } - - return Status; -} - -/** - Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command - If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device - should not be in system. - - @param[in] ConsoleIn Keyboard Private Data Structure - - @retval TRUE Keyboard in System. - @retval FALSE Keyboard not in System. -**/ -BOOLEAN -EFIAPI -CheckKeyboardConnect ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ) -{ - EFI_STATUS Status; - UINTN WaitForValueTimeOutBcakup; - - // - // enable keyboard itself and wait for its ack - // If can't receive ack, Keyboard should not be connected. - // - if (!PcdGetBool (PcdFastPS2Detection)) { - Status = KeyboardWrite ( - ConsoleIn, - KEYBOARD_KBEN - ); - - if (EFI_ERROR (Status)) { - return FALSE; - } - // - // wait for 1s - // - WaitForValueTimeOutBcakup = mWaitForValueTimeOut; - mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT; - Status = KeyboardWaitForValue ( - ConsoleIn, - KEYBOARD_CMDECHO_ACK - ); - mWaitForValueTimeOut = WaitForValueTimeOutBcakup; - - if (EFI_ERROR (Status)) { - return FALSE; - } - - return TRUE; - } else { - return TRUE; - } -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c deleted file mode 100644 index 0efeb39e0d..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c +++ /dev/null @@ -1,683 +0,0 @@ -/** @file - Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces - provided by Ps2KbdCtrller.c. - -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 "Ps2Keyboard.h" - -/** - Check whether the EFI key buffer is empty. - - @param Queue Pointer to instance of EFI_KEY_QUEUE. - - @retval TRUE The EFI key buffer is empty. - @retval FALSE The EFI key buffer isn't empty. -**/ -BOOLEAN -IsEfikeyBufEmpty ( - IN EFI_KEY_QUEUE *Queue - ) -{ - return (BOOLEAN) (Queue->Head == Queue->Tail); -} - -/** - Read & remove one key data from the EFI key buffer. - - @param Queue Pointer to instance of EFI_KEY_QUEUE. - @param KeyData Receive the key data. - - @retval EFI_SUCCESS The key data is popped successfully. - @retval EFI_NOT_READY There is no key data available. -**/ -EFI_STATUS -PopEfikeyBufHead ( - IN EFI_KEY_QUEUE *Queue, - OUT EFI_KEY_DATA *KeyData OPTIONAL - ) -{ - if (IsEfikeyBufEmpty (Queue)) { - return EFI_NOT_READY; - } - // - // Retrieve and remove the values - // - if (KeyData != NULL) { - CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA)); - } - Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT; - return EFI_SUCCESS; -} - -/** - Push one key data to the EFI key buffer. - - @param Queue Pointer to instance of EFI_KEY_QUEUE. - @param KeyData The key data to push. -**/ -VOID -PushEfikeyBufTail ( - IN EFI_KEY_QUEUE *Queue, - IN EFI_KEY_DATA *KeyData - ) -{ - if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) { - // - // If Queue is full, pop the one from head. - // - PopEfikeyBufHead (Queue, NULL); - } - CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA)); - Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT; -} - -/** - Judge whether is a registed key - - @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; - -} - -/** - 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 ConsoleInDev Ps2 Keyboard private structure - @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 -KeyboardReadKeyStrokeWorker ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev, - OUT EFI_KEY_DATA *KeyData - ) - -{ - EFI_STATUS Status; - EFI_TPL OldTpl; - - if (KeyData == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - KeyboardTimerHandler (NULL, ConsoleInDev); - - if (ConsoleInDev->KeyboardErr) { - Status = EFI_DEVICE_ERROR; - } else { - Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData); - } - - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset() - - @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL - @param ExtendedVerification Indicate that the driver may perform a more - exhaustive verification operation of the device during - reset, now this par is ignored in this driver - -**/ -EFI_STATUS -EFIAPI -KeyboardEfiReset ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - EFI_STATUS Status; - KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; - EFI_TPL OldTpl; - - ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); - if (ConsoleIn->KeyboardErr) { - return EFI_DEVICE_ERROR; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET, - ConsoleIn->DevicePath - ); - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Call InitKeyboard to initialize the keyboard - // - Status = InitKeyboard (ConsoleIn, ExtendedVerification); - if (EFI_ERROR (Status)) { - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - return EFI_DEVICE_ERROR; - } - - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - - // - // Report the status If a stuck key was detected - // - if (KeyReadStatusRegister (ConsoleIn) & 0x01) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY, - ConsoleIn->DevicePath - ); - } - // - // Report the status If keyboard is locked - // - if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED, - ConsoleIn->DevicePath - ); - } - - return EFI_SUCCESS; -} - -/** - Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke(). - - @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL - @param Key The output buffer for key value - - @retval EFI_SUCCESS success to read key stroke -**/ -EFI_STATUS -EFIAPI -KeyboardReadKeyStroke ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, - OUT EFI_INPUT_KEY *Key - ) -{ - EFI_STATUS Status; - KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; - EFI_KEY_DATA KeyData; - - ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); - - // - // Considering if the partial keystroke is enabled, there maybe a partial - // keystroke in the queue, so here skip the partial keystroke and get the - // next key from the queue - // - while (1) { - // - // If there is no pending key, then return. - // - Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData); - if (EFI_ERROR (Status)) { - return Status; - } - // - // If it is partial keystroke, skip it. - // - if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { - continue; - } - // - // Translate the CTRL-Alpha characters to their corresponding control value - // (ctrl-a = 0x0001 through ctrl-Z = 0x001A) - // - if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { - if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { - KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); - } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { - KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); - } - } - - CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); - return EFI_SUCCESS; - } -} - -/** - Event notification function for SIMPLE_TEXT_IN.WaitForKey event - Signal the event if there is key available - - @param Event the event object - @param Context waitting context - -**/ -VOID -EFIAPI -KeyboardWaitForKey ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_TPL OldTpl; - KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; - EFI_KEY_DATA KeyData; - - ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context; - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - KeyboardTimerHandler (NULL, ConsoleIn); - - if (!ConsoleIn->KeyboardErr) { - // - // WaitforKey doesn't suppor the partial key. - // Considering if the partial keystroke is enabled, there maybe a partial - // keystroke in the queue, so here skip the partial keystroke and get the - // next key from the queue - // - while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) { - CopyMem ( - &KeyData, - &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]), - sizeof (EFI_KEY_DATA) - ); - if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { - PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData); - continue; - } - // - // if there is pending value key, signal the event. - // - gBS->SignalEvent (Event); - break; - } - } - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); -} - -/** - Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event - Signal the event if there is key available - - @param Event event object - @param Context waiting context - -**/ -VOID -EFIAPI -KeyboardWaitForKeyEx ( - IN EFI_EVENT Event, - IN VOID *Context - ) - -{ - KeyboardWaitForKey (Event, Context); -} - -/** - 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 -KeyboardEfiResetEx ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) - -{ - KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; - - ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); - - return ConsoleInDev->ConIn.Reset ( - &ConsoleInDev->ConIn, - 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 -KeyboardReadKeyStrokeEx ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - OUT EFI_KEY_DATA *KeyData - ) - -{ - KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; - - if (KeyData == NULL) { - return EFI_INVALID_PARAMETER; - } - - ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); - return KeyboardReadKeyStrokeWorker (ConsoleInDev, 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 -KeyboardSetState ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN EFI_KEY_TOGGLE_STATE *KeyToggleState - ) - -{ - EFI_STATUS Status; - KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; - EFI_TPL OldTpl; - - if (KeyToggleState == NULL) { - return EFI_INVALID_PARAMETER; - } - - ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - if (ConsoleInDev->KeyboardErr) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) { - Status = EFI_UNSUPPORTED; - goto Exit; - } - - // - // Update the status light - // - ConsoleInDev->ScrollLock = FALSE; - ConsoleInDev->NumLock = FALSE; - ConsoleInDev->CapsLock = FALSE; - ConsoleInDev->IsSupportPartialKey = FALSE; - - if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { - ConsoleInDev->ScrollLock = TRUE; - } - if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) { - ConsoleInDev->NumLock = TRUE; - } - if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { - ConsoleInDev->CapsLock = TRUE; - } - if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) { - ConsoleInDev->IsSupportPartialKey = TRUE; - } - - Status = UpdateStatusLights (ConsoleInDev); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - } - -Exit: - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - - return Status; - -} - -/** - 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 NotifyHandle or KeyNotificationFunction is NULL. - -**/ -EFI_STATUS -EFIAPI -KeyboardRegisterKeyNotify ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN EFI_KEY_DATA *KeyData, - IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, - OUT VOID **NotifyHandle - ) -{ - EFI_STATUS Status; - KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; - EFI_TPL OldTpl; - LIST_ENTRY *Link; - KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; - KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify; - - if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { - return EFI_INVALID_PARAMETER; - } - - ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. - // - for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) { - CurrentNotify = CR ( - Link, - KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, - KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { - if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { - *NotifyHandle = CurrentNotify; - Status = EFI_SUCCESS; - goto Exit; - } - } - } - - // - // Allocate resource to save the notification function - // - NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY)); - if (NewNotify == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; - NewNotify->KeyNotificationFn = KeyNotificationFunction; - CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); - InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry); - - *NotifyHandle = NewNotify; - Status = EFI_SUCCESS; - -Exit: - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - return Status; - -} - -/** - 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 -KeyboardUnregisterKeyNotify ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN VOID *NotificationHandle - ) -{ - EFI_STATUS Status; - KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev; - EFI_TPL OldTpl; - LIST_ENTRY *Link; - KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; - - if (NotificationHandle == NULL) { - return EFI_INVALID_PARAMETER; - } - - ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) { - CurrentNotify = CR ( - Link, - KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, - KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - if (CurrentNotify == NotificationHandle) { - // - // Remove the notification function from NotifyList and free resources - // - RemoveEntryList (&CurrentNotify->NotifyEntry); - - gBS->FreePool (CurrentNotify); - Status = EFI_SUCCESS; - goto Exit; - } - } - - // - // Can not find the specified Notification Handle - // - Status = EFI_INVALID_PARAMETER; -Exit: - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - return Status; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c deleted file mode 100644 index c020202349..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c +++ /dev/null @@ -1,642 +0,0 @@ -/** @file - - PS/2 Keyboard driver. Routines that interacts with callers, - conforming to EFI driver model - -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 "Ps2Keyboard.h" - -// -// Function prototypes -// -/** - Test controller is a keyboard Controller. - - @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL - @param Controller driver's controller - @param RemainingDevicePath children device path - - @retval EFI_UNSUPPORTED controller is not floppy disk - @retval EFI_SUCCESS controller is floppy disk -**/ -EFI_STATUS -EFIAPI -KbdControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Create KEYBOARD_CONSOLE_IN_DEV instance on controller. - - @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL - @param Controller driver controller handle - @param RemainingDevicePath Children's device path - - @retval whether success to create floppy control instance. -**/ -EFI_STATUS -EFIAPI -KbdControllerDriverStart ( - 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 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 -KbdControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -/** - Free the waiting key notify list. - - @param ListHead Pointer to list head - - @retval EFI_INVALID_PARAMETER ListHead is NULL - @retval EFI_SUCCESS Sucess to free NotifyList -**/ -EFI_STATUS -KbdFreeNotifyList ( - IN OUT LIST_ENTRY *ListHead - ); - -// -// DriverBinding Protocol Instance -// -EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = { - KbdControllerDriverSupported, - KbdControllerDriverStart, - KbdControllerDriverStop, - 0xa, - NULL, - NULL -}; - -/** - Test controller is a keyboard Controller. - - @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL - @param Controller driver's controller - @param RemainingDevicePath children device path - - @retval EFI_UNSUPPORTED controller is not floppy disk - @retval EFI_SUCCESS controller is floppy disk -**/ -EFI_STATUS -EFIAPI -KbdControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_ISA_IO_PROTOCOL *IsaIo; - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Use the ISA I/O Protocol to see if Controller is the Keyboard controller - // - if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) { - Status = EFI_UNSUPPORTED; - } - // - // Close the I/O Abstraction(s) used to perform the supported test - // - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Create KEYBOARD_CONSOLE_IN_DEV instance on controller. - - @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL - @param Controller driver controller handle - @param RemainingDevicePath Children's device path - - @retval whether success to create floppy control instance. -**/ -EFI_STATUS -EFIAPI -KbdControllerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_STATUS Status1; - EFI_ISA_IO_PROTOCOL *IsaIo; - KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; - UINT8 Data; - EFI_STATUS_CODE_VALUE StatusCode; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - - StatusCode = 0; - - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Report that the keyboard is being enabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE, - ParentDevicePath - ); - - // - // Get the ISA I/O Protocol on Controller's handle - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - return EFI_INVALID_PARAMETER; - } - // - // Allocate private data - // - ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV)); - if (ConsoleIn == NULL) { - Status = EFI_OUT_OF_RESOURCES; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; - goto ErrorExit; - } - // - // Setup the device instance - // - ConsoleIn->Signature = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE; - ConsoleIn->Handle = Controller; - (ConsoleIn->ConIn).Reset = KeyboardEfiReset; - (ConsoleIn->ConIn).ReadKeyStroke = KeyboardReadKeyStroke; - ConsoleIn->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER; - ConsoleIn->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER; - ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER; - ConsoleIn->IsaIo = IsaIo; - ConsoleIn->DevicePath = ParentDevicePath; - - ConsoleIn->ConInEx.Reset = KeyboardEfiResetEx; - ConsoleIn->ConInEx.ReadKeyStrokeEx = KeyboardReadKeyStrokeEx; - ConsoleIn->ConInEx.SetState = KeyboardSetState; - ConsoleIn->ConInEx.RegisterKeyNotify = KeyboardRegisterKeyNotify; - ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify; - - InitializeListHead (&ConsoleIn->NotifyList); - - // - // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. - // When KBC decode (IO port 0x60/0x64 decode) is not enabled, - // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS. - // So instead we read status register to detect after read if KBC decode is enabled. - // - - // - // Return code is ignored on purpose. - // - if (!PcdGetBool (PcdFastPS2Detection)) { - KeyboardRead (ConsoleIn, &Data); - if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) { - // - // If nobody decodes KBC I/O port, it will read back as 0xFF. - // Check the Time-Out and Parity bit to see if it has an active KBC in system - // - Status = EFI_DEVICE_ERROR; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; - goto ErrorExit; - } - } - - // - // Setup the WaitForKey event - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_WAIT, - TPL_NOTIFY, - KeyboardWaitForKey, - ConsoleIn, - &((ConsoleIn->ConIn).WaitForKey) - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; - goto ErrorExit; - } - // - // Setup the WaitForKeyEx event - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_WAIT, - TPL_NOTIFY, - KeyboardWaitForKeyEx, - ConsoleIn, - &(ConsoleIn->ConInEx.WaitForKeyEx) - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; - goto ErrorExit; - } - // Setup a periodic timer, used for reading keystrokes at a fixed interval - // - Status = gBS->CreateEvent ( - EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - KeyboardTimerHandler, - ConsoleIn, - &ConsoleIn->TimerEvent - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; - goto ErrorExit; - } - - Status = gBS->SetTimer ( - ConsoleIn->TimerEvent, - TimerPeriodic, - KEYBOARD_TIMER_INTERVAL - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; - goto ErrorExit; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT, - ParentDevicePath - ); - - // - // Reset the keyboard device - // - Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification)); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; - goto ErrorExit; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED, - ParentDevicePath - ); - - ConsoleIn->ControllerNameTable = NULL; - AddUnicodeString2 ( - "eng", - gPs2KeyboardComponentName.SupportedLanguages, - &ConsoleIn->ControllerNameTable, - L"PS/2 Keyboard Device", - TRUE - ); - AddUnicodeString2 ( - "en", - gPs2KeyboardComponentName2.SupportedLanguages, - &ConsoleIn->ControllerNameTable, - L"PS/2 Keyboard Device", - FALSE - ); - - - // - // Install protocol interfaces for the keyboard device. - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiSimpleTextInProtocolGuid, - &ConsoleIn->ConIn, - &gEfiSimpleTextInputExProtocolGuid, - &ConsoleIn->ConInEx, - NULL - ); - if (EFI_ERROR (Status)) { - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; - goto ErrorExit; - } - - return Status; - -ErrorExit: - // - // Report error code - // - if (StatusCode != 0) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - StatusCode, - ParentDevicePath - ); - } - - if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) { - gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey); - } - - if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) { - gBS->CloseEvent (ConsoleIn->TimerEvent); - } - if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) { - gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); - } - KbdFreeNotifyList (&ConsoleIn->NotifyList); - if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) { - FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); - } - // - // Since there will be no timer handler for keyboard input any more, - // exhaust input data just in case there is still keyboard data left - // - if (ConsoleIn != NULL) { - Status1 = EFI_SUCCESS; - while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) { - Status1 = KeyboardRead (ConsoleIn, &Data);; - } - } - - if (ConsoleIn != NULL) { - gBS->FreePool (ConsoleIn); - } - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Stop this driver on ControllerHandle. Support stoping any child handles - created by this driver. - - @param This Protocol instance pointer. - @param 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 -KbdControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; - KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; - UINT8 Data; - - // - // Disable Keyboard - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiSimpleTextInProtocolGuid, - (VOID **) &ConIn, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - Status = gBS->OpenProtocol ( - Controller, - &gEfiSimpleTextInputExProtocolGuid, - NULL, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn); - - // - // Report that the keyboard is being disabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE, - ConsoleIn->DevicePath - ); - - if (ConsoleIn->TimerEvent != NULL) { - gBS->CloseEvent (ConsoleIn->TimerEvent); - ConsoleIn->TimerEvent = NULL; - } - - // - // Since there will be no timer handler for keyboard input any more, - // exhaust input data just in case there is still keyboard data left - // - Status = EFI_SUCCESS; - while (!EFI_ERROR (Status)) { - Status = KeyboardRead (ConsoleIn, &Data);; - } - // - // Uninstall the SimpleTextIn and SimpleTextInEx protocols - // - Status = gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiSimpleTextInProtocolGuid, - &ConsoleIn->ConIn, - &gEfiSimpleTextInputExProtocolGuid, - &ConsoleIn->ConInEx, - NULL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Free other resources - // - if ((ConsoleIn->ConIn).WaitForKey != NULL) { - gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey); - (ConsoleIn->ConIn).WaitForKey = NULL; - } - if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) { - gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); - ConsoleIn->ConInEx.WaitForKeyEx = NULL; - } - KbdFreeNotifyList (&ConsoleIn->NotifyList); - FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); - gBS->FreePool (ConsoleIn); - - return EFI_SUCCESS; -} - -/** - Free the waiting key notify list. - - @param ListHead Pointer to list head - - @retval EFI_INVALID_PARAMETER ListHead is NULL - @retval EFI_SUCCESS Sucess to free NotifyList -**/ -EFI_STATUS -KbdFreeNotifyList ( - IN OUT LIST_ENTRY *ListHead - ) -{ - KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode; - - if (ListHead == NULL) { - return EFI_INVALID_PARAMETER; - } - while (!IsListEmpty (ListHead)) { - NotifyNode = CR ( - ListHead->ForwardLink, - KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, - KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - RemoveEntryList (ListHead->ForwardLink); - gBS->FreePool (NotifyNode); - } - - return EFI_SUCCESS; -} - -/** - The module Entry Point for module Ps2Keyboard. - - @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 -InitializePs2Keyboard( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gKeyboardControllerDriver, - ImageHandle, - &gPs2KeyboardComponentName, - &gPs2KeyboardComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h b/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h deleted file mode 100644 index 2023905538..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h +++ /dev/null @@ -1,550 +0,0 @@ -/** @file - PS/2 keyboard driver header file - -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 _PS2KEYBOARD_H_ -#define _PS2KEYBOARD_H_ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver; -extern EFI_COMPONENT_NAME_PROTOCOL gPs2KeyboardComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gPs2KeyboardComponentName2; - -// -// Driver Private Data -// -#define KEYBOARD_CONSOLE_IN_DEV_SIGNATURE SIGNATURE_32 ('k', 'k', 'e', 'y') -#define KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('k', 'c', 'e', 'n') - -typedef struct _KEYBOARD_CONSOLE_IN_EX_NOTIFY { - UINTN Signature; - EFI_KEY_DATA KeyData; - EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; - LIST_ENTRY NotifyEntry; -} KEYBOARD_CONSOLE_IN_EX_NOTIFY; - -#define KEYBOARD_SCAN_CODE_MAX_COUNT 32 -typedef struct { - UINT8 Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT]; - UINTN Head; - UINTN Tail; -} SCAN_CODE_QUEUE; - -#define KEYBOARD_EFI_KEY_MAX_COUNT 256 -typedef struct { - EFI_KEY_DATA Buffer[KEYBOARD_EFI_KEY_MAX_COUNT]; - UINTN Head; - UINTN Tail; -} EFI_KEY_QUEUE; - -typedef struct { - UINTN Signature; - - EFI_HANDLE Handle; - EFI_SIMPLE_TEXT_INPUT_PROTOCOL ConIn; - EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL ConInEx; - EFI_ISA_IO_PROTOCOL *IsaIo; - - EFI_EVENT TimerEvent; - - UINT32 DataRegisterAddress; - UINT32 StatusRegisterAddress; - UINT32 CommandRegisterAddress; - - BOOLEAN LeftCtrl; - BOOLEAN RightCtrl; - BOOLEAN LeftAlt; - BOOLEAN RightAlt; - BOOLEAN LeftShift; - BOOLEAN RightShift; - BOOLEAN LeftLogo; - BOOLEAN RightLogo; - BOOLEAN Menu; - BOOLEAN SysReq; - - BOOLEAN CapsLock; - BOOLEAN NumLock; - BOOLEAN ScrollLock; - - BOOLEAN IsSupportPartialKey; - // - // Queue storing key scancodes - // - SCAN_CODE_QUEUE ScancodeQueue; - EFI_KEY_QUEUE EfiKeyQueue; - - // - // Error state - // - BOOLEAN KeyboardErr; - - EFI_UNICODE_STRING_TABLE *ControllerNameTable; - - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - // - // Notification Function List - // - LIST_ENTRY NotifyList; -} KEYBOARD_CONSOLE_IN_DEV; - -#define KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) CR (a, KEYBOARD_CONSOLE_IN_DEV, ConIn, KEYBOARD_CONSOLE_IN_DEV_SIGNATURE) -#define TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) \ - CR (a, \ - KEYBOARD_CONSOLE_IN_DEV, \ - ConInEx, \ - KEYBOARD_CONSOLE_IN_DEV_SIGNATURE \ - ) - -#define TABLE_END 0x0 - -// -// Driver entry point -// -/** - The user Entry Point for module Ps2Keyboard. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -InstallPs2KeyboardDriver ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); - -#define KEYBOARD_8042_DATA_REGISTER 0x60 -#define KEYBOARD_8042_STATUS_REGISTER 0x64 -#define KEYBOARD_8042_COMMAND_REGISTER 0x64 - -#define KEYBOARD_KBEN 0xF4 -#define KEYBOARD_CMDECHO_ACK 0xFA - -#define KEYBOARD_MAX_TRY 256 // 256 -#define KEYBOARD_TIMEOUT 65536 // 0.07s -#define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s -#define KEYBOARD_BAT_TIMEOUT 4000000 // 4s -#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s -#define SCANCODE_EXTENDED0 0xE0 -#define SCANCODE_EXTENDED1 0xE1 -#define SCANCODE_CTRL_MAKE 0x1D -#define SCANCODE_CTRL_BREAK 0x9D -#define SCANCODE_ALT_MAKE 0x38 -#define SCANCODE_ALT_BREAK 0xB8 -#define SCANCODE_LEFT_SHIFT_MAKE 0x2A -#define SCANCODE_LEFT_SHIFT_BREAK 0xAA -#define SCANCODE_RIGHT_SHIFT_MAKE 0x36 -#define SCANCODE_RIGHT_SHIFT_BREAK 0xB6 -#define SCANCODE_CAPS_LOCK_MAKE 0x3A -#define SCANCODE_NUM_LOCK_MAKE 0x45 -#define SCANCODE_SCROLL_LOCK_MAKE 0x46 -#define SCANCODE_DELETE_MAKE 0x53 -#define SCANCODE_LEFT_LOGO_MAKE 0x5B //GUI key defined in Keyboard scan code -#define SCANCODE_LEFT_LOGO_BREAK 0xDB -#define SCANCODE_RIGHT_LOGO_MAKE 0x5C -#define SCANCODE_RIGHT_LOGO_BREAK 0xDC -#define SCANCODE_MENU_MAKE 0x5D //APPS key defined in Keyboard scan code -#define SCANCODE_MENU_BREAK 0xDD -#define SCANCODE_SYS_REQ_MAKE 0x37 -#define SCANCODE_SYS_REQ_BREAK 0xB7 -#define SCANCODE_SYS_REQ_MAKE_WITH_ALT 0x54 -#define SCANCODE_SYS_REQ_BREAK_WITH_ALT 0xD4 - -#define SCANCODE_MAX_MAKE 0x60 - - -#define KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA BIT0 ///< 0 - Output register has no data; 1 - Output register has data -#define KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA BIT1 ///< 0 - Input register has no data; 1 - Input register has data -#define KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG BIT2 ///< Set to 0 after power on reset -#define KEYBOARD_STATUS_REGISTER_INPUT_DATA_TYPE BIT3 ///< 0 - Data in input register is data; 1 - Data in input register is command -#define KEYBOARD_STATUS_REGISTER_ENABLE_FLAG BIT4 ///< 0 - Keyboard is disable; 1 - Keyboard is enable -#define KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT BIT5 ///< 0 - Transmit is complete without timeout; 1 - Transmit is timeout without complete -#define KEYBOARD_STATUS_REGISTER_RECEIVE_TIMEOUT BIT6 ///< 0 - Receive is complete without timeout; 1 - Receive is timeout without complete -#define KEYBOARD_STATUS_REGISTER_PARITY BIT7 ///< 0 - Odd parity; 1 - Even parity - -#define KEYBOARD_8042_COMMAND_READ 0x20 -#define KEYBOARD_8042_COMMAND_WRITE 0x60 -#define KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE 0xA7 -#define KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE 0xA8 -#define KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST 0xAA -#define KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST 0xAB -#define KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE 0xAD - -#define KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA 0xF4 -#define KEYBOARD_8048_COMMAND_RESET 0xFF -#define KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET 0xF0 - -#define KEYBOARD_8048_RETURN_8042_BAT_SUCCESS 0xAA -#define KEYBOARD_8048_RETURN_8042_BAT_ERROR 0xFC -#define KEYBOARD_8048_RETURN_8042_ACK 0xFA - - -// -// Keyboard Controller Status -// -#define KBC_PARE 0x80 // Parity Error -#define KBC_TIM 0x40 // General Time Out - -// -// Other functions that are used among .c files -// -/** - Show keyboard status lights according to - indicators in ConsoleIn. - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - - @return status - -**/ -EFI_STATUS -UpdateStatusLights ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ); - -/** - write key to keyboard. - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - @param Data value wanted to be written - - @retval EFI_TIMEOUT - GC_TODO: Add description for return value - @retval EFI_SUCCESS - GC_TODO: Add description for return value - -**/ -EFI_STATUS -KeyboardRead ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - OUT UINT8 *Data - ); - -/** - Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec. - - The function is always called in TPL_NOTIFY. - - @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer - -**/ -VOID -KeyGetchar ( - IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ); - -/** - Perform 8042 controller and keyboard Initialization. - If ExtendedVerification is TRUE, do additional test for - the keyboard interface - - @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer - @param ExtendedVerification - indicates a thorough initialization - - @retval EFI_DEVICE_ERROR Fail to init keyboard - @retval EFI_SUCCESS Success to init keyboard -**/ -EFI_STATUS -InitKeyboard ( - IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, - IN BOOLEAN ExtendedVerification - ); - -/** - Disable the keyboard interface of the 8042 controller. - - @param ConsoleIn - the device instance - - @return status of issuing disable command - -**/ -EFI_STATUS -DisableKeyboard ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ); - -/** - Timer event handler: read a series of scancodes from 8042 - and put them into memory scancode buffer. - it read as much scancodes to either fill - the memory buffer or empty the keyboard buffer. - It is registered as running under TPL_NOTIFY - - @param Event - The timer event - @param Context - A KEYBOARD_CONSOLE_IN_DEV pointer - -**/ -VOID -EFIAPI -KeyboardTimerHandler ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - logic reset keyboard - Implement SIMPLE_TEXT_IN.Reset() - Perform 8042 controller and keyboard initialization - - @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL - @param ExtendedVerification Indicate that the driver may perform a more - exhaustive verification operation of the device during - reset, now this par is ignored in this driver - -**/ -EFI_STATUS -EFIAPI -KeyboardEfiReset ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Implement SIMPLE_TEXT_IN.ReadKeyStroke(). - Retrieve key values for driver user. - - @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL - @param Key The output buffer for key value - - @retval EFI_SUCCESS success to read key stroke -**/ -EFI_STATUS -EFIAPI -KeyboardReadKeyStroke ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, - OUT EFI_INPUT_KEY *Key - ); - -/** - Event notification function for SIMPLE_TEXT_IN.WaitForKey event - Signal the event if there is key available - - @param Event the event object - @param Context waitting context - -**/ -VOID -EFIAPI -KeyboardWaitForKey ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - Read status register. - - @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - - @return value in status register - -**/ -UINT8 -KeyReadStatusRegister ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ); - -/** - Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command - If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device - should not be in system. - - @param[in] ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV - - @retval TRUE Keyboard in System. - @retval FALSE Keyboard not in System. -**/ -BOOLEAN -EFIAPI -CheckKeyboardConnect ( - IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn - ); - -/** - Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event - Signal the event if there is key available - - @param Event event object - @param Context waiting context - -**/ -VOID -EFIAPI -KeyboardWaitForKeyEx ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -// -// 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 -KeyboardEfiResetEx ( - 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 -KeyboardReadKeyStrokeEx ( - 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 -KeyboardSetState ( - 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 NotifyHandle is NULL. - -**/ -EFI_STATUS -EFIAPI -KeyboardRegisterKeyNotify ( - 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 -KeyboardUnregisterKeyNotify ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN VOID *NotificationHandle - ); - -/** - Push one key data to the EFI key buffer. - - @param Queue Pointer to instance of EFI_KEY_QUEUE. - @param KeyData The key data to push. -**/ -VOID -PushEfikeyBufTail ( - IN EFI_KEY_QUEUE *Queue, - IN EFI_KEY_DATA *KeyData - ); - -/** - Judge whether is a registed key - - @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 - ); - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni b/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni deleted file mode 100644 index 0410dd216a..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni b/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni deleted file mode 100644 index 155d2515f8..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf b/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf deleted file mode 100644 index 13c1ea9091..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf +++ /dev/null @@ -1,85 +0,0 @@ -## @file -# Ps2 Keyboard Driver. -# -# Ps2 Keyboard Driver for UEFI. The keyboard type implemented follows IBM -# compatible PS2 protocol using Scan Code Set 1. -# -# 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 -# 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 = Ps2KeyboardDxe - MODULE_UNI_FILE = Ps2KeyboardDxe.uni - FILE_GUID = 3DC82376-637B-40a6-A8FC-A565417F2C38 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializePs2Keyboard - -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# DRIVER_BINDING = gKeyboardControllerDriver; -# COMPONENT_NAME = gPs2KeyboardComponentName; -# COMPONENT_NAME2 = gPs2KeyboardComponentName2; -# - -[Sources] - ComponentName.c - Ps2Keyboard.h - Ps2KbdCtrller.c - Ps2KbdTextIn.c - Ps2Keyboard.c - - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - MemoryAllocationLib - UefiRuntimeServicesTableLib - DebugLib - ReportStatusCodeLib - UefiBootServicesTableLib - UefiLib - UefiDriverEntryPoint - BaseLib - BaseMemoryLib - TimerLib - PcdLib - -[Protocols] - gEfiSimpleTextInProtocolGuid ## BY_START - gEfiSimpleTextInputExProtocolGuid ## BY_START - gEfiPs2PolicyProtocolGuid ## SOMETIMES_CONSUMES - gEfiIsaIoProtocolGuid ## TO_START - gEfiDevicePathProtocolGuid ## TO_START - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification ## CONSUMES - -[Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection ## SOMETIMES_CONSUMES - -# -# [Event] -# -# ## -# # Timer event used to read key strokes at a regular interval. -# # -# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES -# - -[UserExtensions.TianoCore."ExtraFiles"] - Ps2KeyboardDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c deleted file mode 100644 index fb4a75348c..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c +++ /dev/null @@ -1,923 +0,0 @@ -/** @file - PS2 Mouse Communication Interface. - -Copyright (c) 2006 - 2007, Intel 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 "Ps2MouseAbsolutePointer.h" -#include "CommPs2.h" - -UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 }; - -UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 }; - -/** - Issue self test command via IsaIo interface. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return EFI_SUCCESS Success to do keyboard self testing. - @return others Fail to do keyboard self testing. -**/ -EFI_STATUS -KbcSelfTest ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Keyboard controller self test - // - Status = Out8042Command (IsaIo, SELF_TEST); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Read return code - // - Status = In8042Data (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - - if (Data != 0x55) { - return EFI_DEVICE_ERROR; - } - // - // Set system flag - // - Status = Out8042Command (IsaIo, READ_CMD_BYTE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = In8042Data (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = Out8042Command (IsaIo, WRITE_CMD_BYTE); - if (EFI_ERROR (Status)) { - return Status; - } - - Data |= CMD_SYS_FLAG; - Status = Out8042Data (IsaIo, Data); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - Issue command to enable keyboard AUX functionality. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcEnableAux ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send 8042 enable mouse command - // - return Out8042Command (IsaIo, ENABLE_AUX); -} - -/** - Issue command to disable keyboard AUX functionality. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcDisableAux ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send 8042 disable mouse command - // - return Out8042Command (IsaIo, DISABLE_AUX); -} - -/** - Issue command to enable keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcEnableKb ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send 8042 enable keyboard command - // - return Out8042Command (IsaIo, ENABLE_KB); -} - -/** - Issue command to disable keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcDisableKb ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send 8042 disable keyboard command - // - return Out8042Command (IsaIo, DISABLE_KB); -} - -/** - Issue command to check keyboard status. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param KeyboardEnable return whether keyboard is enable. - - @return Status of command issuing. -**/ -EFI_STATUS -CheckKbStatus ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - OUT BOOLEAN *KeyboardEnable - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Send command to read KBC command byte - // - Status = Out8042Command (IsaIo, READ_CMD_BYTE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = In8042Data (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check keyboard enable or not - // - if ((Data & CMD_KB_STS) == CMD_KB_DIS) { - *KeyboardEnable = FALSE; - } else { - *KeyboardEnable = TRUE; - } - - return EFI_SUCCESS; -} - -/** - Issue command to reset keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseReset ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - EFI_STATUS Status; - UINT8 Data; - - Status = Out8042AuxCommand (IsaIo, RESET_CMD, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = In8042AuxData (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check BAT Complete Code - // - if (Data != PS2MOUSE_BAT1) { - return EFI_DEVICE_ERROR; - } - - Status = In8042AuxData (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check BAT Complete Code - // - if (Data != PS2MOUSE_BAT2) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Issue command to set mouse's sample rate - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param SampleRate value of sample rate - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetSampleRate ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_SR SampleRate - ) -{ - EFI_STATUS Status; - - // - // Send auxiliary command to set mouse sample rate - // - Status = Out8042AuxCommand (IsaIo, SETSR_CMD, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = Out8042AuxData (IsaIo, SampleRateTbl[SampleRate]); - - return Status; -} - -/** - Issue command to set mouse's resolution. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Resolution value of resolution - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetResolution ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_RE Resolution - ) -{ - EFI_STATUS Status; - - // - // Send auxiliary command to set mouse resolution - // - Status = Out8042AuxCommand (IsaIo, SETRE_CMD, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = Out8042AuxData (IsaIo, ResolutionTbl[Resolution]); - - return Status; -} - -/** - Issue command to set mouse's scaling. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Scaling value of scaling - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetScaling ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_SF Scaling - ) -{ - UINT8 Command; - - Command = (UINT8) (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD); - - // - // Send auxiliary command to set mouse scaling data - // - return Out8042AuxCommand (IsaIo, Command, FALSE); -} - -/** - Issue command to enable Ps2 mouse. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseEnable ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send auxiliary command to enable mouse - // - return Out8042AuxCommand (IsaIo, ENABLE_CMD, FALSE); -} - -/** - Get mouse packet . Only care first 3 bytes - - @param MouseAbsolutePointerDev Pointer to PS2 Absolute Pointer Simulation Device Private Data Structure - - @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet - @retval EFI_SUCCESS The data packet is gotten successfully. - -**/ -EFI_STATUS -PS2MouseGetPacket ( - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev - ) - -{ - EFI_STATUS Status; - BOOLEAN KeyboardEnable; - UINT8 Packet[PS2_PACKET_LENGTH]; - UINT8 Data; - UINTN Count; - UINTN State; - INT16 RelativeMovementX; - INT16 RelativeMovementY; - BOOLEAN LButton; - BOOLEAN RButton; - - KeyboardEnable = FALSE; - Count = 1; - State = PS2_READ_BYTE_ONE; - - // - // State machine to get mouse packet - // - while (1) { - - switch (State) { - case PS2_READ_BYTE_ONE: - // - // Read mouse first byte data, if failed, immediately return - // - KbcDisableAux (MouseAbsolutePointerDev->IsaIo); - Status = PS2MouseRead (MouseAbsolutePointerDev->IsaIo, &Data, &Count, State); - if (EFI_ERROR (Status)) { - KbcEnableAux (MouseAbsolutePointerDev->IsaIo); - return EFI_NOT_READY; - } - - if (Count != 1) { - KbcEnableAux (MouseAbsolutePointerDev->IsaIo); - return EFI_NOT_READY; - } - - if (IS_PS2_SYNC_BYTE (Data)) { - Packet[0] = Data; - State = PS2_READ_DATA_BYTE; - - CheckKbStatus (MouseAbsolutePointerDev->IsaIo, &KeyboardEnable); - KbcDisableKb (MouseAbsolutePointerDev->IsaIo); - KbcEnableAux (MouseAbsolutePointerDev->IsaIo); - } - break; - - case PS2_READ_DATA_BYTE: - Count = 2; - Status = PS2MouseRead (MouseAbsolutePointerDev->IsaIo, (Packet + 1), &Count, State); - if (EFI_ERROR (Status)) { - if (KeyboardEnable) { - KbcEnableKb (MouseAbsolutePointerDev->IsaIo); - } - - return EFI_NOT_READY; - } - - if (Count != 2) { - if (KeyboardEnable) { - KbcEnableKb (MouseAbsolutePointerDev->IsaIo); - } - - return EFI_NOT_READY; - } - - State = PS2_PROCESS_PACKET; - break; - - case PS2_PROCESS_PACKET: - if (KeyboardEnable) { - KbcEnableKb (MouseAbsolutePointerDev->IsaIo); - } - // - // Decode the packet - // - RelativeMovementX = Packet[1]; - RelativeMovementY = Packet[2]; - // - // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 - // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn - // Byte 1 | 8 bit X Movement - // Byte 2 | 8 bit Y Movement - // - // X sign bit + 8 bit X Movement : 9-bit signed twos complement integer that presents the relative displacement of the device in the X direction since the last data transmission. - // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement. - // - // - // First, Clear X and Y high 8 bits - // - RelativeMovementX = (INT16) (RelativeMovementX & 0xFF); - RelativeMovementY = (INT16) (RelativeMovementY & 0xFF); - // - // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff - // - if ((Packet[0] & 0x10) != 0) { - RelativeMovementX = (INT16) (RelativeMovementX | 0xFF00); - } - if ((Packet[0] & 0x20) != 0) { - RelativeMovementY = (INT16) (RelativeMovementY | 0xFF00); - } - - - RButton = (UINT8) (Packet[0] & 0x2); - LButton = (UINT8) (Packet[0] & 0x1); - - // - // Update mouse state - // - MouseAbsolutePointerDev->State.CurrentX += RelativeMovementX; - MouseAbsolutePointerDev->State.CurrentY -= RelativeMovementY; - MouseAbsolutePointerDev->State.CurrentZ = 0; - MouseAbsolutePointerDev->State.ActiveButtons = (UINT8) (LButton || RButton) & 0x3; - MouseAbsolutePointerDev->StateChanged = TRUE; - - return EFI_SUCCESS; - } - } -} - -/** - Read data via IsaIo protocol with given number. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Buffer Buffer receive data of mouse - @param BufSize The size of buffer - @param State Check input or read data - - @return status of reading mouse data. -**/ -EFI_STATUS -PS2MouseRead ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - OUT VOID *Buffer, - IN OUT UINTN *BufSize, - IN UINTN State - ) -{ - EFI_STATUS Status; - UINTN BytesRead; - - Status = EFI_SUCCESS; - BytesRead = 0; - - if (State == PS2_READ_BYTE_ONE) { - // - // Check input for mouse - // - Status = CheckForInput (IsaIo); - - if (EFI_ERROR (Status)) { - return Status; - } - } - - while (BytesRead < *BufSize) { - - Status = WaitOutputFull (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - break; - } - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Buffer); - - BytesRead++; - Buffer = (UINT8 *) Buffer + 1; - } - // - // Verify the correct number of bytes read - // - if (BytesRead == 0 || BytesRead != *BufSize) { - Status = EFI_NOT_FOUND; - } - - *BufSize = BytesRead; - return Status; -} - -// -// 8042 I/O function -// -/** - I/O work flow of outing 8042 command. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Command I/O command. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042Command ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Command - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Wait keyboard controller input buffer empty - // - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Send command - // - Data = Command; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow of outing 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Data - ) -{ - EFI_STATUS Status; - UINT8 Temp; - // - // Wait keyboard controller input buffer empty - // - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - Temp = Data; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow of in 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ) -{ - UINTN Delay; - UINT8 Temp; - - Delay = TIMEOUT / 50; - - do { - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp); - - // - // Check keyboard controller status bit 0(output buffer status) - // - if ((Temp & KBC_OUTB) == KBC_OUTB) { - break; - } - - gBS->Stall (50); - Delay--; - } while (Delay != 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data); - - return EFI_SUCCESS; -} - -/** - I/O work flow of outing 8042 Aux command. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Command Aux I/O command - @param Resend Whether need resend the Aux command. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042AuxCommand ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Command, - IN BOOLEAN Resend - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Wait keyboard controller input buffer empty - // - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Send write to auxiliary device command - // - Data = WRITE_AUX_DEV; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Send auxiliary device command - // - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command); - - // - // Read return code - // - Status = In8042AuxData (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - - if (Data == PS2_ACK) { - // - // Receive mouse acknowledge, command send success - // - return EFI_SUCCESS; - - } else if (Resend) { - // - // Resend fail - // - return EFI_DEVICE_ERROR; - - } else if (Data == PS2_RESEND) { - // - // Resend command - // - Status = Out8042AuxCommand (IsaIo, Command, TRUE); - if (EFI_ERROR (Status)) { - return Status; - } - - } else { - // - // Invalid return code - // - return EFI_DEVICE_ERROR; - - } - - return EFI_SUCCESS; -} - -/** - I/O work flow of outing 8042 Aux data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Buffer holding return value - - @retval EFI_SUCCESS Success to excute I/O work flow. - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042AuxData ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Data - ) -{ - EFI_STATUS Status; - UINT8 Temp; - // - // Wait keyboard controller input buffer empty - // - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Send write to auxiliary device command - // - Temp = WRITE_AUX_DEV; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - Temp = Data; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow of in 8042 Aux data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Buffer holding return value. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042AuxData ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ) -{ - EFI_STATUS Status; - - // - // wait for output data - // - Status = WaitOutputFull (IsaIo, BAT_TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data); - - return EFI_SUCCESS; -} - - -/** - Check keyboard controller status, if it is output buffer full and for auxiliary device. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @retval EFI_SUCCESS Keyboard controller is ready - @retval EFI_NOT_READY Keyboard controller is not ready -**/ -EFI_STATUS -CheckForInput ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - UINT8 Data; - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - // - // Check keyboard controller status, if it is output buffer full and for auxiliary device - // - if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) { - return EFI_NOT_READY; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow to wait input buffer empty in given time. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Timeout Wating time. - - @retval EFI_TIMEOUT if input is still not empty in given time. - @retval EFI_SUCCESS input is empty. -**/ -EFI_STATUS -WaitInputEmpty ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINTN Timeout - ) -{ - UINTN Delay; - UINT8 Data; - - Delay = Timeout / 50; - - do { - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - // - // Check keyboard controller status bit 1(input buffer status) - // - if ((Data & KBC_INPB) == 0) { - break; - } - - gBS->Stall (50); - Delay--; - } while (Delay != 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow to wait output buffer full in given time. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Timeout given time - - @retval EFI_TIMEOUT output is not full in given time - @retval EFI_SUCCESS output is full in given time. -**/ -EFI_STATUS -WaitOutputFull ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINTN Timeout - ) -{ - UINTN Delay; - UINT8 Data; - - Delay = Timeout / 50; - - do { - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - // - // Check keyboard controller status bit 0(output buffer status) - // & bit5(output buffer for auxiliary device) - // - if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) { - break; - } - - gBS->Stall (50); - Delay--; - } while (Delay != 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h deleted file mode 100644 index 59d7b51d44..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.h +++ /dev/null @@ -1,435 +0,0 @@ -/** @file - Using PS2 Mouse to simulation Absolution Pointer Device. - -Copyright (c) 2006 - 2009, Intel 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 __COMMPS2_H__ -#define __COMMPS2_H__ - -#define PS2_PACKET_LENGTH 3 -#define PS2_SYNC_MASK 0xc -#define PS2_SYNC_BYTE 0x8 - -#define IS_PS2_SYNC_BYTE(byte) ((byte & PS2_SYNC_MASK) == PS2_SYNC_BYTE) - -#define PS2_READ_BYTE_ONE 0 -#define PS2_READ_DATA_BYTE 1 -#define PS2_PROCESS_PACKET 2 - -#define TIMEOUT 50000 -#define BAT_TIMEOUT 500000 - -// -// 8042 I/O Port -// -#define KBC_DATA_PORT 0x60 -#define KBC_CMD_STS_PORT 0x64 - -// -// 8042 Command -// -#define READ_CMD_BYTE 0x20 -#define WRITE_CMD_BYTE 0x60 -#define DISABLE_AUX 0xa7 -#define ENABLE_AUX 0xa8 -#define SELF_TEST 0xaa -#define DISABLE_KB 0xad -#define ENABLE_KB 0xae -#define WRITE_AUX_DEV 0xd4 - -#define CMD_SYS_FLAG 0x04 -#define CMD_KB_STS 0x10 -#define CMD_KB_DIS 0x10 -#define CMD_KB_EN 0x0 - -// -// 8042 Auxiliary Device Command -// -#define SETSF1_CMD 0xe6 -#define SETSF2_CMD 0xe7 -#define SETRE_CMD 0xe8 -#define READ_CMD 0xeb -#define SETRM_CMD 0xf0 -#define SETSR_CMD 0xf3 -#define ENABLE_CMD 0xf4 -#define DISABLE_CMD 0xf5 -#define RESET_CMD 0xff - -// -// return code -// -#define PS2_ACK 0xfa -#define PS2_RESEND 0xfe -#define PS2MOUSE_BAT1 0xaa -#define PS2MOUSE_BAT2 0x0 - -// -// Keyboard Controller Status -// -/// -/// Parity Error -/// -#define KBC_PARE 0x80 -/// -/// General Time Out -/// -#define KBC_TIM 0x40 -/// -/// Output buffer for auxiliary device (PS/2): -/// 0 - Holds keyboard data -/// 1 - Holds data for auxiliary device -/// -#define KBC_AUXB 0x20 -/// -/// Keyboard lock status: -/// 0 - keyboard locked -/// 1 - keyboard free -/// -#define KBC_KEYL 0x10 -/// -/// Command/Data: -/// 0 - data byte written via port 60h -/// 1 - command byte written via port 64h -/// -#define KBC_CD 0x08 -/// -/// System Flag: -/// 0 - power-on reset -/// 1 - self-test successful -/// -#define KBC_SYSF 0x04 -/// -/// Input Buffer Status : -/// 0 - input buffer empty -/// 1 - CPU data in input buffer -/// -#define KBC_INPB 0x02 -/// -/// Output Buffer Status : -/// 0 - output buffer empty -/// 1 - keyboard controller data in output buffer -/// -#define KBC_OUTB 0x01 - -/** - Issue self test command via IsaIo interface. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return EFI_SUCCESS Success to do keyboard self testing. - @return others Fail to do keyboard self testing. -**/ -EFI_STATUS -KbcSelfTest ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to enable keyboard AUX functionality. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcEnableAux ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to disable keyboard AUX functionality. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcDisableAux ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to enable keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcEnableKb ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to disable keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcDisableKb ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to check keyboard status. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param KeyboardEnable return whether keyboard is enable. - - @return Status of command issuing. -**/ -EFI_STATUS -CheckKbStatus ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - OUT BOOLEAN *KeyboardEnable - ); - -/** - Issue command to reset keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseReset ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to set mouse's sample rate - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param SampleRate value of sample rate - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetSampleRate ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_SR SampleRate - ); - -/** - Issue command to set mouse's resolution. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Resolution value of resolution - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetResolution ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_RE Resolution - ); - -/** - Issue command to set mouse's scaling. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Scaling value of scaling - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetScaling ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_SF Scaling - ); - -/** - Issue command to enable Ps2 mouse. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseEnable ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Get mouse packet . Only care first 3 bytes - - @param MouseAbsolutePointerDev Pointer to PS2 Absolute Pointer Simulation Device Private Data Structure - - @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet - @retval EFI_SUCCESS The data packet is gotten successfully. - -**/ -EFI_STATUS -PS2MouseGetPacket ( - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev - ); - -/** - Read data via IsaIo protocol with given number. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Buffer Buffer receive data of mouse - @param BufSize The size of buffer - @param State Check input or read data - - @return status of reading mouse data. -**/ -EFI_STATUS -PS2MouseRead ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - OUT VOID *Buffer, - IN OUT UINTN *BufSize, - IN UINTN State - ); - -// -// 8042 I/O function -// -/** - I/O work flow of outing 8042 command. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Command I/O command. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042Command ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Command - ); - -/** - I/O work flow of in 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ); - -/** - I/O work flow of outing 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Data - ); - -/** - I/O work flow of outing 8042 Aux command. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Command Aux I/O command - @param Resend Whether need resend the Aux command. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042AuxCommand ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Command, - IN BOOLEAN Resend - ); - -/** - I/O work flow of in 8042 Aux data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Buffer holding return value. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042AuxData ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ); - -/** - I/O work flow of outing 8042 Aux data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Buffer holding return value. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042AuxData ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Data - ); - -/** - Check keyboard controller status, if it is output buffer full and for auxiliary device. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @retval EFI_SUCCESS Keyboard controller is ready - @retval EFI_NOT_READY Keyboard controller is not ready -**/ -EFI_STATUS -CheckForInput ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - I/O work flow to wait input buffer empty in given time. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Timeout Wating time. - - @retval EFI_TIMEOUT if input is still not empty in given time. - @retval EFI_SUCCESS input is empty. -**/ -EFI_STATUS -WaitInputEmpty ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINTN Timeout - ); - -/** - I/O work flow to wait output buffer full in given time. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Timeout given time - - @retval EFI_TIMEOUT output is not full in given time - @retval EFI_SUCCESS output is full in given time. -**/ -EFI_STATUS -WaitOutputFull ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINTN Timeout - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c deleted file mode 100644 index 8fbef28985..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/ComponentName.c +++ /dev/null @@ -1,241 +0,0 @@ -/** @file - UEFI Component Name(2) protocol implementation for Ps2 Absolute Pointer Simulation Dxe 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 "Ps2MouseAbsolutePointer.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPs2MouseAbsolutePointerComponentName = { - Ps2MouseAbsolutePointerComponentNameGetDriverName, - Ps2MouseAbsolutePointerComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPs2MouseAbsolutePointerComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ps2MouseAbsolutePointerComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ps2MouseAbsolutePointerComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPs2MouseAbsolutePointerDriverNameTable[] = { - { - "eng;en", - L"faked PS/2 Touchpad Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -Ps2MouseAbsolutePointerComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mPs2MouseAbsolutePointerDriverNameTable, - DriverName, - (BOOLEAN)(This == &gPs2MouseAbsolutePointerComponentName) - ); -} - -/** - 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 -Ps2MouseAbsolutePointerComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol; - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; - EFI_ISA_IO_PROTOCOL *IsaIoProtocol; - - // - // This is a device driver, so ChildHandle must be NULL. - // - if (ChildHandle != NULL) { - return EFI_UNSUPPORTED; - } - // - // Check Controller's handle - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIoProtocol, - gPS2MouseAbsolutePointerDriver.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (!EFI_ERROR (Status)) { - gBS->CloseProtocol ( - ControllerHandle, - &gEfiIsaIoProtocolGuid, - gPS2MouseAbsolutePointerDriver.DriverBindingHandle, - ControllerHandle - ); - - return EFI_UNSUPPORTED; - } - - if (Status != EFI_ALREADY_STARTED) { - return EFI_UNSUPPORTED; - } - // - // Get the device context - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiAbsolutePointerProtocolGuid, - (VOID **) &AbsolutePointerProtocol, - gPS2MouseAbsolutePointerDriver.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (AbsolutePointerProtocol); - - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - MouseAbsolutePointerDev->ControllerNameTable, - ControllerName, - (BOOLEAN)(This == &gPs2MouseAbsolutePointerComponentName) - ); -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.c deleted file mode 100644 index 7af35bcd11..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.c +++ /dev/null @@ -1,778 +0,0 @@ -/** @file - A faked PS/2 Absolute Pointer driver. Routines that interacts with callers, - conforming to EFI driver model - -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 "Ps2MouseAbsolutePointer.h" -#include "CommPs2.h" - -// -// DriverBinding Protocol Instance -// -EFI_DRIVER_BINDING_PROTOCOL gPS2MouseAbsolutePointerDriver = { - PS2MouseAbsolutePointerDriverSupported, - PS2MouseAbsolutePointerDriverStart, - PS2MouseAbsolutePointerDriverStop, - 0x1, - NULL, - NULL -}; - -/** - Test to see if this driver supports ControllerHandle. Any ControllerHandle - than contains a IsaIo protocol can be supported. - - @param This 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 EFI_ALREADY_STARTED This driver is already running on this device - @retval other This driver does not support this device - -**/ -EFI_STATUS -EFIAPI -PS2MouseAbsolutePointerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_ISA_IO_PROTOCOL *IsaIo; - - Status = EFI_SUCCESS; - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Use the ISA I/O Protocol to see if Controller is the Mouse controller - // - switch (IsaIo->ResourceList->Device.HID) { - case EISA_PNP_ID (0xF03): - // - // Microsoft PS/2 style mouse - // - case EISA_PNP_ID (0xF13): - // - // PS/2 Port for PS/2-style Mice - // - break; - - case EISA_PNP_ID (0x303): - // - // IBM Enhanced (101/102-key, PS/2 mouse support) - // - if (IsaIo->ResourceList->Device.UID == 1) { - break; - } - - default: - Status = EFI_UNSUPPORTED; - break; - } - // - // Close the I/O Abstraction(s) used to perform the supported test - // - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Start this driver on ControllerHandle by opening a IsaIo protocol, creating - PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid - finally. - - @param This 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 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 -PS2MouseAbsolutePointerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_STATUS EmptyStatus; - EFI_ISA_IO_PROTOCOL *IsaIo; - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; - UINT8 Data; - EFI_TPL OldTpl; - EFI_STATUS_CODE_VALUE StatusCode; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - - StatusCode = 0; - MouseAbsolutePointerDev = NULL; - IsaIo = NULL; - - // - // Open the device path protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Report that the keyboard is being enabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE, - ParentDevicePath - ); - - // - // Get the ISA I/O Protocol on Controller's handle - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - return EFI_INVALID_PARAMETER; - } - // - // Raise TPL to avoid keyboard operation impact - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Allocate private data - // - MouseAbsolutePointerDev = AllocateZeroPool (sizeof (PS2_MOUSE_ABSOLUTE_POINTER_DEV)); - if (MouseAbsolutePointerDev == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - // - // Setup the device instance - // - MouseAbsolutePointerDev->Signature = PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE; - MouseAbsolutePointerDev->Handle = Controller; - MouseAbsolutePointerDev->SampleRate = SampleRate20; - MouseAbsolutePointerDev->Resolution = MouseResolution4; - MouseAbsolutePointerDev->Scaling = Scaling1; - MouseAbsolutePointerDev->DataPackageSize = 3; - MouseAbsolutePointerDev->IsaIo = IsaIo; - MouseAbsolutePointerDev->DevicePath = ParentDevicePath; - - // - // Resolution = 4 counts/mm - // - MouseAbsolutePointerDev->Mode.AbsoluteMaxX = 1024; - MouseAbsolutePointerDev->Mode.AbsoluteMinX = 0; - MouseAbsolutePointerDev->Mode.AbsoluteMaxY = 798; - MouseAbsolutePointerDev->Mode.AbsoluteMinY = 0; - MouseAbsolutePointerDev->Mode.AbsoluteMaxZ = 0; - MouseAbsolutePointerDev->Mode.AbsoluteMinZ = 0; - MouseAbsolutePointerDev->Mode.Attributes = 0x03; - - MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset = MouseAbsolutePointerReset; - MouseAbsolutePointerDev->AbsolutePointerProtocol.GetState = MouseAbsolutePointerGetState; - MouseAbsolutePointerDev->AbsolutePointerProtocol.Mode = &(MouseAbsolutePointerDev->Mode); - - // - // Initialize keyboard controller if necessary - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST, - ParentDevicePath - ); - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - if ((Data & KBC_SYSF) != KBC_SYSF) { - Status = KbcSelfTest (IsaIo); - if (EFI_ERROR (Status)) { - StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR; - goto ErrorExit; - } - } - - KbcEnableAux (IsaIo); - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT, - ParentDevicePath - ); - - // - // Reset the mouse - // - Status = MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset ( - &MouseAbsolutePointerDev->AbsolutePointerProtocol, - FeaturePcdGet (PcdPs2MouseExtendedVerification) - ); - if (EFI_ERROR (Status)) { - // - // mouse not connected - // - Status = EFI_SUCCESS; - StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; - goto ErrorExit; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED, - ParentDevicePath - ); - - // - // Setup the WaitForKey event - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_WAIT, - TPL_NOTIFY, - MouseAbsolutePointerWaitForInput, - MouseAbsolutePointerDev, - &((MouseAbsolutePointerDev->AbsolutePointerProtocol).WaitForInput) - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - // - // Setup a periodic timer, used to poll mouse state - // - Status = gBS->CreateEvent ( - EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - PollMouseAbsolutePointer, - MouseAbsolutePointerDev, - &MouseAbsolutePointerDev->TimerEvent - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - // - // Start timer to poll mouse (100 samples per second) - // - Status = gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerPeriodic, 100000); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - MouseAbsolutePointerDev->ControllerNameTable = NULL; - AddUnicodeString2 ( - "eng", - gPs2MouseAbsolutePointerComponentName.SupportedLanguages, - &MouseAbsolutePointerDev->ControllerNameTable, - L"Faked PS/2 Touchpad Device", - TRUE - ); - AddUnicodeString2 ( - "en", - gPs2MouseAbsolutePointerComponentName2.SupportedLanguages, - &MouseAbsolutePointerDev->ControllerNameTable, - L"Faked PS/2 Touchpad Device", - FALSE - ); - - - // - // Install protocol interfaces for the mouse device. - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiAbsolutePointerProtocolGuid, - &MouseAbsolutePointerDev->AbsolutePointerProtocol, - NULL - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - gBS->RestoreTPL (OldTpl); - - return Status; - -ErrorExit: - - KbcDisableAux (IsaIo); - - if (StatusCode != 0) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - StatusCode, - ParentDevicePath - ); - } - - if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput != NULL)) { - gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput); - } - - if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->TimerEvent != NULL)) { - gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent); - } - - if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->ControllerNameTable != NULL)) { - FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable); - } - // - // Since there will be no timer handler for mouse input any more, - // exhaust input data just in case there is still mouse data left - // - EmptyStatus = EFI_SUCCESS; - while (!EFI_ERROR (EmptyStatus)) { - EmptyStatus = In8042Data (IsaIo, &Data); - } - - if (MouseAbsolutePointerDev != NULL) { - FreePool (MouseAbsolutePointerDev); - } - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Stop this driver on ControllerHandle. Support stoping any child handles - created by this driver. - - @param This 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 -PS2MouseAbsolutePointerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol; - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; - UINT8 Data; - - Status = gBS->OpenProtocol ( - Controller, - &gEfiAbsolutePointerProtocolGuid, - (VOID **) &AbsolutePointerProtocol, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return EFI_SUCCESS; - } - - MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (AbsolutePointerProtocol); - - // - // Report that the keyboard is being disabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE, - MouseAbsolutePointerDev->DevicePath - ); - - Status = gBS->UninstallProtocolInterface ( - Controller, - &gEfiAbsolutePointerProtocolGuid, - &MouseAbsolutePointerDev->AbsolutePointerProtocol - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Cancel mouse data polling timer, close timer event - // - gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerCancel, 0); - gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent); - - // - // Since there will be no timer handler for mouse input any more, - // exhaust input data just in case there is still mouse data left - // - Status = EFI_SUCCESS; - while (!EFI_ERROR (Status)) { - Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data); - } - - gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput); - FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable); - FreePool (MouseAbsolutePointerDev); - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return EFI_SUCCESS; -} - -/** - Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system. - - @param This - Pointer of simple pointer Protocol. - @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. - - - @retval EFI_SUCCESS - The command byte is written successfully. - @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. - -**/ -EFI_STATUS -EFIAPI -MouseAbsolutePointerReset ( - IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - EFI_STATUS Status; - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; - EFI_TPL OldTpl; - BOOLEAN KeyboardEnable; - UINT8 Data; - - MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This); - - // - // Report reset progress code - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET, - MouseAbsolutePointerDev->DevicePath - ); - - KeyboardEnable = FALSE; - - // - // Raise TPL to avoid keyboard operation impact - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - ZeroMem (&MouseAbsolutePointerDev->State, sizeof (EFI_ABSOLUTE_POINTER_STATE)); - MouseAbsolutePointerDev->StateChanged = FALSE; - - // - // Exhaust input data - // - Status = EFI_SUCCESS; - while (!EFI_ERROR (Status)) { - Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data); - } - - CheckKbStatus (MouseAbsolutePointerDev->IsaIo, &KeyboardEnable); - - KbcDisableKb (MouseAbsolutePointerDev->IsaIo); - - MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - // - // if there's data block on KBC data port, read it out - // - if ((Data & KBC_OUTB) == KBC_OUTB) { - MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data); - } - - Status = EFI_SUCCESS; - // - // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system. - // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is - // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling - // - if (ExtendedVerification && CheckMouseAbsolutePointerConnect (MouseAbsolutePointerDev)) { - // - // Send mouse reset command and set mouse default configure - // - Status = PS2MouseReset (MouseAbsolutePointerDev->IsaIo); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = PS2MouseSetSampleRate (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->SampleRate); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = PS2MouseSetResolution (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Resolution); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = PS2MouseSetScaling (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Scaling); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - } -Exit: - gBS->RestoreTPL (OldTpl); - - if (KeyboardEnable) { - KbcEnableKb (MouseAbsolutePointerDev->IsaIo); - } - - return Status; -} - -/** - Check whether there is Ps/2 mouse device in system - - @param MouseAbsolutePointerDev - Absolute Pointer Device Private Data Structure - - @retval TRUE - Keyboard in System. - @retval FALSE - Keyboard not in System. - -**/ -BOOLEAN -CheckMouseAbsolutePointerConnect ( - IN PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev - ) - -{ - EFI_STATUS Status; - - Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo); - if (!EFI_ERROR (Status)) { - return TRUE; - } - - return FALSE; -} - -/** - Get and Clear mouse status. - - @param This - Pointer of simple pointer Protocol. - @param State - Output buffer holding status. - - @retval EFI_INVALID_PARAMETER Output buffer is invalid. - @retval EFI_NOT_READY Mouse is not changed status yet. - @retval EFI_SUCCESS Mouse status is changed and get successful. -**/ -EFI_STATUS -EFIAPI -MouseAbsolutePointerGetState ( - IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, - IN OUT EFI_ABSOLUTE_POINTER_STATE *State - ) -{ - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; - EFI_TPL OldTpl; - - MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This); - - if (State == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (!MouseAbsolutePointerDev->StateChanged) { - return EFI_NOT_READY; - } - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - CopyMem (State, &(MouseAbsolutePointerDev->State), sizeof (EFI_ABSOLUTE_POINTER_STATE)); - - // - // clear mouse state - // - MouseAbsolutePointerDev->State.CurrentX = 0; - MouseAbsolutePointerDev->State.CurrentY = 0; - MouseAbsolutePointerDev->State.CurrentZ = 0; - MouseAbsolutePointerDev->State.ActiveButtons = 0x0; - MouseAbsolutePointerDev->StateChanged = FALSE; - gBS->RestoreTPL (OldTpl); - - return EFI_SUCCESS; -} - -/** - - Event notification function for SIMPLE_POINTER.WaitForInput event. - Signal the event if there is input from mouse. - - @param Event event object - @param Context event context - -**/ -VOID -EFIAPI -MouseAbsolutePointerWaitForInput ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; - - MouseAbsolutePointerDev = (PS2_MOUSE_ABSOLUTE_POINTER_DEV *) Context; - - // - // Someone is waiting on the mouse event, if there's - // input from mouse, signal the event - // - if (MouseAbsolutePointerDev->StateChanged) { - gBS->SignalEvent (Event); - } - -} - -/** - Event notification function for TimerEvent event. - If mouse device is connected to system, try to get the mouse packet data. - - @param Event - TimerEvent in PS2_MOUSE_DEV - @param Context - Pointer to PS2_MOUSE_DEV structure - -**/ -VOID -EFIAPI -PollMouseAbsolutePointer( - IN EFI_EVENT Event, - IN VOID *Context - ) - -{ - PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; - - MouseAbsolutePointerDev = (PS2_MOUSE_ABSOLUTE_POINTER_DEV *) Context; - - // - // Polling mouse packet data - // - PS2MouseGetPacket (MouseAbsolutePointerDev); -} - -/** - The user Entry Point for module Ps2MouseAbsolutePointer. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -InitializePs2MouseAbsolutePointer( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gPS2MouseAbsolutePointerDriver, - ImageHandle, - &gPs2MouseAbsolutePointerComponentName, - &gPs2MouseAbsolutePointerComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.h b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.h deleted file mode 100644 index a4e2174a4c..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointer.h +++ /dev/null @@ -1,400 +0,0 @@ -/** @file - A Ps2MouseAbsolutePointer driver header file - -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 __PS2MOUSEABSOLUTEPOINTER_H__ -#define __PS2MOUSEABSOLUTEPOINTER_H__ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gPS2MouseAbsolutePointerDriver; -extern EFI_COMPONENT_NAME_PROTOCOL gPs2MouseAbsolutePointerComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gPs2MouseAbsolutePointerComponentName2; - -// -// PS/2 mouse sample rate -// -typedef enum { - SampleRate10, - SampleRate20, - SampleRate40, - SampleRate60, - SampleRate80, - SampleRate100, - SampleRate200, - MaxSampleRate -} MOUSE_SR; - -// -// PS/2 mouse resolution -// -typedef enum { - MouseResolution1, - MouseResolution2, - MouseResolution4, - MouseResolution8, - MaxResolution -} MOUSE_RE; - -// -// PS/2 mouse scaling -// -typedef enum { - Scaling1, - Scaling2 -} MOUSE_SF; - -// -// Driver Private Data -// -#define PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE SIGNATURE_32 ('p', '2', 's', 't') - -typedef struct { - UINTN Signature; - - EFI_HANDLE Handle; - EFI_ABSOLUTE_POINTER_PROTOCOL AbsolutePointerProtocol; - EFI_ABSOLUTE_POINTER_STATE State; - EFI_ABSOLUTE_POINTER_MODE Mode; - BOOLEAN StateChanged; - - // - // PS2 Mouse device specific information - // - MOUSE_SR SampleRate; - MOUSE_RE Resolution; - MOUSE_SF Scaling; - UINT8 DataPackageSize; - - EFI_ISA_IO_PROTOCOL *IsaIo; - - EFI_EVENT TimerEvent; - - EFI_UNICODE_STRING_TABLE *ControllerNameTable; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} PS2_MOUSE_ABSOLUTE_POINTER_DEV; - -#define PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS(a) CR (a, PS2_MOUSE_ABSOLUTE_POINTER_DEV, AbsolutePointerProtocol, PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE) - -// -// Function prototypes -// -/** - Test to see if this driver supports ControllerHandle. Any ControllerHandle - than contains a IsaIo protocol can be supported. - - @param This 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 EFI_ALREADY_STARTED This driver is already running on this device - @retval other This driver does not support this device - -**/ -EFI_STATUS -EFIAPI -PS2MouseAbsolutePointerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Start this driver on ControllerHandle by opening a IsaIo - protocol, creating PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid - finnally. - - @param This 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 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 -PS2MouseAbsolutePointerDriverStart ( - 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 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 -PS2MouseAbsolutePointerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// EFI Component Name Functions -// -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -Ps2MouseAbsolutePointerComponentNameGetDriverName ( - 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 -Ps2MouseAbsolutePointerComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -/** - Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system. - - @param This - Pointer of simple pointer Protocol. - @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. - - - @retval EFI_SUCCESS - The command byte is written successfully. - @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. - -**/ -EFI_STATUS -EFIAPI -MouseAbsolutePointerReset ( - IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Get and Clear mouse status. - - @param This - Pointer of simple pointer Protocol. - @param State - Output buffer holding status. - - @retval EFI_INVALID_PARAMETER Output buffer is invalid. - @retval EFI_NOT_READY Mouse is not changed status yet. - @retval EFI_SUCCESS Mouse status is changed and get successful. -**/ -EFI_STATUS -EFIAPI -MouseAbsolutePointerGetState ( - IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, - IN OUT EFI_ABSOLUTE_POINTER_STATE *State - ); - -/** - - Event notification function for SIMPLE_POINTER.WaitForInput event. - Signal the event if there is input from mouse. - - @param Event event object - @param Context event context - -**/ -VOID -EFIAPI -MouseAbsolutePointerWaitForInput ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - Event notification function for TimerEvent event. - If mouse device is connected to system, try to get the mouse packet data. - - @param Event - TimerEvent in PS2_MOUSE_DEV - @param Context - Pointer to PS2_MOUSE_DEV structure - -**/ -VOID -EFIAPI -PollMouseAbsolutePointer ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - I/O work flow of in 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ); - -/** - Check whether there is Ps/2 mouse device in system - - @param MouseAbsolutePointerDev - Absolute Pointer Device Private Data Structure - - @retval TRUE - Keyboard in System. - @retval FALSE - Keyboard not in System. - -**/ -BOOLEAN -CheckMouseAbsolutePointerConnect ( - IN PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev - ); - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf deleted file mode 100644 index be16671a2f..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf +++ /dev/null @@ -1,77 +0,0 @@ -## @file -# PS2 Mouse driver providing absolute (touch pad) pointer support. -# -# This driver simulates a touch pad absolute pointing device using a standard -# PS2 mouse as the input hardware. -# -# 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 -# 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 = Ps2MouseAbsolutePointerDxe - MODULE_UNI_FILE = Ps2MouseAbsolutePointerDxe.uni - FILE_GUID = 2899C94A-1FB6-4b1a-B96B-8364975303E0 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializePs2MouseAbsolutePointer - -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# DRIVER_BINDING = gPS2MouseAbsolutePointerDriver; -# COMPONENT_NAME = gPs2MouseAbsolutePointerComponentName; -# COMPONENT_NAME2 = gPs2MouseAbsolutePointerComponentName2; -# - -[Sources] - ComponentName.c - CommPs2.h - CommPs2.c - Ps2MouseAbsolutePointer.h - Ps2MouseAbsolutePointer.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - ReportStatusCodeLib - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - UefiLib - UefiDriverEntryPoint - DebugLib - PcdLib - -[Protocols] - gEfiIsaIoProtocolGuid ## TO_START - gEfiAbsolutePointerProtocolGuid ## BY_START - gEfiDevicePathProtocolGuid ## TO_START - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification ## CONSUMES - -# -# [Event] -# -# ## -# # Timer event used to check the mouse state at a regular interval. -# # -# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES -# - -[UserExtensions.TianoCore."ExtraFiles"] - Ps2MouseAbsolutePointerDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.uni b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.uni deleted file mode 100644 index 22f885d660..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxeExtra.uni b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxeExtra.uni deleted file mode 100644 index d5d7de237b..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c deleted file mode 100644 index 1c763e97f3..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c +++ /dev/null @@ -1,921 +0,0 @@ -/** @file - PS2 Mouse Communication Interface. - -Copyright (c) 2006 - 2009, Intel 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 "Ps2Mouse.h" -#include "CommPs2.h" - -UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 }; - -UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 }; - -/** - Issue self test command via IsaIo interface. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return EFI_SUCCESS Success to do keyboard self testing. - @return others Fail to do keyboard self testing. -**/ -EFI_STATUS -KbcSelfTest ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Keyboard controller self test - // - Status = Out8042Command (IsaIo, SELF_TEST); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Read return code - // - Status = In8042Data (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - - if (Data != 0x55) { - return EFI_DEVICE_ERROR; - } - // - // Set system flag - // - Status = Out8042Command (IsaIo, READ_CMD_BYTE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = In8042Data (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = Out8042Command (IsaIo, WRITE_CMD_BYTE); - if (EFI_ERROR (Status)) { - return Status; - } - - Data |= CMD_SYS_FLAG; - Status = Out8042Data (IsaIo, Data); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - Issue command to enable keyboard AUX functionality. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcEnableAux ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send 8042 enable mouse command - // - return Out8042Command (IsaIo, ENABLE_AUX); -} - -/** - Issue command to disable keyboard AUX functionality. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcDisableAux ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send 8042 disable mouse command - // - return Out8042Command (IsaIo, DISABLE_AUX); -} - -/** - Issue command to enable keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcEnableKb ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send 8042 enable keyboard command - // - return Out8042Command (IsaIo, ENABLE_KB); -} - -/** - Issue command to disable keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcDisableKb ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send 8042 disable keyboard command - // - return Out8042Command (IsaIo, DISABLE_KB); -} - -/** - Issue command to check keyboard status. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param KeyboardEnable return whether keyboard is enable. - - @return Status of command issuing. -**/ -EFI_STATUS -CheckKbStatus ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - OUT BOOLEAN *KeyboardEnable - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Send command to read KBC command byte - // - Status = Out8042Command (IsaIo, READ_CMD_BYTE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = In8042Data (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check keyboard enable or not - // - if ((Data & CMD_KB_STS) == CMD_KB_DIS) { - *KeyboardEnable = FALSE; - } else { - *KeyboardEnable = TRUE; - } - - return EFI_SUCCESS; -} - -/** - Issue command to reset keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseReset ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - EFI_STATUS Status; - UINT8 Data; - - Status = Out8042AuxCommand (IsaIo, RESET_CMD, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = In8042AuxData (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check BAT Complete Code - // - if (Data != PS2MOUSE_BAT1) { - return EFI_DEVICE_ERROR; - } - - Status = In8042AuxData (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check BAT Complete Code - // - if (Data != PS2MOUSE_BAT2) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Issue command to set mouse's sample rate - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param SampleRate value of sample rate - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetSampleRate ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_SR SampleRate - ) -{ - EFI_STATUS Status; - - // - // Send auxiliary command to set mouse sample rate - // - Status = Out8042AuxCommand (IsaIo, SETSR_CMD, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = Out8042AuxData (IsaIo, SampleRateTbl[SampleRate]); - - return Status; -} - -/** - Issue command to set mouse's resolution. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Resolution value of resolution - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetResolution ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_RE Resolution - ) -{ - EFI_STATUS Status; - - // - // Send auxiliary command to set mouse resolution - // - Status = Out8042AuxCommand (IsaIo, SETRE_CMD, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = Out8042AuxData (IsaIo, ResolutionTbl[Resolution]); - - return Status; -} - -/** - Issue command to set mouse's scaling. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Scaling value of scaling - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetScaling ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_SF Scaling - ) -{ - UINT8 Command; - - Command = (UINT8) (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD); - - // - // Send auxiliary command to set mouse scaling data - // - return Out8042AuxCommand (IsaIo, Command, FALSE); -} - -/** - Issue command to enable Ps2 mouse. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseEnable ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - // - // Send auxiliary command to enable mouse - // - return Out8042AuxCommand (IsaIo, ENABLE_CMD, FALSE); -} - -/** - Get mouse packet . Only care first 3 bytes - - @param MouseDev Pointer of PS2 Mouse Private Data Structure - - @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet - @retval EFI_SUCCESS The data packet is gotten successfully. - -**/ -EFI_STATUS -PS2MouseGetPacket ( - PS2_MOUSE_DEV *MouseDev - ) - -{ - EFI_STATUS Status; - BOOLEAN KeyboardEnable; - UINT8 Packet[PS2_PACKET_LENGTH]; - UINT8 Data; - UINTN Count; - UINTN State; - INT16 RelativeMovementX; - INT16 RelativeMovementY; - BOOLEAN LButton; - BOOLEAN RButton; - - KeyboardEnable = FALSE; - Count = 1; - State = PS2_READ_BYTE_ONE; - - // - // State machine to get mouse packet - // - while (1) { - - switch (State) { - case PS2_READ_BYTE_ONE: - // - // Read mouse first byte data, if failed, immediately return - // - KbcDisableAux (MouseDev->IsaIo); - Status = PS2MouseRead (MouseDev->IsaIo, &Data, &Count, State); - if (EFI_ERROR (Status)) { - KbcEnableAux (MouseDev->IsaIo); - return EFI_NOT_READY; - } - - if (Count != 1) { - KbcEnableAux (MouseDev->IsaIo); - return EFI_NOT_READY; - } - - if (IS_PS2_SYNC_BYTE (Data)) { - Packet[0] = Data; - State = PS2_READ_DATA_BYTE; - - CheckKbStatus (MouseDev->IsaIo, &KeyboardEnable); - KbcDisableKb (MouseDev->IsaIo); - KbcEnableAux (MouseDev->IsaIo); - } - break; - - case PS2_READ_DATA_BYTE: - Count = 2; - Status = PS2MouseRead (MouseDev->IsaIo, (Packet + 1), &Count, State); - if (EFI_ERROR (Status)) { - if (KeyboardEnable) { - KbcEnableKb (MouseDev->IsaIo); - } - - return EFI_NOT_READY; - } - - if (Count != 2) { - if (KeyboardEnable) { - KbcEnableKb (MouseDev->IsaIo); - } - - return EFI_NOT_READY; - } - - State = PS2_PROCESS_PACKET; - break; - - case PS2_PROCESS_PACKET: - if (KeyboardEnable) { - KbcEnableKb (MouseDev->IsaIo); - } - // - // Decode the packet - // - RelativeMovementX = Packet[1]; - RelativeMovementY = Packet[2]; - // - // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 - // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn - // Byte 1 | 8 bit X Movement - // Byte 2 | 8 bit Y Movement - // - // X sign bit + 8 bit X Movement : 9-bit signed twos complement integer that presents the relative displacement of the device in the X direction since the last data transmission. - // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement. - // - // - // First, Clear X and Y high 8 bits - // - RelativeMovementX = (INT16) (RelativeMovementX & 0xFF); - RelativeMovementY = (INT16) (RelativeMovementY & 0xFF); - // - // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff - // - if ((Packet[0] & 0x10) != 0) { - RelativeMovementX = (INT16) (RelativeMovementX | 0xFF00); - } - if ((Packet[0] & 0x20) != 0) { - RelativeMovementY = (INT16) (RelativeMovementY | 0xFF00); - } - - - RButton = (UINT8) (Packet[0] & 0x2); - LButton = (UINT8) (Packet[0] & 0x1); - - // - // Update mouse state - // - MouseDev->State.RelativeMovementX += RelativeMovementX; - MouseDev->State.RelativeMovementY -= RelativeMovementY; - MouseDev->State.RightButton = (UINT8) (RButton ? TRUE : FALSE); - MouseDev->State.LeftButton = (UINT8) (LButton ? TRUE : FALSE); - MouseDev->StateChanged = TRUE; - - return EFI_SUCCESS; - } - } -} - -/** - Read data via IsaIo protocol with given number. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Buffer Buffer receive data of mouse - @param BufSize The size of buffer - @param State Check input or read data - - @return status of reading mouse data. -**/ -EFI_STATUS -PS2MouseRead ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - OUT VOID *Buffer, - IN OUT UINTN *BufSize, - IN UINTN State - ) -{ - EFI_STATUS Status; - UINTN BytesRead; - - Status = EFI_SUCCESS; - BytesRead = 0; - - if (State == PS2_READ_BYTE_ONE) { - // - // Check input for mouse - // - Status = CheckForInput (IsaIo); - - if (EFI_ERROR (Status)) { - return Status; - } - } - - while (BytesRead < *BufSize) { - - Status = WaitOutputFull (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - break; - } - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Buffer); - - BytesRead++; - Buffer = (UINT8 *) Buffer + 1; - } - // - // Verify the correct number of bytes read - // - if (BytesRead == 0 || BytesRead != *BufSize) { - Status = EFI_NOT_FOUND; - } - - *BufSize = BytesRead; - return Status; -} -// -// 8042 I/O function -// -/** - I/O work flow of outing 8042 command. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Command I/O command. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042Command ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Command - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Wait keyboard controller input buffer empty - // - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Send command - // - Data = Command; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow of outing 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Data - ) -{ - EFI_STATUS Status; - UINT8 Temp; - // - // Wait keyboard controller input buffer empty - // - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - Temp = Data; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow of in 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ) -{ - UINTN Delay; - UINT8 Temp; - - Delay = TIMEOUT / 50; - - do { - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp); - - // - // Check keyboard controller status bit 0(output buffer status) - // - if ((Temp & KBC_OUTB) == KBC_OUTB) { - break; - } - - gBS->Stall (50); - Delay--; - } while (Delay != 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data); - - return EFI_SUCCESS; -} - -/** - I/O work flow of outing 8042 Aux command. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Command Aux I/O command - @param Resend Whether need resend the Aux command. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042AuxCommand ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Command, - IN BOOLEAN Resend - ) -{ - EFI_STATUS Status; - UINT8 Data; - - // - // Wait keyboard controller input buffer empty - // - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Send write to auxiliary device command - // - Data = WRITE_AUX_DEV; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Send auxiliary device command - // - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command); - - // - // Read return code - // - Status = In8042AuxData (IsaIo, &Data); - if (EFI_ERROR (Status)) { - return Status; - } - - if (Data == PS2_ACK) { - // - // Receive mouse acknowledge, command send success - // - return EFI_SUCCESS; - - } else if (Resend) { - // - // Resend fail - // - return EFI_DEVICE_ERROR; - - } else if (Data == PS2_RESEND) { - // - // Resend command - // - Status = Out8042AuxCommand (IsaIo, Command, TRUE); - if (EFI_ERROR (Status)) { - return Status; - } - - } else { - // - // Invalid return code - // - return EFI_DEVICE_ERROR; - - } - - return EFI_SUCCESS; -} - -/** - I/O work flow of outing 8042 Aux data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Buffer holding return value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042AuxData ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Data - ) -{ - EFI_STATUS Status; - UINT8 Temp; - // - // Wait keyboard controller input buffer empty - // - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Send write to auxiliary device command - // - Temp = WRITE_AUX_DEV; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - Temp = Data; - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp); - - Status = WaitInputEmpty (IsaIo, TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow of in 8042 Aux data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Buffer holding return value. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042AuxData ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ) -{ - EFI_STATUS Status; - - // - // wait for output data - // - Status = WaitOutputFull (IsaIo, BAT_TIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data); - - return EFI_SUCCESS; -} - - -/** - Check keyboard controller status, if it is output buffer full and for auxiliary device. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @retval EFI_SUCCESS Keyboard controller is ready - @retval EFI_NOT_READY Keyboard controller is not ready -**/ -EFI_STATUS -CheckForInput ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ) -{ - UINT8 Data; - - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - // - // Check keyboard controller status, if it is output buffer full and for auxiliary device - // - if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) { - return EFI_NOT_READY; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow to wait input buffer empty in given time. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Timeout Wating time. - - @retval EFI_TIMEOUT if input is still not empty in given time. - @retval EFI_SUCCESS input is empty. -**/ -EFI_STATUS -WaitInputEmpty ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINTN Timeout - ) -{ - UINTN Delay; - UINT8 Data; - - Delay = Timeout / 50; - - do { - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - // - // Check keyboard controller status bit 1(input buffer status) - // - if ((Data & KBC_INPB) == 0) { - break; - } - - gBS->Stall (50); - Delay--; - } while (Delay != 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - I/O work flow to wait output buffer full in given time. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Timeout given time - - @retval EFI_TIMEOUT output is not full in given time - @retval EFI_SUCCESS output is full in given time. -**/ -EFI_STATUS -WaitOutputFull ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINTN Timeout - ) -{ - UINTN Delay; - UINT8 Data; - - Delay = Timeout / 50; - - do { - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - // - // Check keyboard controller status bit 0(output buffer status) - // & bit5(output buffer for auxiliary device) - // - if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) { - break; - } - - gBS->Stall (50); - Delay--; - } while (Delay != 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.h b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.h deleted file mode 100644 index a48ee8cb09..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.h +++ /dev/null @@ -1,435 +0,0 @@ -/** @file - PS2 Mouse Communication Interface - -Copyright (c) 2006 - 2007, Intel 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 _COMMPS2_H_ -#define _COMMPS2_H_ - -#define PS2_PACKET_LENGTH 3 -#define PS2_SYNC_MASK 0xc -#define PS2_SYNC_BYTE 0x8 - -#define IS_PS2_SYNC_BYTE(byte) ((byte & PS2_SYNC_MASK) == PS2_SYNC_BYTE) - -#define PS2_READ_BYTE_ONE 0 -#define PS2_READ_DATA_BYTE 1 -#define PS2_PROCESS_PACKET 2 - -#define TIMEOUT 50000 -#define BAT_TIMEOUT 500000 - -// -// 8042 I/O Port -// -#define KBC_DATA_PORT 0x60 -#define KBC_CMD_STS_PORT 0x64 - -// -// 8042 Command -// -#define READ_CMD_BYTE 0x20 -#define WRITE_CMD_BYTE 0x60 -#define DISABLE_AUX 0xa7 -#define ENABLE_AUX 0xa8 -#define SELF_TEST 0xaa -#define DISABLE_KB 0xad -#define ENABLE_KB 0xae -#define WRITE_AUX_DEV 0xd4 - -#define CMD_SYS_FLAG 0x04 -#define CMD_KB_STS 0x10 -#define CMD_KB_DIS 0x10 -#define CMD_KB_EN 0x0 - -// -// 8042 Auxiliary Device Command -// -#define SETSF1_CMD 0xe6 -#define SETSF2_CMD 0xe7 -#define SETRE_CMD 0xe8 -#define READ_CMD 0xeb -#define SETRM_CMD 0xf0 -#define SETSR_CMD 0xf3 -#define ENABLE_CMD 0xf4 -#define DISABLE_CMD 0xf5 -#define RESET_CMD 0xff - -// -// return code -// -#define PS2_ACK 0xfa -#define PS2_RESEND 0xfe -#define PS2MOUSE_BAT1 0xaa -#define PS2MOUSE_BAT2 0x0 - -// -// Keyboard Controller Status -// -/// -/// Parity Error -/// -#define KBC_PARE 0x80 -/// -/// General Time Out -/// -#define KBC_TIM 0x40 -/// -/// Output buffer for auxiliary device (PS/2): -/// 0 - Holds keyboard data -/// 1 - Holds data for auxiliary device -/// -#define KBC_AUXB 0x20 -/// -/// Keyboard lock status: -/// 0 - keyboard locked -/// 1 - keyboard free -/// -#define KBC_KEYL 0x10 -/// -/// Command/Data: -/// 0 - data byte written via port 60h -/// 1 - command byte written via port 64h -/// -#define KBC_CD 0x08 -/// -/// System Flag: -/// 0 - power-on reset -/// 1 - self-test successful -/// -#define KBC_SYSF 0x04 -/// -/// Input Buffer Status : -/// 0 - input buffer empty -/// 1 - CPU data in input buffer -/// -#define KBC_INPB 0x02 -/// -/// Output Buffer Status : -/// 0 - output buffer empty -/// 1 - keyboard controller data in output buffer -/// -#define KBC_OUTB 0x01 - -/** - Issue self test command via IsaIo interface. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return EFI_SUCCESS Success to do keyboard self testing. - @return others Fail to do keyboard self testing. -**/ -EFI_STATUS -KbcSelfTest ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to enable keyboard AUX functionality. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcEnableAux ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to disable keyboard AUX functionality. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcDisableAux ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to enable keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcEnableKb ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to disable keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -KbcDisableKb ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to check keyboard status. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param KeyboardEnable return whether keyboard is enable. - - @return Status of command issuing. -**/ -EFI_STATUS -CheckKbStatus ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - OUT BOOLEAN *KeyboardEnable - ); - -/** - Issue command to reset keyboard. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseReset ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Issue command to set mouse's sample rate - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param SampleRate value of sample rate - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetSampleRate ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_SR SampleRate - ); - -/** - Issue command to set mouse's resolution. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Resolution value of resolution - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetResolution ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_RE Resolution - ); - -/** - Issue command to set mouse's scaling. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Scaling value of scaling - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseSetScaling ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN MOUSE_SF Scaling - ); - -/** - Issue command to enable Ps2 mouse. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @return Status of command issuing. -**/ -EFI_STATUS -PS2MouseEnable ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - Get mouse packet . Only care first 3 bytes - - @param MouseDev Pointer of PS2 Mouse Private Data Structure - - @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet - @retval EFI_SUCCESS The data packet is gotten successfully. - -**/ -EFI_STATUS -PS2MouseGetPacket ( - PS2_MOUSE_DEV *MouseDev - ); - -/** - Read data via IsaIo protocol with given number. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Buffer Buffer receive data of mouse - @param BufSize The size of buffer - @param State Check input or read data - - @return status of reading mouse data. -**/ -EFI_STATUS -PS2MouseRead ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - OUT VOID *Buffer, - IN OUT UINTN *BufSize, - IN UINTN State - ); - -// -// 8042 I/O function -// -/** - I/O work flow of outing 8042 command. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Command I/O command. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042Command ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Command - ); - -/** - I/O work flow of in 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ); - -/** - I/O work flow of outing 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Data - ); - -/** - I/O work flow of outing 8042 Aux command. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Command Aux I/O command - @param Resend Whether need resend the Aux command. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042AuxCommand ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Command, - IN BOOLEAN Resend - ); - -/** - I/O work flow of in 8042 Aux data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Buffer holding return value. - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042AuxData ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ); - -/** - I/O work flow of outing 8042 Aux data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Buffer holding return value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -Out8042AuxData ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINT8 Data - ); - -/** - Check keyboard controller status, if it is output buffer full and for auxiliary device. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - - @retval EFI_SUCCESS Keyboard controller is ready - @retval EFI_NOT_READY Keyboard controller is not ready -**/ -EFI_STATUS -CheckForInput ( - IN EFI_ISA_IO_PROTOCOL *IsaIo - ); - -/** - I/O work flow to wait input buffer empty in given time. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Timeout Wating time. - - @retval EFI_TIMEOUT if input is still not empty in given time. - @retval EFI_SUCCESS input is empty. -**/ -EFI_STATUS -WaitInputEmpty ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINTN Timeout - ); - -/** - I/O work flow to wait output buffer full in given time. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Timeout given time - - @retval EFI_TIMEOUT output is not full in given time - @retval EFI_SUCCESS output is full in given time. -**/ -EFI_STATUS -WaitOutputFull ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN UINTN Timeout - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/ComponentName.c deleted file mode 100644 index 1c3e84ec6d..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/ComponentName.c +++ /dev/null @@ -1,241 +0,0 @@ -/** @file - UEFI Component Name(2) protocol implementation for Ps2MouseDxe 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 "Ps2Mouse.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPs2MouseComponentName = { - Ps2MouseComponentNameGetDriverName, - Ps2MouseComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPs2MouseComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ps2MouseComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Ps2MouseComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPs2MouseDriverNameTable[] = { - { - "eng;en", - L"PS/2 Mouse Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -Ps2MouseComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mPs2MouseDriverNameTable, - DriverName, - (BOOLEAN)(This == &gPs2MouseComponentName) - ); -} - -/** - 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 -Ps2MouseComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol; - PS2_MOUSE_DEV *MouseDev; - EFI_ISA_IO_PROTOCOL *IsaIoProtocol; - - // - // This is a device driver, so ChildHandle must be NULL. - // - if (ChildHandle != NULL) { - return EFI_UNSUPPORTED; - } - // - // Check Controller's handle - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIoProtocol, - gPS2MouseDriver.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (!EFI_ERROR (Status)) { - gBS->CloseProtocol ( - ControllerHandle, - &gEfiIsaIoProtocolGuid, - gPS2MouseDriver.DriverBindingHandle, - ControllerHandle - ); - - return EFI_UNSUPPORTED; - } - - if (Status != EFI_ALREADY_STARTED) { - return EFI_UNSUPPORTED; - } - // - // Get the device context - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiSimplePointerProtocolGuid, - (VOID **) &SimplePointerProtocol, - gPS2MouseDriver.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - MouseDev = PS2_MOUSE_DEV_FROM_THIS (SimplePointerProtocol); - - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - MouseDev->ControllerNameTable, - ControllerName, - (BOOLEAN)(This == &gPs2MouseComponentName) - ); -} diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c deleted file mode 100644 index 1623201876..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c +++ /dev/null @@ -1,792 +0,0 @@ -/** @file - PS/2 Mouse driver. Routines that interacts with callers, - conforming to EFI driver model. - -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 "Ps2Mouse.h" -#include "CommPs2.h" - -/// -/// DriverBinding Protocol Instance -/// -EFI_DRIVER_BINDING_PROTOCOL gPS2MouseDriver = { - PS2MouseDriverSupported, - PS2MouseDriverStart, - PS2MouseDriverStop, - 0xa, - NULL, - NULL -}; - -/** - Test to see if this driver supports ControllerHandle. Any ControllerHandle - than contains a IsaIo protocol can be supported. - - @param This 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 EFI_ALREADY_STARTED This driver is already running on this device - @retval other This driver does not support this device - -**/ -EFI_STATUS -EFIAPI -PS2MouseDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_ISA_IO_PROTOCOL *IsaIo; - - Status = EFI_SUCCESS; - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Use the ISA I/O Protocol to see if Controller is the Keyboard controller - // - switch (IsaIo->ResourceList->Device.HID) { - case EISA_PNP_ID (0xF03): - // - // Microsoft PS/2 style mouse - // - case EISA_PNP_ID (0xF13): - // - // PS/2 Port for PS/2-style Mice - // - break; - - case EISA_PNP_ID (0x303): - // - // IBM Enhanced (101/102-key, PS/2 mouse support) - // - if (IsaIo->ResourceList->Device.UID == 1) { - break; - } - - default: - Status = EFI_UNSUPPORTED; - break; - } - // - // Close the I/O Abstraction(s) used to perform the supported test - // - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Start this driver on ControllerHandle by opening a IsaIo protocol, creating - PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid - finally. - - @param This 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 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 -PS2MouseDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_STATUS EmptyStatus; - EFI_ISA_IO_PROTOCOL *IsaIo; - PS2_MOUSE_DEV *MouseDev; - UINT8 Data; - EFI_TPL OldTpl; - EFI_STATUS_CODE_VALUE StatusCode; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - - StatusCode = 0; - MouseDev = NULL; - IsaIo = NULL; - - // - // Open the device path protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Report that the keyboard is being enabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE, - ParentDevicePath - ); - - // - // Get the ISA I/O Protocol on Controller's handle - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - return EFI_INVALID_PARAMETER; - } - // - // Raise TPL to avoid keyboard operation impact - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Allocate private data - // - MouseDev = AllocateZeroPool (sizeof (PS2_MOUSE_DEV)); - if (MouseDev == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - // - // Setup the device instance - // - MouseDev->Signature = PS2_MOUSE_DEV_SIGNATURE; - MouseDev->Handle = Controller; - MouseDev->SampleRate = SampleRate20; - MouseDev->Resolution = MouseResolution4; - MouseDev->Scaling = Scaling1; - MouseDev->DataPackageSize = 3; - MouseDev->IsaIo = IsaIo; - MouseDev->DevicePath = ParentDevicePath; - - // - // Resolution = 4 counts/mm - // - MouseDev->Mode.ResolutionX = 4; - MouseDev->Mode.ResolutionY = 4; - MouseDev->Mode.LeftButton = TRUE; - MouseDev->Mode.RightButton = TRUE; - - MouseDev->SimplePointerProtocol.Reset = MouseReset; - MouseDev->SimplePointerProtocol.GetState = MouseGetState; - MouseDev->SimplePointerProtocol.Mode = &(MouseDev->Mode); - - // - // Initialize keyboard controller if necessary - // - IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - // - // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. - // - if ((Data & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) { - // - // If nobody decodes KBC I/O port, it will read back as 0xFF. - // Check the Time-Out and Parity bit to see if it has an active KBC in system - // - Status = EFI_DEVICE_ERROR; - StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; - goto ErrorExit; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST, - ParentDevicePath - ); - - if ((Data & KBC_SYSF) != KBC_SYSF) { - Status = KbcSelfTest (IsaIo); - if (EFI_ERROR (Status)) { - StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR; - goto ErrorExit; - } - } - - KbcEnableAux (IsaIo); - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT, - ParentDevicePath - ); - - // - // Reset the mouse - // - Status = MouseDev->SimplePointerProtocol.Reset ( - &MouseDev->SimplePointerProtocol, - FeaturePcdGet (PcdPs2MouseExtendedVerification) - ); - if (EFI_ERROR (Status)) { - // - // mouse not connected - // - Status = EFI_SUCCESS; - StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; - goto ErrorExit; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED, - ParentDevicePath - ); - - // - // Setup the WaitForKey event - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_WAIT, - TPL_NOTIFY, - MouseWaitForInput, - MouseDev, - &((MouseDev->SimplePointerProtocol).WaitForInput) - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - // - // Setup a periodic timer, used to poll mouse state - // - Status = gBS->CreateEvent ( - EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - PollMouse, - MouseDev, - &MouseDev->TimerEvent - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - // - // Start timer to poll mouse (100 samples per second) - // - Status = gBS->SetTimer (MouseDev->TimerEvent, TimerPeriodic, 100000); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - MouseDev->ControllerNameTable = NULL; - AddUnicodeString2 ( - "eng", - gPs2MouseComponentName.SupportedLanguages, - &MouseDev->ControllerNameTable, - L"PS/2 Mouse Device", - TRUE - ); - AddUnicodeString2 ( - "en", - gPs2MouseComponentName2.SupportedLanguages, - &MouseDev->ControllerNameTable, - L"PS/2 Mouse Device", - FALSE - ); - - - // - // Install protocol interfaces for the mouse device. - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiSimplePointerProtocolGuid, - &MouseDev->SimplePointerProtocol, - NULL - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - gBS->RestoreTPL (OldTpl); - - return Status; - -ErrorExit: - - if (Status != EFI_DEVICE_ERROR) { - KbcDisableAux (IsaIo); - } - - if (StatusCode != 0) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - StatusCode, - ParentDevicePath - ); - } - - if ((MouseDev != NULL) && (MouseDev->SimplePointerProtocol.WaitForInput != NULL)) { - gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput); - } - - if ((MouseDev != NULL) && (MouseDev->TimerEvent != NULL)) { - gBS->CloseEvent (MouseDev->TimerEvent); - } - - if ((MouseDev != NULL) && (MouseDev->ControllerNameTable != NULL)) { - FreeUnicodeStringTable (MouseDev->ControllerNameTable); - } - - if (Status != EFI_DEVICE_ERROR) { - // - // Since there will be no timer handler for mouse input any more, - // exhaust input data just in case there is still mouse data left - // - EmptyStatus = EFI_SUCCESS; - while (!EFI_ERROR (EmptyStatus)) { - EmptyStatus = In8042Data (IsaIo, &Data); - } - } - - if (MouseDev != NULL) { - FreePool (MouseDev); - } - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Stop this driver on ControllerHandle. Support stoping any child handles - created by this driver. - - @param This 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 -PS2MouseDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol; - PS2_MOUSE_DEV *MouseDev; - UINT8 Data; - - Status = gBS->OpenProtocol ( - Controller, - &gEfiSimplePointerProtocolGuid, - (VOID **) &SimplePointerProtocol, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return EFI_SUCCESS; - } - - MouseDev = PS2_MOUSE_DEV_FROM_THIS (SimplePointerProtocol); - - // - // Report that the keyboard is being disabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE, - MouseDev->DevicePath - ); - - Status = gBS->UninstallProtocolInterface ( - Controller, - &gEfiSimplePointerProtocolGuid, - &MouseDev->SimplePointerProtocol - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Cancel mouse data polling timer, close timer event - // - gBS->SetTimer (MouseDev->TimerEvent, TimerCancel, 0); - gBS->CloseEvent (MouseDev->TimerEvent); - - // - // Since there will be no timer handler for mouse input any more, - // exhaust input data just in case there is still mouse data left - // - Status = EFI_SUCCESS; - while (!EFI_ERROR (Status)) { - Status = In8042Data (MouseDev->IsaIo, &Data); - } - - gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput); - FreeUnicodeStringTable (MouseDev->ControllerNameTable); - FreePool (MouseDev); - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return EFI_SUCCESS; -} - -/** - Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system - - @param This - Pointer of simple pointer Protocol. - @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. - - - @retval EFI_SUCCESS - The command byte is written successfully. - @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. - -**/ -EFI_STATUS -EFIAPI -MouseReset ( - IN EFI_SIMPLE_POINTER_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - EFI_STATUS Status; - PS2_MOUSE_DEV *MouseDev; - EFI_TPL OldTpl; - BOOLEAN KeyboardEnable; - UINT8 Data; - - MouseDev = PS2_MOUSE_DEV_FROM_THIS (This); - - // - // Report reset progress code - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET, - MouseDev->DevicePath - ); - - KeyboardEnable = FALSE; - - // - // Raise TPL to avoid keyboard operation impact - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - ZeroMem (&MouseDev->State, sizeof (EFI_SIMPLE_POINTER_STATE)); - MouseDev->StateChanged = FALSE; - - // - // Exhaust input data - // - Status = EFI_SUCCESS; - while (!EFI_ERROR (Status)) { - Status = In8042Data (MouseDev->IsaIo, &Data); - } - - CheckKbStatus (MouseDev->IsaIo, &KeyboardEnable); - - KbcDisableKb (MouseDev->IsaIo); - - MouseDev->IsaIo->Io.Read (MouseDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); - - // - // if there's data block on KBC data port, read it out - // - if ((Data & KBC_OUTB) == KBC_OUTB) { - MouseDev->IsaIo->Io.Read (MouseDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data); - } - - Status = EFI_SUCCESS; - // - // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system. - // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is - // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling - // - if (ExtendedVerification && CheckMouseConnect (MouseDev)) { - // - // Send mouse reset command and set mouse default configure - // - Status = PS2MouseReset (MouseDev->IsaIo); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = PS2MouseSetSampleRate (MouseDev->IsaIo, MouseDev->SampleRate); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = PS2MouseSetResolution (MouseDev->IsaIo, MouseDev->Resolution); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = PS2MouseSetScaling (MouseDev->IsaIo, MouseDev->Scaling); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = PS2MouseEnable (MouseDev->IsaIo); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - } -Exit: - gBS->RestoreTPL (OldTpl); - - if (KeyboardEnable) { - KbcEnableKb (MouseDev->IsaIo); - } - - return Status; -} - -/** - Check whether there is Ps/2 mouse device in system - - @param MouseDev - Mouse Private Data Structure - - @retval TRUE - Keyboard in System. - @retval FALSE - Keyboard not in System. - -**/ -BOOLEAN -CheckMouseConnect ( - IN PS2_MOUSE_DEV *MouseDev - ) - -{ - EFI_STATUS Status; - - Status = PS2MouseEnable (MouseDev->IsaIo); - if (!EFI_ERROR (Status)) { - return TRUE; - } - - return FALSE; -} - -/** - Get and Clear mouse status. - - @param This - Pointer of simple pointer Protocol. - @param State - Output buffer holding status. - - @retval EFI_INVALID_PARAMETER Output buffer is invalid. - @retval EFI_NOT_READY Mouse is not changed status yet. - @retval EFI_SUCCESS Mouse status is changed and get successful. -**/ -EFI_STATUS -EFIAPI -MouseGetState ( - IN EFI_SIMPLE_POINTER_PROTOCOL *This, - IN OUT EFI_SIMPLE_POINTER_STATE *State - ) -{ - PS2_MOUSE_DEV *MouseDev; - EFI_TPL OldTpl; - - MouseDev = PS2_MOUSE_DEV_FROM_THIS (This); - - if (State == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (!MouseDev->StateChanged) { - return EFI_NOT_READY; - } - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - CopyMem (State, &(MouseDev->State), sizeof (EFI_SIMPLE_POINTER_STATE)); - - // - // clear mouse state - // - MouseDev->State.RelativeMovementX = 0; - MouseDev->State.RelativeMovementY = 0; - MouseDev->State.RelativeMovementZ = 0; - MouseDev->StateChanged = FALSE; - gBS->RestoreTPL (OldTpl); - - return EFI_SUCCESS; -} - -/** - - Event notification function for SIMPLE_POINTER.WaitForInput event. - Signal the event if there is input from mouse. - - @param Event event object - @param Context event context - -**/ -VOID -EFIAPI -MouseWaitForInput ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - PS2_MOUSE_DEV *MouseDev; - - MouseDev = (PS2_MOUSE_DEV *) Context; - - // - // Someone is waiting on the mouse event, if there's - // input from mouse, signal the event - // - if (MouseDev->StateChanged) { - gBS->SignalEvent (Event); - } - -} - -/** - Event notification function for TimerEvent event. - If mouse device is connected to system, try to get the mouse packet data. - - @param Event - TimerEvent in PS2_MOUSE_DEV - @param Context - Pointer to PS2_MOUSE_DEV structure - -**/ -VOID -EFIAPI -PollMouse ( - IN EFI_EVENT Event, - IN VOID *Context - ) - -{ - PS2_MOUSE_DEV *MouseDev; - - MouseDev = (PS2_MOUSE_DEV *) Context; - - // - // Polling mouse packet data - // - PS2MouseGetPacket (MouseDev); -} - -/** - The user Entry Point for module Ps2Mouse. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -InitializePs2Mouse( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gPS2MouseDriver, - ImageHandle, - &gPs2MouseComponentName, - &gPs2MouseComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.h b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.h deleted file mode 100644 index 604fb47e47..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.h +++ /dev/null @@ -1,400 +0,0 @@ -/** @file - PS/2 Mouse driver header file. - -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 _PS2MOUSE_H_ -#define _PS2MOUSE_H_ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gPS2MouseDriver; -extern EFI_COMPONENT_NAME_PROTOCOL gPs2MouseComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gPs2MouseComponentName2; - -// -// PS/2 mouse sample rate -// -typedef enum { - SampleRate10, - SampleRate20, - SampleRate40, - SampleRate60, - SampleRate80, - SampleRate100, - SampleRate200, - MaxSampleRate -} MOUSE_SR; - -// -// PS/2 mouse resolution -// -typedef enum { - MouseResolution1, - MouseResolution2, - MouseResolution4, - MouseResolution8, - MaxResolution -} MOUSE_RE; - -// -// PS/2 mouse scaling -// -typedef enum { - Scaling1, - Scaling2 -} MOUSE_SF; - -// -// Driver Private Data -// -#define PS2_MOUSE_DEV_SIGNATURE SIGNATURE_32 ('p', 's', '2', 'm') - -typedef struct { - UINTN Signature; - - EFI_HANDLE Handle; - EFI_SIMPLE_POINTER_PROTOCOL SimplePointerProtocol; - EFI_SIMPLE_POINTER_STATE State; - EFI_SIMPLE_POINTER_MODE Mode; - BOOLEAN StateChanged; - - // - // PS2 Mouse device specific information - // - MOUSE_SR SampleRate; - MOUSE_RE Resolution; - MOUSE_SF Scaling; - UINT8 DataPackageSize; - - EFI_ISA_IO_PROTOCOL *IsaIo; - - EFI_EVENT TimerEvent; - - EFI_UNICODE_STRING_TABLE *ControllerNameTable; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} PS2_MOUSE_DEV; - -#define PS2_MOUSE_DEV_FROM_THIS(a) CR (a, PS2_MOUSE_DEV, SimplePointerProtocol, PS2_MOUSE_DEV_SIGNATURE) - -// -// Function prototypes -// -/** - Test to see if this driver supports ControllerHandle. Any ControllerHandle - than contains a IsaIo protocol can be supported. - - @param This 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 EFI_ALREADY_STARTED This driver is already running on this device - @retval other This driver does not support this device - -**/ -EFI_STATUS -EFIAPI -PS2MouseDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Start this driver on ControllerHandle by opening a IsaIo - protocol, creating PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid - finnally. - - @param This 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 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 -PS2MouseDriverStart ( - 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 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 -PS2MouseDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// EFI Component Name Functions -// -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -Ps2MouseComponentNameGetDriverName ( - 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 -Ps2MouseComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -/** - Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system - - @param This - Pointer of simple pointer Protocol. - @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. - - - @retval EFI_SUCCESS - The command byte is written successfully. - @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. - -**/ -EFI_STATUS -EFIAPI -MouseReset ( - IN EFI_SIMPLE_POINTER_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Get and Clear mouse status. - - @param This - Pointer of simple pointer Protocol. - @param State - Output buffer holding status. - - @retval EFI_INVALID_PARAMETER Output buffer is invalid. - @retval EFI_NOT_READY Mouse is not changed status yet. - @retval EFI_SUCCESS Mouse status is changed and get successful. -**/ -EFI_STATUS -EFIAPI -MouseGetState ( - IN EFI_SIMPLE_POINTER_PROTOCOL *This, - IN OUT EFI_SIMPLE_POINTER_STATE *State - ); - -/** - - Event notification function for SIMPLE_POINTER.WaitForInput event. - Signal the event if there is input from mouse. - - @param Event event object - @param Context event context - -**/ -VOID -EFIAPI -MouseWaitForInput ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - Event notification function for TimerEvent event. - If mouse device is connected to system, try to get the mouse packet data. - - @param Event - TimerEvent in PS2_MOUSE_DEV - @param Context - Pointer to PS2_MOUSE_DEV structure - -**/ -VOID -EFIAPI -PollMouse ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - I/O work flow of in 8042 data. - - @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL - @param Data Data value - - @retval EFI_SUCCESS Success to excute I/O work flow - @retval EFI_TIMEOUT Keyboard controller time out. -**/ -EFI_STATUS -In8042Data ( - IN EFI_ISA_IO_PROTOCOL *IsaIo, - IN OUT UINT8 *Data - ); - -/** - Check whether there is Ps/2 mouse device in system - - @param MouseDev - Mouse Private Data Structure - - @retval TRUE - Keyboard in System. - @retval FALSE - Keyboard not in System. - -**/ -BOOLEAN -CheckMouseConnect ( - IN PS2_MOUSE_DEV *MouseDev - ); - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf deleted file mode 100644 index ea7af5b10b..0000000000 --- a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf +++ /dev/null @@ -1,76 +0,0 @@ -## @file -# PS2 Mouse Driver. -# -# This dirver provides support for PS2 based mice. -# -# 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 -# 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 = Ps2MouseDxe - MODULE_UNI_FILE = Ps2MouseDxe.uni - FILE_GUID = 202A2B0E-9A31-4812-B291-8747DF152439 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializePs2Mouse - -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# DRIVER_BINDING = gPS2MouseDriver; -# COMPONENT_NAME = gPs2MouseComponentName; -# COMPONENT_NAME2 = gPs2MouseComponentName2; -# - -[Sources] - ComponentName.c - CommPs2.h - CommPs2.c - Ps2Mouse.h - Ps2Mouse.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - ReportStatusCodeLib - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - UefiLib - UefiDriverEntryPoint - DebugLib - PcdLib - -[Protocols] - gEfiIsaIoProtocolGuid ## TO_START - gEfiSimplePointerProtocolGuid ## BY_START - gEfiDevicePathProtocolGuid ## TO_START - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification ## CONSUMES - -# -# [Event] -# -# ## -# # Timer event used to check the mouse state at a regular interval. -# # -# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES -# - -[UserExtensions.TianoCore."ExtraFiles"] - Ps2MouseDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni deleted file mode 100644 index c22c440d85..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni b/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni deleted file mode 100644 index 750a15a849..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c deleted file mode 100644 index c541eb8991..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c +++ /dev/null @@ -1,2799 +0,0 @@ -/** @file - This file contains all helper functions on the ATA command - - Copyright (c) 2006 - 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. - - @par Revision Reference: - 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including - update - ATAIdentity() func - update - AtaBlockIoReadBlocks() func - update - AtaBlockIoWriteBlocks() func - add - AtaAtapi6Identify() func - add - AtaReadSectorsExt() func - add - AtaWriteSectorsExt() func - add - AtaPioDataInExt() func - add - AtaPioDataOutExt() func - -**/ - -#include "IdeBus.h" -/** - This function is called by ATAIdentify() to identity whether this disk - supports ATA/ATAPI6 48bit addressing, ie support >120G capacity - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - - @retval EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one and - 48-bit addressing must be used - @retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but the - capacity is below 120G, 48bit addressing is not needed - @retval EFI_DEVICE_ERROR The identify data in IdeDev is incorrect - @retval EFI_INVALID_PARAMETER The identify data in IdeDev is NULL. - - @note This function must be called after DEVICE_IDENTITY command has been - successfully returned - -**/ -EFI_STATUS -AtaAtapi6Identify ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - UINT8 Index; - EFI_LBA TmpLba; - EFI_LBA Capacity; - EFI_IDENTIFY_DATA *Atapi6IdentifyStruct; - - if (IdeDev->IdData == NULL) { - return EFI_INVALID_PARAMETER; - } - - Atapi6IdentifyStruct = IdeDev->IdData; - - if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & (BIT15 | BIT14)) != 0x4000) { - // - // Per ATA-6 spec, word83: bit15 is zero and bit14 is one - // - return EFI_DEVICE_ERROR; - } - - if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & BIT10) == 0) { - // - // The device dosn't support 48 bit addressing - // - return EFI_UNSUPPORTED; - } - - // - // 48 bit address feature set is supported, get maximum capacity - // - Capacity = Atapi6IdentifyStruct->AtaData.maximum_lba_for_48bit_addressing[0]; - for (Index = 1; Index < 4; Index++) { - // - // Lower byte goes first: word[100] is the lowest word, word[103] is highest - // - TmpLba = Atapi6IdentifyStruct->AtaData.maximum_lba_for_48bit_addressing[Index]; - Capacity |= LShiftU64 (TmpLba, 16 * Index); - } - - if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) { - // - // Capacity exceeds 120GB. 48-bit addressing is really needed - // - IdeDev->Type = Ide48bitAddressingHardDisk; - - // - // Fill block media information:Media->LogicalPartition , - // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function. - // - IdeDev->BlkIo.Media->IoAlign = 4; - IdeDev->BlkIo.Media->MediaId = 1; - IdeDev->BlkIo.Media->RemovableMedia = FALSE; - IdeDev->BlkIo.Media->MediaPresent = TRUE; - IdeDev->BlkIo.Media->ReadOnly = FALSE; - IdeDev->BlkIo.Media->BlockSize = 0x200; - IdeDev->BlkIo.Media->LastBlock = Capacity - 1; - - return EFI_SUCCESS; - } - - return EFI_UNSUPPORTED; -} -/** - Enable SMART of the disk if supported - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record - all the information of the IDE device. -**/ -VOID -AtaSMARTSupport ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - EFI_STATUS Status; - BOOLEAN SMARTSupported; - UINT8 Device; - EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer; - UINT8 DeviceSelect; - UINT8 LBAMid; - UINT8 LBAHigh; - - // - // Detect if the device supports S.M.A.R.T. - // - if ((IdeDev->IdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) { - // - // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one) - // - return ; - } else { - if ((IdeDev->IdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) { - // - // S.M.A.R.T is not supported by the device - // - SMARTSupported = FALSE; - } else { - SMARTSupported = TRUE; - } - } - - if (!SMARTSupported) { - // - // Report nonsupport status code - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED) - ); - } else { - // - // Enable this feature - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE) - ); - - Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); - Status = AtaNonDataCommandIn ( - IdeDev, - ATA_CMD_SMART, - Device, - ATA_SMART_ENABLE_OPERATION, - 0, - 0, - ATA_CONSTANT_4F, - ATA_CONSTANT_C2 - ); - // - // Detect if this feature is enabled - // - TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA)); - if (TmpAtaIdentifyPointer == NULL) { - return; - } - - DeviceSelect = (UINT8) ((IdeDev->Device) << 4); - Status = AtaPioDataIn ( - IdeDev, - (VOID *) TmpAtaIdentifyPointer, - sizeof (EFI_IDENTIFY_DATA), - ATA_CMD_IDENTIFY_DRIVE, - DeviceSelect, - 0, - 0, - 0, - 0 - ); - if (EFI_ERROR (Status)) { - gBS->FreePool (TmpAtaIdentifyPointer); - return ; - } - - // - // Check if the feature is enabled - // - if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) { - // - // Read status data - // - AtaNonDataCommandIn ( - IdeDev, - ATA_CMD_SMART, - Device, - ATA_SMART_RETURN_STATUS, - 0, - 0, - ATA_CONSTANT_4F, - ATA_CONSTANT_C2 - ); - LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); - LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb); - - if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) { - // - // The threshold exceeded condition is not detected by the device - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD) - ); - - } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) { - // - // The threshold exceeded condition is detected by the device - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD) - ); - } - - } else { - // - // Report disabled status code - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED) - ); - } - - gBS->FreePool (TmpAtaIdentifyPointer); - } - - return ; -} -/** - Sends out an ATA Identify Command to the specified device. - - This function is called by DiscoverIdeDevice() during its device - identification. It sends out the ATA Identify Command to the - specified device. Only ATA device responses to this command. If - the command succeeds, it returns the Identify data structure which - contains information about the device. This function extracts the - information it needs to fill the IDE_BLK_IO_DEV data structure, - including device type, media block size, media capacity, and etc. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record - all the information of the IDE device. - - @retval EFI_SUCCESS Identify ATA device successfully. - @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device. - @note parameter IdeDev will be updated in this function. - -**/ -EFI_STATUS -ATAIdentify ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - EFI_STATUS Status; - EFI_IDENTIFY_DATA *AtaIdentifyPointer; - UINT32 Capacity; - UINT8 DeviceSelect; - UINTN Retry; - - // - // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of - // the ATA Identify command - // - AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA)); - if (AtaIdentifyPointer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // use ATA PIO Data In protocol to send ATA Identify command - // and receive data from device - // - DeviceSelect = (UINT8) ((IdeDev->Device) << 4); - - - Retry = 3; - while (Retry > 0) { - Status = AtaPioDataIn ( - IdeDev, - (VOID *) AtaIdentifyPointer, - sizeof (EFI_IDENTIFY_DATA), - ATA_CMD_IDENTIFY_DRIVE, - DeviceSelect, - 0, - 0, - 0, - 0 - ); - // - // If ATA Identify command succeeds, then according to the received - // IDENTIFY data, - // identify the device type ( ATA or not ). - // If ATA device, fill the information in IdeDev. - // If not ATA device, return IDE_DEVICE_ERROR - // - if (!EFI_ERROR (Status)) { - - IdeDev->IdData = AtaIdentifyPointer; - - // - // Print ATA Module Name - // - PrintAtaModuleName (IdeDev); - - // - // bit 15 of pAtaIdentify->config is used to identify whether device is - // ATA device or ATAPI device. - // if 0, means ATA device; if 1, means ATAPI device. - // - if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) { - // - // Detect if support S.M.A.R.T. If yes, enable it as default - // - AtaSMARTSupport (IdeDev); - - // - // Check whether this device needs 48-bit addressing (ATAPI-6 ata device) - // - Status = AtaAtapi6Identify (IdeDev); - if (!EFI_ERROR (Status)) { - // - // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify() - // - return EFI_SUCCESS; - } else if (Status == EFI_DEVICE_ERROR) { - // - // Some disk with big capacity (>200GB) is slow when being identified - // and will return all zero for word83. - // We try twice at first. If it fails, we do a SoftRest and try again. - // - Retry--; - if (Retry == 1) { - // - // Do a SoftRest before the third attempt. - // - AtaSoftReset (IdeDev); - } - continue; - } - // - // This is a hard disk <= 120GB capacity, treat it as normal hard disk - // - IdeDev->Type = IdeHardDisk; - - // - // Block Media Information: - // Media->LogicalPartition , Media->WriteCaching will be filled - // in the DiscoverIdeDevcie() function. - // - IdeDev->BlkIo.Media->IoAlign = 4; - IdeDev->BlkIo.Media->MediaId = 1; - IdeDev->BlkIo.Media->RemovableMedia = FALSE; - IdeDev->BlkIo.Media->MediaPresent = TRUE; - IdeDev->BlkIo.Media->ReadOnly = FALSE; - IdeDev->BlkIo.Media->BlockSize = 0x200; - - // - // Calculate device capacity - // - Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) | - AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ; - IdeDev->BlkIo.Media->LastBlock = Capacity - 1; - - return EFI_SUCCESS; - } - - } - break; - } - - gBS->FreePool (AtaIdentifyPointer); - // - // Make sure the pIdData will not be freed again. - // - IdeDev->IdData = NULL; - - return EFI_DEVICE_ERROR; -} - -/** - This function is a helper function used to change the char order in a string. It - is designed specially for the PrintAtaModuleName() function. After the IDE device - is detected, the IDE driver gets the device module name by sending ATA command - called ATA Identify Command or ATAPI Identify Command to the specified IDE device. - The module name returned is a string of ASCII characters: the first character is bit8--bit15 - of the first word, the second character is BIT0--bit7 of the first word and so on. Thus - the string can not be print directly before it is preprocessed by this func to change - the order of characters in each word in the string. - - @param Destination Indicates the destination string. - @param Source Indicates the source string. - @param Size the length of the string -**/ -VOID -SwapStringChars ( - IN CHAR8 *Destination, - IN CHAR8 *Source, - IN UINT32 Size - ) -{ - UINT32 Index; - CHAR8 Temp; - - for (Index = 0; Index < Size; Index += 2) { - - Temp = Source[Index + 1]; - Destination[Index + 1] = Source[Index]; - Destination[Index] = Temp; - } -} -/** - This function is called by ATAIdentify() or ATAPIIdentify() to print device's module name. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. -**/ -VOID -PrintAtaModuleName ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - if (IdeDev->IdData == NULL) { - return ; - } - - SwapStringChars (IdeDev->ModelName, IdeDev->IdData->AtaData.ModelName, 40); - IdeDev->ModelName[40] = 0x00; -} - -/** - This function is used to send out ATA commands conforms to the PIO Data In Protocol. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param Buffer buffer contained data transferred from device to host. - @param ByteCount data size in byte unit of the buffer. - @param AtaCommand value of the Command Register - @param Head value of the Head/Device Register - @param SectorCount value of the Sector Count Register - @param SectorNumber value of the Sector Number Register - @param CylinderLsb value of the low byte of the Cylinder Register - @param CylinderMsb value of the high byte of the Cylinder Register - - @retval EFI_SUCCESS send out the ATA command and device send required data successfully. - @retval EFI_DEVICE_ERROR command sent failed. - -**/ -EFI_STATUS -AtaPioDataIn ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN UINT8 Head, - IN UINT8 SectorCount, - IN UINT8 SectorNumber, - IN UINT8 CylinderLsb, - IN UINT8 CylinderMsb - ) -{ - UINTN WordCount; - UINTN Increment; - UINT16 *Buffer16; - EFI_STATUS Status; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // e0:1110,0000-- bit7 and bit5 are reserved bits. - // bit6 set means LBA mode - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head) - ); - - // - // All ATAPI device's ATA commands can be issued regardless of the - // state of the DRDY - // - if (IdeDev->Type == IdeHardDisk) { - - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - } - // - // set all the command parameters - // Before write to all the following registers, BSY and DRQ must be 0. - // - Status = DRQClear2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - if (AtaCommand == ATA_CMD_SET_FEATURES) { - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); - } - - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb); - - // - // send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - Buffer16 = (UINT16 *) Buffer; - - // - // According to PIO data in protocol, host can perform a series of reads to - // the data register after each time device set DRQ ready; - // The data size of "a series of read" is command specific. - // For most ATA command, data size received from device will not exceed - // 1 sector, hence the data size for "a series of read" can be the whole data - // size of one command request. - // For ATA command such as Read Sector command, the data size of one ATA - // command request is often larger than 1 sector, according to the - // Read Sector command, the data size of "a series of read" is exactly 1 - // sector. - // Here for simplification reason, we specify the data size for - // "a series of read" to 1 sector (256 words) if data size of one ATA command - // request is larger than 256 words. - // - Increment = 256; - - // - // used to record bytes of currently transfered data - // - WordCount = 0; - - while (WordCount < ByteCount / 2) { - // - // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. - // - Status = DRQReady2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Status = CheckErrorStatus (IdeDev); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Get the byte count for one series of read - // - if ((WordCount + Increment) > ByteCount / 2) { - Increment = ByteCount / 2 - WordCount; - } - - IDEReadPortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - Increment, - Buffer16 - ); - - WordCount += Increment; - Buffer16 += Increment; - - } - - DRQClear (IdeDev, ATATIMEOUT); - - return CheckErrorStatus (IdeDev); -} - -/** - This function is used to send out ATA commands conforms to the - PIO Data Out Protocol. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param *Buffer buffer contained data transferred from host to device. - @param ByteCount data size in byte unit of the buffer. - @param AtaCommand value of the Command Register - @param Head value of the Head/Device Register - @param SectorCount value of the Sector Count Register - @param SectorNumber value of the Sector Number Register - @param CylinderLsb value of the low byte of the Cylinder Register - @param CylinderMsb value of the high byte of the Cylinder Register - - @retval EFI_SUCCESS send out the ATA command and device received required - data successfully. - @retval EFI_DEVICE_ERROR command sent failed. - -**/ -EFI_STATUS -AtaPioDataOut ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN UINT8 Head, - IN UINT8 SectorCount, - IN UINT8 SectorNumber, - IN UINT8 CylinderLsb, - IN UINT8 CylinderMsb - ) -{ - UINTN WordCount; - UINTN Increment; - UINT16 *Buffer16; - EFI_STATUS Status; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // select device via Head/Device register. - // Before write Head/Device register, BSY and DRQ must be 0. - // - Status = DRQClear2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // e0:1110,0000-- bit7 and bit5 are reserved bits. - // bit6 set means LBA mode - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head) - ); - - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // set all the command parameters - // Before write to all the following registers, BSY and DRQ must be 0. - // - Status = DRQClear2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb); - - // - // send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - Buffer16 = (UINT16 *) Buffer; - - // - // According to PIO data out protocol, host can perform a series of - // writes to the data register after each time device set DRQ ready; - // The data size of "a series of read" is command specific. - // For most ATA command, data size written to device will not exceed 1 sector, - // hence the data size for "a series of write" can be the data size of one - // command request. - // For ATA command such as Write Sector command, the data size of one - // ATA command request is often larger than 1 sector, according to the - // Write Sector command, the data size of "a series of read" is exactly - // 1 sector. - // Here for simplification reason, we specify the data size for - // "a series of write" to 1 sector (256 words) if data size of one ATA command - // request is larger than 256 words. - // - Increment = 256; - WordCount = 0; - - while (WordCount < ByteCount / 2) { - - // - // DRQReady2-- read Alternate Status Register to determine the DRQ bit - // data transfer can be performed only when DRQ is ready. - // - Status = DRQReady2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Status = CheckErrorStatus (IdeDev); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Check the remaining byte count is less than 512 bytes - // - if ((WordCount + Increment) > ByteCount / 2) { - Increment = ByteCount / 2 - WordCount; - } - // - // perform a series of write without check DRQ ready - // - - IDEWritePortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - Increment, - Buffer16 - ); - WordCount += Increment; - Buffer16 += Increment; - - } - - DRQClear (IdeDev, ATATIMEOUT); - - return CheckErrorStatus (IdeDev); -} - -/** - This function is used to analyze the Status Register and print out - some debug information and if there is ERR bit set in the Status - Register, the Error Register's value is also be parsed and print out. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to - record all the information of the IDE device. - - @retval EFI_SUCCESS No err information in the Status Register. - @retval EFI_DEVICE_ERROR Any err information in the Status Register. - -**/ -EFI_STATUS -CheckErrorStatus ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - UINT8 StatusRegister; - UINT8 ErrorRegister; - - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - - DEBUG_CODE_BEGIN (); - - if ((StatusRegister & ATA_STSREG_DWF) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Write Fault\n", - StatusRegister) - ); - } - - if ((StatusRegister & ATA_STSREG_CORR) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Corrected Data\n", - StatusRegister) - ); - } - - if ((StatusRegister & ATA_STSREG_ERR) != 0) { - ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - - if ((ErrorRegister & ATA_ERRREG_BBK) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n", - ErrorRegister) - ); - } - - if ((ErrorRegister & ATA_ERRREG_UNC) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n", - ErrorRegister) - ); - } - - if ((ErrorRegister & ATA_ERRREG_MC) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Media Change\n", - ErrorRegister) - ); - } - - if ((ErrorRegister & ATA_ERRREG_ABRT) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Abort\n", - ErrorRegister) - ); - } - - if ((ErrorRegister & ATA_ERRREG_TK0NF) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n", - ErrorRegister) - ); - } - - if ((ErrorRegister & ATA_ERRREG_AMNF) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n", - ErrorRegister) - ); - } - } - - DEBUG_CODE_END (); - - if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) { - return EFI_SUCCESS; - } - - return EFI_DEVICE_ERROR; - -} - -/** - This function is called by the AtaBlkIoReadBlocks() to perform reading from - media in block unit. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param DataBuffer A pointer to the destination buffer for the data. - @param Lba The starting logical block address to read from on the device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status is fully dependent on the return status of AtaPioDataIn() function. - -**/ -EFI_STATUS -AtaReadSectors ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ) -{ - EFI_STATUS Status; - UINTN BlocksRemaining; - UINT32 Lba32; - UINT8 Lba0; - UINT8 Lba1; - UINT8 Lba2; - UINT8 Lba3; - UINT8 AtaCommand; - UINT8 SectorCount8; - UINT16 SectorCount; - UINTN ByteCount; - VOID *Buffer; - - Buffer = DataBuffer; - - // - // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol - // - AtaCommand = ATA_CMD_READ_SECTORS; - - - BlocksRemaining = NumberOfBlocks; - - Lba32 = (UINT32) Lba; - - Status = EFI_SUCCESS; - - while (BlocksRemaining > 0) { - - // - // in ATA-3 spec, LBA is in 28 bit width - // - Lba0 = (UINT8) Lba32; - Lba1 = (UINT8) (Lba32 >> 8); - Lba2 = (UINT8) (Lba32 >> 16); - // - // low 4 bit of Lba3 stands for LBA bit24~bit27. - // - Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f); - - if (BlocksRemaining >= 0x100) { - - // - // SectorCount8 is sent to Sector Count register, 0x00 means 256 - // sectors to be read - // - SectorCount8 = 0x00; - // - // SectorCount is used to record the number of sectors to be read - // - SectorCount = 256; - } else { - - SectorCount8 = (UINT8) BlocksRemaining; - SectorCount = (UINT16) BlocksRemaining; - } - - // - // ByteCount is the number of bytes that will be read - // - ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); - - // - // call AtaPioDataIn() to send Read Sector Command and receive data read - // - Status = AtaPioDataIn ( - IdeDev, - Buffer, - (UINT32) ByteCount, - AtaCommand, - Lba3, - SectorCount8, - Lba0, - Lba1, - Lba2 - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Lba32 += SectorCount; - Buffer = ((UINT8 *) Buffer + ByteCount); - BlocksRemaining -= SectorCount; - } - - return Status; -} - -/** - This function is called by the AtaBlkIoWriteBlocks() to perform writing onto - media in block unit. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record - all the information of the IDE device. - @param BufferData A pointer to the source buffer for the data. - @param Lba The starting logical block address to write onto the device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status is fully dependent on the return status of AtaPioDataIn() function. - -**/ -EFI_STATUS -AtaWriteSectors ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *BufferData, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ) -{ - EFI_STATUS Status; - UINTN BlocksRemaining; - UINT32 Lba32; - UINT8 Lba0; - UINT8 Lba1; - UINT8 Lba2; - UINT8 Lba3; - UINT8 AtaCommand; - UINT8 SectorCount8; - UINT16 SectorCount; - UINTN ByteCount; - VOID *Buffer; - - Buffer = BufferData; - - // - // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol - // - AtaCommand = ATA_CMD_WRITE_SECTORS; - - BlocksRemaining = NumberOfBlocks; - - Lba32 = (UINT32) Lba; - - Status = EFI_SUCCESS; - - while (BlocksRemaining > 0) { - - Lba0 = (UINT8) Lba32; - Lba1 = (UINT8) (Lba32 >> 8); - Lba2 = (UINT8) (Lba32 >> 16); - Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f); - - if (BlocksRemaining >= 0x100) { - - // - // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors - // to be written - // - SectorCount8 = 0x00; - // - // SectorCount is used to record the number of sectors to be written - // - SectorCount = 256; - } else { - - SectorCount8 = (UINT8) BlocksRemaining; - SectorCount = (UINT16) BlocksRemaining; - } - - ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); - - Status = AtaPioDataOut ( - IdeDev, - Buffer, - (UINT32) ByteCount, - AtaCommand, - Lba3, - SectorCount8, - Lba0, - Lba1, - Lba2 - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Lba32 += SectorCount; - Buffer = ((UINT8 *) Buffer + ByteCount); - BlocksRemaining -= SectorCount; - } - - return Status; -} -/** - This function is used to implement the Soft Reset on the specified device. But, - the ATA Soft Reset mechanism is so strong a reset method that it will force - resetting on both devices connected to the same cable. - - It is called by IdeBlkIoReset(), a interface function of Block - I/O protocol. - - This function can also be used by the ATAPI device to perform reset when - ATAPI Reset command is failed. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @retval EFI_SUCCESS Soft reset completes successfully. - @retval EFI_DEVICE_ERROR Any step during the reset process is failed. - - @note The registers initial values after ATA soft reset are different - to the ATA device and ATAPI device. -**/ -EFI_STATUS -AtaSoftReset ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - - UINT8 DeviceControl; - - DeviceControl = 0; - // - // set SRST bit to initiate soft reset - // - DeviceControl |= ATA_CTLREG_SRST; - - // - // disable Interrupt - // - DeviceControl |= BIT1; - - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); - - // - // SRST should assert for at least 5 us, we use 10 us for - // better compatibility - // - gBS->Stall (10); - - // - // Enable interrupt to support UDMA, and clear SRST bit - // - DeviceControl = 0; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); - - // - // Wait for at least 2 ms to check BSY status, we use 10 ms - // for better compatibility - // - gBS->Stall(10000); - // - // slave device needs at most 31s to clear BSY - // - if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} -/** - This function is used to send out ATA commands conforms to the PIO Data In - Protocol, supporting ATA/ATAPI-6 standard - - Comparing with ATA-3 data in protocol, we have two differents here: - 1. Do NOT wait for DRQ clear before sending command into IDE device.(the - wait will frequently fail... cause writing function return error) - - 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly - slow down writing performance by 100 times!) - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param Buffer buffer contained data transferred from device to host. - @param ByteCount data size in byte unit of the buffer. - @param AtaCommand value of the Command Register - @param StartLba the start LBA of this transaction - @param SectorCount the count of sectors to be transfered - - @retval EFI_SUCCESS send out the ATA command and device send required data successfully. - @retval EFI_DEVICE_ERROR command sent failed. - -**/ -EFI_STATUS -AtaPioDataInExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN OUT VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN EFI_LBA StartLba, - IN UINT16 SectorCount - ) -{ - UINT8 DevSel; - UINT8 SectorCount8; - UINT8 LbaLow; - UINT8 LbaMid; - UINT8 LbaHigh; - UINTN WordCount; - UINTN Increment; - UINT16 *Buffer16; - EFI_STATUS Status; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device, set bit6 as 1 to indicate LBA mode is used - // - DevSel = (UINT8) (IdeDev->Device << 4); - DevSel |= 0x40; - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - DevSel - ); - - // - // Wait for DRDY singnal asserting. ATAPI device needn't wait - // - if ( (IdeDev->Type == IdeHardDisk) || - (IdeDev->Type == Ide48bitAddressingHardDisk)) { - - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - } - - // - // Fill feature register if needed - // - if (AtaCommand == ATA_CMD_SET_FEATURES) { - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); - } - - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) (SectorCount >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - // - // Fill the start LBA registers, which are also two-byte FIFO - // - LbaLow = (UINT8) RShiftU64 (StartLba, 24); - LbaMid = (UINT8) RShiftU64 (StartLba, 32); - LbaHigh = (UINT8) RShiftU64 (StartLba, 40); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - LbaLow = (UINT8) StartLba; - LbaMid = (UINT8) RShiftU64 (StartLba, 8); - LbaHigh = (UINT8) RShiftU64 (StartLba, 16); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - // - // Send command via Command Register, invoking the processing of this command - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - Buffer16 = (UINT16 *) Buffer; - - // - // According to PIO data in protocol, host can perform a series of reads to - // the data register after each time device set DRQ ready; - // - - // - // 256 words - // - Increment = 256; - - // - // used to record bytes of currently transfered data - // - WordCount = 0; - - while (WordCount < ByteCount / 2) { - // - // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. - // - Status = DRQReady2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Status = CheckErrorStatus (IdeDev); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Get the byte count for one series of read - // - if ((WordCount + Increment) > ByteCount / 2) { - Increment = ByteCount / 2 - WordCount; - } - - IDEReadPortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - Increment, - Buffer16 - ); - - WordCount += Increment; - Buffer16 += Increment; - - } - - return CheckErrorStatus (IdeDev); -} -/** - Send ATA Ext command into device with NON_DATA protocol. - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaAddress The LBA address in 48-bit mode - - @retval EFI_SUCCESS Reading succeed - @retval EFI_DEVICE_ERROR Error executing commands on this device. - -**/ -EFI_STATUS -AtaCommandIssueExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ) -{ - EFI_STATUS Status; - UINT8 SectorCount8; - UINT8 Feature8; - UINT8 LbaLow; - UINT8 LbaMid; - UINT8 LbaHigh; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0) - ); - - // - // ATA commands for ATA device must be issued when DRDY is set - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Pass parameter into device register block - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - - // - // Fill the feature register, which is a two-byte FIFO. Need write twice. - // - Feature8 = (UINT8) (Feature >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - - Feature8 = (UINT8) Feature; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) (SectorCount >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - // - // Fill the start LBA registers, which are also two-byte FIFO - // - LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - LbaLow = (UINT8) LbaAddress; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - - LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - - LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - // - // Work around for Segate 160G disk writing - // - gBS->Stall (1800); - - // - // Send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - // - // Stall at least 400ns - // - gBS->Stall (100); - - return EFI_SUCCESS; -} -/** - Send ATA Ext command into device with NON_DATA protocol - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaAddress The LBA address in 48-bit mode - - @retval EFI_SUCCESS Reading succeed - @retval EFI_DEVICE_ERROR Error executing commands on this device. - -**/ -EFI_STATUS -AtaCommandIssue ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ) -{ - EFI_STATUS Status; - UINT8 SectorCount8; - UINT8 Feature8; - UINT8 Lba0; - UINT8 Lba1; - UINT8 Lba2; - UINT8 Lba3; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0) - ); - - // - // ATA commands for ATA device must be issued when DRDY is set - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Lba0 = (UINT8) LbaAddress; - Lba1 = (UINT8) RShiftU64 (LbaAddress, 8); - Lba2 = (UINT8) RShiftU64 (LbaAddress, 16); - Lba3 = (UINT8) RShiftU64 (LbaAddress, 24); - Device = (UINT8) (Device | Lba3); - - // - // Pass parameter into device register block - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - - // - // Fill the feature register, which is a two-byte FIFO. Need write twice. - // - Feature8 = (UINT8) Feature; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - // - // Fill the start LBA registers, which are also two-byte FIFO - // - - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2); - - // - // Send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - // - // Stall at least 400ns - // - gBS->Stall (100); - - return EFI_SUCCESS; -} -/** - Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt). - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param DataBuffer A pointer to the source buffer for the data. - @param StartLba The starting logical block address to write to - on the device media. - @param NumberOfBlocks The number of transfer data blocks. - @param UdmaOp The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp, - AtaUdmaWriteOp, AtaUdmaWriteExOp - - @retval EFI_SUCCESS the operation is successful. - @retval EFI_OUT_OF_RESOURCES Build PRD table failed - @retval EFI_UNSUPPORTED Unknown channel or operations command - @retval EFI_DEVICE_ERROR Ata command execute failed - -**/ -EFI_STATUS -DoAtaUdma ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks, - IN ATA_UDMA_OPERATION UdmaOp - ) -{ - IDE_DMA_PRD *PrdAddr; - IDE_DMA_PRD *UsedPrdAddr; - IDE_DMA_PRD *TempPrdAddr; - UINT8 RegisterValue; - UINT8 Device; - UINT64 IoPortForBmic; - UINT64 IoPortForBmis; - UINT64 IoPortForBmid; - EFI_STATUS Status; - UINTN PrdTableNum; - UINTN ByteCount; - UINTN ByteAvailable; - UINT8 *PrdBuffer; - UINTN RemainBlockNum; - UINT8 DeviceControl; - UINT32 Count; - UINTN PageCount; - VOID *Map; - VOID *MemPage; - EFI_PHYSICAL_ADDRESS DeviceAddress; - UINTN MaxDmaCommandSectors; - EFI_PCI_IO_PROTOCOL_OPERATION PciIoProtocolOp; - UINT8 AtaCommand; - - switch (UdmaOp) { - case AtaUdmaReadOp: - MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS; - PciIoProtocolOp = EfiPciIoOperationBusMasterWrite; - AtaCommand = ATA_CMD_READ_DMA; - break; - case AtaUdmaReadExtOp: - MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS; - PciIoProtocolOp = EfiPciIoOperationBusMasterWrite; - AtaCommand = ATA_CMD_READ_DMA_EXT; - break; - case AtaUdmaWriteOp: - MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS; - PciIoProtocolOp = EfiPciIoOperationBusMasterRead; - AtaCommand = ATA_CMD_WRITE_DMA; - break; - case AtaUdmaWriteExtOp: - MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS; - PciIoProtocolOp = EfiPciIoOperationBusMasterRead; - AtaCommand = ATA_CMD_WRITE_DMA_EXT; - break; - default: - return EFI_UNSUPPORTED; - break; - } - - // - // Select device - // - Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - - // - // Enable interrupt to support UDMA - // - DeviceControl = 0; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); - - if (IdePrimary == IdeDev->Channel) { - IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET; - IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; - IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET; - } else { - if (IdeSecondary == IdeDev->Channel) { - IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET; - IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; - IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET; - } else { - return EFI_UNSUPPORTED; - } - } - - // - // Read BMIS register and clear ERROR and INTR bit - // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - - RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); - - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - - Status = EFI_SUCCESS; - - RemainBlockNum = NumberOfBlocks; - while (RemainBlockNum > 0) { - - if (RemainBlockNum >= MaxDmaCommandSectors) { - // - // SectorCount is used to record the number of sectors to be read - // Max 65536 sectors can be transfered at a time. - // - NumberOfBlocks = MaxDmaCommandSectors; - RemainBlockNum -= MaxDmaCommandSectors; - } else { - NumberOfBlocks = (UINT16) RemainBlockNum; - RemainBlockNum = 0; - } - - // - // Calculate the number of PRD table to make sure the memory region - // not cross 64K boundary - // - ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; - PrdTableNum = ((ByteCount >> 16) + 1) + 1; - - // - // Build PRD table - // - PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD)); - Status = IdeDev->PciIo->AllocateBuffer ( - IdeDev->PciIo, - AllocateAnyPages, - EfiBootServicesData, - PageCount, - &MemPage, - 0 - ); - if (EFI_ERROR (Status)) { - return EFI_OUT_OF_RESOURCES; - } - ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount)); - - PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage); - // - // To make sure PRD is allocated in one 64K page - // - if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) { - UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000); - } else { - if ((UINTN) PrdAddr & 0x03) { - UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC); - } else { - UsedPrdAddr = PrdAddr; - } - } - - // - // Build the PRD table - // - Status = IdeDev->PciIo->Map ( - IdeDev->PciIo, - PciIoProtocolOp, - DataBuffer, - &ByteCount, - &DeviceAddress, - &Map - ); - if (EFI_ERROR (Status)) { - IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); - return EFI_OUT_OF_RESOURCES; - } - PrdBuffer = (VOID *) ((UINTN) DeviceAddress); - TempPrdAddr = UsedPrdAddr; - while (TRUE) { - - ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF); - - if (ByteCount <= ByteAvailable) { - TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); - TempPrdAddr->ByteCount = (UINT16) ByteCount; - TempPrdAddr->EndOfTable = 0x8000; - break; - } - - TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); - TempPrdAddr->ByteCount = (UINT16) ByteAvailable; - - ByteCount -= ByteAvailable; - PrdBuffer += ByteAvailable; - TempPrdAddr++; - } - - // - // Set the base address to BMID register - // - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint32, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmid, - 1, - &UsedPrdAddr - ); - - // - // Set BMIC register to identify the operation direction - // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); - - if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) { - RegisterValue |= BMIC_NREAD; - } else { - RegisterValue &= ~((UINT8) BMIC_NREAD); - } - - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); - - if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) { - Status = AtaCommandIssueExt ( - IdeDev, - AtaCommand, - Device, - 0, - (UINT16) NumberOfBlocks, - StartLba - ); - } else { - Status = AtaCommandIssue ( - IdeDev, - AtaCommand, - Device, - 0, - (UINT16) NumberOfBlocks, - StartLba - ); - } - - if (EFI_ERROR (Status)) { - IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); - IdeDev->PciIo->Unmap (IdeDev->PciIo, Map); - return EFI_DEVICE_ERROR; - } - - // - // Set START bit of BMIC register - // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); - - RegisterValue |= BMIC_START; - - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); - - // - // Check the INTERRUPT and ERROR bit of BMIS - // Max transfer number of sectors for one command is 65536(32Mbyte), - // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps). - // So set the variable Count to 2000, for about 2 second timeout time. - // - Status = EFI_SUCCESS; - Count = 2000; - while (TRUE) { - - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - if (((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) != 0) || (Count == 0)) { - if (((RegisterValue & BMIS_ERROR) != 0) || (Count == 0)) { - Status = EFI_DEVICE_ERROR; - break; - } - break; - } - - gBS->Stall (1000); - Count --; - } - - IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); - IdeDev->PciIo->Unmap (IdeDev->PciIo, Map); - // - // Read BMIS register and clear ERROR and INTR bit - // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - - RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); - - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - // - // Read Status Register of IDE device to clear interrupt - // - RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status); - // - // Clear START bit of BMIC register - // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); - - RegisterValue &= ~((UINT8) BMIC_START); - - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); - - if ((RegisterValue & BMIS_ERROR) != 0) { - return EFI_DEVICE_ERROR; - } - - if (EFI_ERROR (Status)) { - break; - } - DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; - StartLba += NumberOfBlocks; - } - - // - // Disable interrupt of Select device - // - IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl); - DeviceControl |= ATA_CTLREG_IEN_L; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); - - return Status; -} - - -/** - This function is called by the AtaBlkIoReadBlocks() to perform reading from - media in block unit. The function has been enhanced to support >120GB access - and transfer at most 65536 blocks per command - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param DataBuffer A pointer to the destination buffer for the data. - @param StartLba The starting logical block address to read from on the device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status depends on the function DoAtaUdma() returns. -**/ -EFI_STATUS -AtaUdmaReadExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ) -{ - return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp); -} -/** - This function is called by the AtaBlkIoReadBlocks() to perform - reading from media in block unit. The function has been enhanced to - support >120GB access and transfer at most 65536 blocks per command - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param DataBuffer A pointer to the destination buffer for the data. - @param StartLba The starting logical block address to read from - on the device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status depends on the function DoAtaUdma() returns. -**/ -EFI_STATUS -AtaUdmaRead ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ) -{ - return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp); -} - -/** - This function is called by the AtaBlkIoReadBlocks() to perform - reading from media in block unit. The function has been enhanced to - support >120GB access and transfer at most 65536 blocks per command - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param DataBuffer A pointer to the destination buffer for the data. - @param StartLba The starting logical block address to read from on the device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status is fully dependent on the return status of AtaPioDataInExt() function. -**/ -EFI_STATUS -AtaReadSectorsExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ) -{ - EFI_STATUS Status; - UINTN BlocksRemaining; - EFI_LBA Lba64; - UINT8 AtaCommand; - UINT16 SectorCount; - UINT32 ByteCount; - VOID *Buffer; - - // - // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol - // - AtaCommand = ATA_CMD_READ_SECTORS_EXT; - Buffer = DataBuffer; - BlocksRemaining = NumberOfBlocks; - Lba64 = StartLba; - Status = EFI_SUCCESS; - - while (BlocksRemaining > 0) { - - if (BlocksRemaining >= 0x10000) { - // - // SectorCount is used to record the number of sectors to be read - // Max 65536 sectors can be transfered at a time. - // - SectorCount = 0xffff; - } else { - SectorCount = (UINT16) BlocksRemaining; - } - - // - // ByteCount is the number of bytes that will be read - // - ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); - - // - // call AtaPioDataInExt() to send Read Sector Command and receive data read - // - Status = AtaPioDataInExt ( - IdeDev, - Buffer, - ByteCount, - AtaCommand, - Lba64, - SectorCount - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Lba64 += SectorCount; - Buffer = ((UINT8 *) Buffer + ByteCount); - BlocksRemaining -= SectorCount; - } - - return Status; -} -/** - This function is the ATA implementation for ReadBlocks in the - Block I/O Protocol interface. - - @param IdeBlkIoDevice Indicates the calling context. - @param MediaId The media id that the read request is for. - @param Lba The starting logical block address to read from on the device. - @param BufferSize The size of the Buffer in bytes. This must be a multiple - of the intrinsic block size of the device. - - @param Buffer A pointer to the destination buffer for the data. The caller - is responsible for either having implicit or explicit ownership - of the memory that data is read into. - - @retval EFI_SUCCESS Read Blocks successfully. - @retval EFI_DEVICE_ERROR Read Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, - or the data buffer is not valid. - - @note If Read Block error because of device error, this function will call - AtaSoftReset() function to reset device. - -**/ -EFI_STATUS -AtaBlkIoReadBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - UINTN BlockSize; - UINTN NumberOfBlocks; - EFI_STATUS Status; - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - Status = EFI_SUCCESS; - - // - // Get the intrinsic block size - // - Media = IdeBlkIoDevice->BlkIo.Media; - BlockSize = Media->BlockSize; - - NumberOfBlocks = BufferSize / BlockSize; - - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (!(Media->MediaPresent)) { - return EFI_NO_MEDIA; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - // - // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism - // - if (IdeBlkIoDevice->UdmaMode.Valid) { - Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - } else { - Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - } - } else { - // - // For ATA-3 compatible device, use ATA-3 read block mechanism - // - if (IdeBlkIoDevice->UdmaMode.Valid) { - Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - } else { - Status = AtaReadSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - } - } - - if (EFI_ERROR (Status)) { - AtaSoftReset (IdeBlkIoDevice); - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; - -} -/** - This function is used to send out ATA commands conforms to the - PIO Data Out Protocol, supporting ATA/ATAPI-6 standard - - Comparing with ATA-3 data out protocol, we have two differents here:
- 1. Do NOT wait for DRQ clear before sending command into IDE device.(the - wait will frequently fail... cause writing function return error) - - 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly - slow down writing performance by 100 times!) - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param Buffer buffer contained data transferred from host to device. - @param ByteCount data size in byte unit of the buffer. - @param AtaCommand value of the Command Register - @param StartLba the start LBA of this transaction - @param SectorCount the count of sectors to be transfered - - @retval EFI_SUCCESS send out the ATA command and device receive required - data successfully. - @retval EFI_DEVICE_ERROR command sent failed. - -**/ -EFI_STATUS -AtaPioDataOutExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN EFI_LBA StartLba, - IN UINT16 SectorCount - ) -{ - UINT8 DevSel; - UINT8 SectorCount8; - UINT8 LbaLow; - UINT8 LbaMid; - UINT8 LbaHigh; - UINTN WordCount; - UINTN Increment; - UINT16 *Buffer16; - EFI_STATUS Status; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device. Set bit6 as 1 to indicate LBA mode is used - // - DevSel = (UINT8) (IdeDev->Device << 4); - DevSel |= 0x40; - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - DevSel - ); - - // - // Wait for DRDY singnal asserting. - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Fill feature register if needed - // - if (AtaCommand == ATA_CMD_SET_FEATURES) { - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); - } - - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) (SectorCount >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - // - // Fill the start LBA registers, which are also two-byte FIFO - // - LbaLow = (UINT8) RShiftU64 (StartLba, 24); - LbaMid = (UINT8) RShiftU64 (StartLba, 32); - LbaHigh = (UINT8) RShiftU64 (StartLba, 40); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - LbaLow = (UINT8) StartLba; - LbaMid = (UINT8) RShiftU64 (StartLba, 8); - LbaHigh = (UINT8) RShiftU64 (StartLba, 16); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - // - // Send command via Command Register, invoking the processing of this command - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - Buffer16 = (UINT16 *) Buffer; - - // - // According to PIO Data Out protocol, host can perform a series of writes to - // the data register after each time device set DRQ ready; - // - Increment = 256; - - // - // used to record bytes of currently transfered data - // - WordCount = 0; - - while (WordCount < ByteCount / 2) { - // - // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. - // - Status = DRQReady2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Status = CheckErrorStatus (IdeDev); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Write data into device by one series of writing to data register - // - if ((WordCount + Increment) > ByteCount / 2) { - Increment = ByteCount / 2 - WordCount; - } - - IDEWritePortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - Increment, - Buffer16 - ); - - WordCount += Increment; - Buffer16 += Increment; - - } - return CheckErrorStatus (IdeDev); -} -/** - This function is called by the AtaBlkIoWriteBlocks() to perform - writing to media in block unit. The function has been enhanced to - support >120GB access and transfer at most 65536 blocks per command - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param DataBuffer A pointer to the source buffer for the data. - @param StartLba The starting logical block address to write to - on the device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status depends on the function DoAtaUdma() returns. -**/ -EFI_STATUS -AtaUdmaWriteExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ) -{ - return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp); -} - -/** - This function is called by the AtaBlkIoWriteBlocks() to perform - writing to media in block unit. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param DataBuffer A pointer to the source buffer for the data. - @param StartLba The starting logical block address to write to - on the device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status depends on the function DoAtaUdma() returns. -**/ -EFI_STATUS -AtaUdmaWrite ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ) -{ - return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp); -} -/** - This function is called by the AtaBlkIoWriteBlocks() to perform - writing onto media in block unit. The function has been enhanced to - support >120GB access and transfer at most 65536 blocks per command - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used - to record all the information of the IDE device. - @param DataBuffer A pointer to the source buffer for the data. - @param StartLba The starting logical block address to write onto the device - media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status is fully dependent on the return status of AtaPioDataOutExt() function. -**/ -EFI_STATUS -AtaWriteSectorsExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ) -{ - EFI_STATUS Status; - EFI_LBA Lba64; - UINTN BlocksRemaining; - UINT8 AtaCommand; - UINT16 SectorCount; - UINT32 ByteCount; - VOID *Buffer; - - // - // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol - // - AtaCommand = ATA_CMD_WRITE_SECTORS_EXT; - Lba64 = StartLba; - Buffer = DataBuffer; - BlocksRemaining = NumberOfBlocks; - - Status = EFI_SUCCESS; - - while (BlocksRemaining > 0) { - - if (BlocksRemaining >= 0x10000) { - // - // SectorCount is used to record the number of sectors to be written. - // Max 65536 sectors can be transfered at a time. - // - SectorCount = 0xffff; - } else { - SectorCount = (UINT16) BlocksRemaining; - } - - // - // ByteCount is the number of bytes that will be written - // - ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); - - // - // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command - // - Status = AtaPioDataOutExt ( - IdeDev, - Buffer, - ByteCount, - AtaCommand, - Lba64, - SectorCount - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Lba64 += SectorCount; - Buffer = ((UINT8 *) Buffer + ByteCount); - BlocksRemaining -= SectorCount; - } - - return Status; -} -/** - This function is the ATA implementation for WriteBlocks in the - Block I/O Protocol interface. - - @param IdeBlkIoDevice Indicates the calling context. - @param MediaId The media id that the write request is for. - @param Lba The starting logical block address to write onto the device. - @param BufferSize The size of the Buffer in bytes. This must be a multiple - of the intrinsic block size of the device. - @param Buffer A pointer to the source buffer for the data.The caller - is responsible for either having implicit or explicit - ownership of the memory that data is written from. - - @retval EFI_SUCCESS Write Blocks successfully. - @retval EFI_DEVICE_ERROR Write Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, - or the data buffer is not valid. - - @note If Write Block error because of device error, this function will call - AtaSoftReset() function to reset device. -**/ -EFI_STATUS -AtaBlkIoWriteBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - - EFI_BLOCK_IO_MEDIA *Media; - UINTN BlockSize; - UINTN NumberOfBlocks; - EFI_STATUS Status; - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - Status = EFI_SUCCESS; - - // - // Get the intrinsic block size - // - Media = IdeBlkIoDevice->BlkIo.Media; - BlockSize = Media->BlockSize; - NumberOfBlocks = BufferSize / BlockSize; - - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - // - // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism - // - if (IdeBlkIoDevice->UdmaMode.Valid) { - Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - } else { - Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - } - } else { - // - // For ATA-3 compatible device, use ATA-3 write block mechanism - // - if (IdeBlkIoDevice->UdmaMode.Valid) { - Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - } else { - Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - } - } - - if (EFI_ERROR (Status)) { - AtaSoftReset (IdeBlkIoDevice); - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} -/** - Enable Long Physical Sector Feature for ATA device. - - @param IdeDev The IDE device data - - @retval EFI_SUCCESS The ATA device supports Long Physical Sector feature - and corresponding fields in BlockIo structure is updated. - @retval EFI_UNSUPPORTED The device is not ATA device or Long Physical Sector - feature is not supported. -**/ -EFI_STATUS -AtaEnableLongPhysicalSector ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - EFI_ATA_IDENTIFY_DATA *AtaIdentifyData; - UINT16 PhyLogicSectorSupport; - - ASSERT (IdeDev->IdData != NULL); - // - // Only valid for ATA device - // - AtaIdentifyData = (EFI_ATA_IDENTIFY_DATA *) &IdeDev->IdData->AtaData; - if ((AtaIdentifyData->config & 0x8000) != 0) { - return EFI_UNSUPPORTED; - } - PhyLogicSectorSupport = AtaIdentifyData->phy_logic_sector_support; - // - // Check whether Long Physical Sector Feature is supported - // - if ((PhyLogicSectorSupport & 0xc000) == 0x4000) { - IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = 1; - IdeDev->BlkIo.Media->LowestAlignedLba = 0; - // - // Check whether one physical block contains multiple physical blocks - // - if ((PhyLogicSectorSupport & 0x2000) != 0) { - IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = - (UINT32) (1 << (PhyLogicSectorSupport & 0x000f)); - // - // Check lowest alignment of logical blocks within physical block - // - if ((AtaIdentifyData->alignment_logic_in_phy_blocks & 0xc000) == 0x4000) { - IdeDev->BlkIo.Media->LowestAlignedLba = - (EFI_LBA) ((IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock - ((UINT32)AtaIdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) % - IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock); - } - } - // - // Check logical block size - // - IdeDev->BlkIo.Media->BlockSize = 0x200; - if ((PhyLogicSectorSupport & 0x1000) != 0) { - IdeDev->BlkIo.Media->BlockSize = (UINT32) ( - ((AtaIdentifyData->logic_sector_size_hi << 16) | - AtaIdentifyData->logic_sector_size_lo) * sizeof (UINT16) - ); - } - return EFI_SUCCESS; - } else { - return EFI_UNSUPPORTED; - } -} -/** - Send ATA command into device with NON_DATA protocol - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaLow The value in LBA_LOW register - @param LbaMiddle The value in LBA_MIDDLE register - @param LbaHigh The value in LBA_HIGH register - - @retval EFI_SUCCESS Reading succeed - @retval EFI_ABORTED Command failed - @retval EFI_DEVICE_ERROR Device status error. - -**/ -EFI_STATUS -AtaNonDataCommandIn ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT8 Feature, - IN UINT8 SectorCount, - IN UINT8 LbaLow, - IN UINT8 LbaMiddle, - IN UINT8 LbaHigh - ) -{ - EFI_STATUS Status; - UINT8 StatusRegister; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device (bit4), set Lba mode(bit6) (use 0xe0 for compatibility) - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0) - ); - - // - // ATA commands for ATA device must be issued when DRDY is set - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Pass parameter into device register block - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - // - // Send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - // - // Wait for command completion - // For ATAPI_SMART_CMD, we may need more timeout to let device - // adjust internal states. - // - if (AtaCommand == ATA_CMD_SMART) { - Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT); - } else { - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - } - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { - // - // Failed to execute command, abort operation - // - return EFI_ABORTED; - } - - return EFI_SUCCESS; -} - -/** - Send ATA Ext command into device with NON_DATA protocol - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaAddress The LBA address in 48-bit mode - - @retval EFI_SUCCESS Reading succeed - @retval EFI_ABORTED Command failed - @retval EFI_DEVICE_ERROR Device status error. - -**/ -EFI_STATUS -AtaNonDataCommandInExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ) -{ - EFI_STATUS Status; - UINT8 StatusRegister; - UINT8 SectorCount8; - UINT8 Feature8; - UINT8 LbaLow; - UINT8 LbaMid; - UINT8 LbaHigh; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0) - ); - - // - // ATA commands for ATA device must be issued when DRDY is set - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Pass parameter into device register block - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - - // - // Fill the feature register, which is a two-byte FIFO. Need write twice. - // - Feature8 = (UINT8) (Feature >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - - Feature8 = (UINT8) Feature; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) (SectorCount >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - // - // Fill the start LBA registers, which are also two-byte FIFO - // - LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); - LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); - LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - LbaLow = (UINT8) LbaAddress; - LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); - LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - // - // Send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - // - // Wait for command completion - // - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { - // - // Failed to execute command, abort operation - // - return EFI_ABORTED; - } - - return EFI_SUCCESS; -} - - - diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c deleted file mode 100644 index 1a3cb2e0a0..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c +++ /dev/null @@ -1,1952 +0,0 @@ -/** @file - This file contains all helper functions on the ATAPI command - - Copyright (c) 2006 - 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 "IdeBus.h" - -/** - This function is used to get the current status of the media residing - in the LS-120 drive or ZIP drive. The media status is returned in the - Error Status. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS The media status is achieved successfully and the media - can be read/written. - @retval EFI_DEVICE_ERROR Get Media Status Command is failed. - @retval EFI_NO_MEDIA There is no media in the drive. - @retval EFI_WRITE_PROTECTED The media is writing protected. - - @note This function must be called after the LS120EnableMediaStatus() - with second parameter set to TRUE - (means enable media status notification) is called. -**/ -EFI_STATUS -LS120GetMediaStatus ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - UINT8 DeviceSelect; - UINT8 StatusValue; - EFI_STATUS EfiStatus; - // - // Poll Alternate Register for BSY clear within timeout. - // - EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (EfiStatus)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device via Device/Head Register. - // - DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); - - // - // Poll Alternate Register for DRDY set within timeout. - // After device is selected, DRDY set indicates the device is ready to - // accept command. - // - EfiStatus = DRDYReady2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (EfiStatus)) { - return EFI_DEVICE_ERROR; - } - - // - // Get Media Status Command is sent - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xDA); - - // - // BSY bit will clear after command is complete. - // - EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (EfiStatus)) { - return EFI_DEVICE_ERROR; - } - - // - // the media status is returned by the command in the ERROR register - // - StatusValue = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - - if ((StatusValue & BIT1) != 0) { - return EFI_NO_MEDIA; - } - - if ((StatusValue & BIT6) != 0) { - return EFI_WRITE_PROTECTED; - } else { - return EFI_SUCCESS; - } -} -/** - This function is used to send Enable Media Status Notification Command - or Disable Media Status Notification Command. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param Enable a flag that indicates whether enable or disable media - status notification. - @retval EFI_SUCCESS If command completes successfully. - @retval EFI_DEVICE_ERROR If command failed. -**/ -EFI_STATUS -LS120EnableMediaStatus ( - IN IDE_BLK_IO_DEV *IdeDev, - IN BOOLEAN Enable - ) -{ - UINT8 DeviceSelect; - EFI_STATUS Status; - - // - // Poll Alternate Register for BSY clear within timeout. - // - Status = WaitForBSYClear2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device via Device/Head Register. - // - DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); - - // - // Poll Alternate Register for DRDY set within timeout. - // After device is selected, DRDY set indicates the device is ready to - // accept command. - // - Status = DRDYReady2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - if (Enable) { - // - // 0x95: Enable media status notification - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x95); - } else { - // - // 0x31: Disable media status notification - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x31); - } - // - // Set Feature Command is sent - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xEF); - - // - // BSY bit will clear after command is complete. - // - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} -/** - This function reads the pending data in the device. - - @param IdeDev Indicates the calling context. - - @retval EFI_SUCCESS Successfully read. - @retval EFI_NOT_READY The BSY is set avoiding reading. - -**/ -EFI_STATUS -AtapiReadPendingData ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - UINT8 AltRegister; - UINT16 TempWordBuffer; - - AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); - if ((AltRegister & ATA_STSREG_BSY) == ATA_STSREG_BSY) { - return EFI_NOT_READY; - } - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { - TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus); - while ((TempWordBuffer & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { - IDEReadPortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - 1, - &TempWordBuffer - ); - TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus); - } - } - return EFI_SUCCESS; -} - -/** - This function is called by either AtapiPacketCommandIn() or AtapiPacketCommandOut(). - It is used to transfer data between host and device. The data direction is specified - by the fourth parameter. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param Buffer buffer contained data transferred between host and device. - @param ByteCount data size in byte unit of the buffer. - @param Read flag used to determine the data transfer direction. - Read equals 1, means data transferred from device to host; - Read equals 0, means data transferred from host to device. - @param TimeOut timeout value for wait DRQ ready before each data stream's transfer. - - @retval EFI_SUCCESS data is transferred successfully. - @retval EFI_DEVICE_ERROR the device failed to transfer data. -**/ -EFI_STATUS -PioReadWriteData ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT16 *Buffer, - IN UINT32 ByteCount, - IN BOOLEAN Read, - IN UINTN TimeOut - ) -{ - // - // required transfer data in word unit. - // - UINT32 RequiredWordCount; - - // - // actual transfer data in word unit. - // - UINT32 ActualWordCount; - UINT32 WordCount; - EFI_STATUS Status; - UINT16 *PtrBuffer; - - // - // No data transfer is premitted. - // - if (ByteCount == 0) { - return EFI_SUCCESS; - } - // - // for performance, we assert the ByteCount is an even number - // which is actually a resonable assumption - ASSERT((ByteCount%2) == 0); - - PtrBuffer = Buffer; - RequiredWordCount = ByteCount / 2; - // - // ActuralWordCount means the word count of data really transferred. - // - ActualWordCount = 0; - - while (ActualWordCount < RequiredWordCount) { - - // - // before each data transfer stream, the host should poll DRQ bit ready, - // to see whether indicates device is ready to transfer data. - // - Status = DRQReady2 (IdeDev, TimeOut); - if (EFI_ERROR (Status)) { - return CheckErrorStatus (IdeDev); - } - - // - // read Status Register will clear interrupt - // - IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - - // - // get current data transfer size from Cylinder Registers. - // - WordCount = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8; - WordCount = WordCount | IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); - WordCount = WordCount & 0xffff; - WordCount /= 2; - - WordCount = MIN (WordCount, (RequiredWordCount - ActualWordCount)); - - if (Read) { - IDEReadPortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - WordCount, - PtrBuffer - ); - } else { - IDEWritePortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - WordCount, - PtrBuffer - ); - } - - PtrBuffer += WordCount; - ActualWordCount += WordCount; - } - - if (Read) { - // - // In the case where the drive wants to send more data than we need to read, - // the DRQ bit will be set and cause delays from DRQClear2(). - // We need to read data from the drive until it clears DRQ so we can move on. - // - AtapiReadPendingData (IdeDev); - } - - // - // After data transfer is completed, normally, DRQ bit should clear. - // - Status = DRQClear2 (IdeDev, ATAPITIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // read status register to check whether error happens. - // - return CheckErrorStatus (IdeDev); -} - -/** - This function is used to send out ATAPI commands conforms to the Packet Command - with PIO Data In Protocol. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure - which contains the contents of the command. - @param Buffer buffer contained data transferred from device to host. - @param ByteCount data size in byte unit of the buffer. - @param TimeOut this parameter is used to specify the timeout value for the - PioReadWriteData() function. - - @retval EFI_SUCCESS send out the ATAPI packet command successfully - and device sends data successfully. - @retval EFI_DEVICE_ERROR the device failed to send data. - -**/ -EFI_STATUS -AtapiPacketCommandIn ( - IN IDE_BLK_IO_DEV *IdeDev, - IN ATAPI_PACKET_COMMAND *Packet, - IN UINT16 *Buffer, - IN UINT32 ByteCount, - IN UINTN TimeOut - ) -{ - UINT16 *CommandIndex; - EFI_STATUS Status; - UINT32 Count; - - // - // Set all the command parameters by fill related registers. - // Before write to all the following registers, BSY and DRQ must be 0. - // - Status = DRQClear2 (IdeDev, ATAPITIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Select device via Device/Head Register. - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | ATA_DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000) - ); - - // - // No OVL; No DMA - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00); - - // - // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device - // determine how many data should be transferred. - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->CylinderLsb, - (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff) - ); - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->CylinderMsb, - (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8) - ); - - // - // ATA_DEFAULT_CTL:0x0a (0000,1010) - // Disable interrupt - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, ATA_DEFAULT_CTL); - - // - // Send Packet command to inform device - // that the following data bytes are command packet. - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, ATA_CMD_PACKET); - - Status = DRQReady (IdeDev, ATAPITIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Send out command packet - // - CommandIndex = Packet->Data16; - for (Count = 0; Count < 6; Count++, CommandIndex++) { - - IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex); - gBS->Stall (10); - } - - // - // call PioReadWriteData() function to get - // requested transfer data form device. - // - return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut); -} -/** - This function is used to send out ATAPI commands conforms to the Packet Command - with PIO Data Out Protocol. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure - which contains the contents of the command. - @param Buffer buffer contained data transferred from host to device. - @param ByteCount data size in byte unit of the buffer. - @param TimeOut this parameter is used to specify the timeout value - for the PioReadWriteData() function. - @retval EFI_SUCCESS send out the ATAPI packet command successfully - and device received data successfully. - @retval EFI_DEVICE_ERROR the device failed to send data. - -**/ -EFI_STATUS -AtapiPacketCommandOut ( - IN IDE_BLK_IO_DEV *IdeDev, - IN ATAPI_PACKET_COMMAND *Packet, - IN UINT16 *Buffer, - IN UINT32 ByteCount, - IN UINTN TimeOut - ) -{ - UINT16 *CommandIndex; - EFI_STATUS Status; - UINT32 Count; - - // - // set all the command parameters - // Before write to all the following registers, BSY and DRQ must be 0. - // - Status = DRQClear2 (IdeDev, ATAPITIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Select device via Device/Head Register. - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | ATA_DEFAULT_CMD) // ATA_DEFAULT_CMD: 0xa0 (1010,0000) - ); - - // - // No OVL; No DMA - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00); - - // - // set the transfersize to ATAPI_MAX_BYTE_COUNT to - // let the device determine how many data should be transferred. - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->CylinderLsb, - (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff) - ); - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->CylinderMsb, - (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8) - ); - - // - // DEFAULT_CTL:0x0a (0000,1010) - // Disable interrupt - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, ATA_DEFAULT_CTL); - - // - // Send Packet command to inform device - // that the following data bytes are command packet. - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, ATA_CMD_PACKET); - - Status = DRQReady2 (IdeDev, ATAPITIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Send out command packet - // - CommandIndex = Packet->Data16; - for (Count = 0; Count < 6; Count++, CommandIndex++) { - IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex); - gBS->Stall (10); - } - - // - // call PioReadWriteData() function to send requested transfer data to device. - // - return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut); -} -/** - Sends out ATAPI Inquiry Packet Command to the specified device. This command will - return INQUIRY data of the device. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS Inquiry command completes successfully. - @retval EFI_DEVICE_ERROR Inquiry command failed. - - @note Parameter "IdeDev" will be updated in this function. - -**/ -EFI_STATUS -AtapiInquiry ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - ATAPI_PACKET_COMMAND Packet; - EFI_STATUS Status; - ATAPI_INQUIRY_DATA *InquiryData; - - // - // prepare command packet for the ATAPI Inquiry Packet Command. - // - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Packet.Inquiry.opcode = ATA_CMD_INQUIRY; - Packet.Inquiry.page_code = 0; - Packet.Inquiry.allocation_length = (UINT8) sizeof (ATAPI_INQUIRY_DATA); - - InquiryData = AllocatePool (sizeof (ATAPI_INQUIRY_DATA)); - if (InquiryData == NULL) { - return EFI_DEVICE_ERROR; - } - - // - // Send command packet and get requested Inquiry data. - // - Status = AtapiPacketCommandIn ( - IdeDev, - &Packet, - (UINT16 *) InquiryData, - sizeof (ATAPI_INQUIRY_DATA), - ATAPITIMEOUT - ); - if (EFI_ERROR (Status)) { - gBS->FreePool (InquiryData); - return EFI_DEVICE_ERROR; - } - - IdeDev->InquiryData = InquiryData; - - return EFI_SUCCESS; -} -/** - This function is called by DiscoverIdeDevice() during its device - identification. - Its main purpose is to get enough information for the device media - to fill in the Media data structure of the Block I/O Protocol interface. - - There are 5 steps to reach such objective: - 1. Sends out the ATAPI Identify Command to the specified device. - Only ATAPI device responses to this command. If the command succeeds, - it returns the Identify data structure which filled with information - about the device. Since the ATAPI device contains removable media, - the only meaningful information is the device module name. - 2. Sends out ATAPI Inquiry Packet Command to the specified device. - This command will return inquiry data of the device, which contains - the device type information. - 3. Allocate sense data space for future use. We don't detect the media - presence here to improvement boot performance, especially when CD - media is present. The media detection will be performed just before - each BLK_IO read/write - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS Identify ATAPI device successfully. - @retval EFI_DEVICE_ERROR ATAPI Identify Device Command failed or device type - is not supported by this IDE driver. - @retval EFI_OUT_OF_RESOURCES Allocate memory for sense data failed - - @note Parameter "IdeDev" will be updated in this function. -**/ -EFI_STATUS -ATAPIIdentify ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - EFI_IDENTIFY_DATA *AtapiIdentifyPointer; - UINT8 DeviceSelect; - EFI_STATUS Status; - - // - // device select bit - // - DeviceSelect = (UINT8) ((IdeDev->Device) << 4); - - AtapiIdentifyPointer = AllocatePool (sizeof (EFI_IDENTIFY_DATA)); - if (AtapiIdentifyPointer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // Send ATAPI Identify Command to get IDENTIFY data. - // - Status = AtaPioDataIn ( - IdeDev, - (VOID *) AtapiIdentifyPointer, - sizeof (EFI_IDENTIFY_DATA), - ATA_CMD_IDENTIFY_DEVICE, - DeviceSelect, - 0, - 0, - 0, - 0 - ); - - if (EFI_ERROR (Status)) { - gBS->FreePool (AtapiIdentifyPointer); - return EFI_DEVICE_ERROR; - } - - IdeDev->IdData = AtapiIdentifyPointer; - PrintAtaModuleName (IdeDev); - - // - // Send ATAPI Inquiry Packet Command to get INQUIRY data. - // - Status = AtapiInquiry (IdeDev); - if (EFI_ERROR (Status)) { - gBS->FreePool (IdeDev->IdData); - // - // Make sure the pIdData will not be freed again. - // - IdeDev->IdData = NULL; - return EFI_DEVICE_ERROR; - } - // - // Get media removable info from INQUIRY data. - // - IdeDev->BlkIo.Media->RemovableMedia = (UINT8) ((IdeDev->InquiryData->RMB & 0x80) == 0x80); - - // - // Identify device type via INQUIRY data. - // - switch (IdeDev->InquiryData->peripheral_type & 0x1f) { - - // - // Magnetic Disk - // - case 0x00: - - // - // device is LS120 or ZIP drive. - // - IdeDev->Type = IdeMagnetic; - - IdeDev->BlkIo.Media->MediaId = 0; - // - // Give initial value - // - IdeDev->BlkIo.Media->MediaPresent = FALSE; - - IdeDev->BlkIo.Media->LastBlock = 0; - IdeDev->BlkIo.Media->BlockSize = 0x200; - break; - - // - // CD-ROM - // - case 0x05: - - IdeDev->Type = IdeCdRom; - IdeDev->BlkIo.Media->MediaId = 0; - // - // Give initial value - // - IdeDev->BlkIo.Media->MediaPresent = FALSE; - - IdeDev->BlkIo.Media->LastBlock = 0; - IdeDev->BlkIo.Media->BlockSize = 0x800; - IdeDev->BlkIo.Media->ReadOnly = TRUE; - break; - - // - // Tape - // - case 0x01: - - // - // WORM - // - case 0x04: - - // - // Optical - // - case 0x07: - - default: - IdeDev->Type = IdeUnknown; - gBS->FreePool (IdeDev->IdData); - gBS->FreePool (IdeDev->InquiryData); - // - // Make sure the pIdData and pInquiryData will not be freed again. - // - IdeDev->IdData = NULL; - IdeDev->InquiryData = NULL; - return EFI_DEVICE_ERROR; - } - - // - // original sense data numbers - // - IdeDev->SenseDataNumber = 20; - - IdeDev->SenseData = AllocatePool (IdeDev->SenseDataNumber * sizeof (ATAPI_REQUEST_SENSE_DATA)); - if (IdeDev->SenseData == NULL) { - gBS->FreePool (IdeDev->IdData); - gBS->FreePool (IdeDev->InquiryData); - // - // Make sure the pIdData and pInquiryData will not be freed again. - // - IdeDev->IdData = NULL; - IdeDev->InquiryData = NULL; - return EFI_OUT_OF_RESOURCES; - } - - return EFI_SUCCESS; -} -/** - Sends out ATAPI Request Sense Packet Command to the specified device. This command - will return all the current Sense data in the device. This function will pack - all the Sense data in one single buffer. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param SenseCounts allocated in this function, and freed by the calling function. - This buffer is used to accommodate all the sense data returned - by the device. - - @retval EFI_SUCCESS Request Sense command completes successfully. - @retval EFI_DEVICE_ERROR Request Sense command failed. -**/ -EFI_STATUS -AtapiRequestSense ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT UINTN *SenseCounts - ) -{ - EFI_STATUS Status; - ATAPI_REQUEST_SENSE_DATA *Sense; - UINT16 *Ptr; - BOOLEAN FetchSenseData; - ATAPI_PACKET_COMMAND Packet; - - *SenseCounts = 0; - - ZeroMem (IdeDev->SenseData, sizeof (ATAPI_REQUEST_SENSE_DATA) * (IdeDev->SenseDataNumber)); - // - // fill command packet for Request Sense Packet Command - // - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Packet.RequestSence.opcode = ATA_CMD_REQUEST_SENSE; - Packet.RequestSence.allocation_length = (UINT8) sizeof (ATAPI_REQUEST_SENSE_DATA); - - // - // initialize pointer - // - Ptr = (UINT16 *) IdeDev->SenseData; - // - // request sense data from device continuously until no sense data - // exists in the device. - // - for (FetchSenseData = TRUE; FetchSenseData;) { - - Sense = (ATAPI_REQUEST_SENSE_DATA *) Ptr; - - // - // send out Request Sense Packet Command and get one Sense data form device - // - Status = AtapiPacketCommandIn ( - IdeDev, - &Packet, - Ptr, - sizeof (ATAPI_REQUEST_SENSE_DATA), - ATAPITIMEOUT - ); - // - // failed to get Sense data - // - if (EFI_ERROR (Status)) { - if (*SenseCounts == 0) { - return EFI_DEVICE_ERROR; - } else { - return EFI_SUCCESS; - } - } - - (*SenseCounts)++; - // - // We limit MAX sense data count to 20 in order to avoid dead loop. Some - // incompatible ATAPI devices don't retrive NO_SENSE when there is no media. - // In this case, dead loop occurs if we don't have a gatekeeper. 20 is - // supposed to be large enough for any ATAPI device. - // - if ((Sense->sense_key != ATA_SK_NO_SENSE) && ((*SenseCounts) < 20)) { - // - // Ptr is word-based pointer - // - Ptr += (sizeof (ATAPI_REQUEST_SENSE_DATA) + 1) >> 1; - - } else { - // - // when no sense key, skip out the loop - // - FetchSenseData = FALSE; - } - } - - return EFI_SUCCESS; -} -/** - This function is used to parse sense data. Only the first sense data is honoured - - @param IdeDev Indicates the calling context. - @param SenseCount Count of sense data. - @param Result The parsed result. - - @retval EFI_SUCCESS Successfully parsed. - @retval EFI_INVALID_PARAMETER Count of sense data is zero. - -**/ -EFI_STATUS -ParseSenseData ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN SenseCount, - OUT SENSE_RESULT *Result - ) -{ - ATAPI_REQUEST_SENSE_DATA *SenseData; - - if (SenseCount == 0) { - return EFI_INVALID_PARAMETER; - } - - // - // Only use the first sense data - // - SenseData = IdeDev->SenseData; - *Result = SenseOtherSense; - - switch (SenseData->sense_key) { - case ATA_SK_NO_SENSE: - *Result = SenseNoSenseKey; - break; - case ATA_SK_NOT_READY: - switch (SenseData->addnl_sense_code) { - case ATA_ASC_NO_MEDIA: - *Result = SenseNoMedia; - break; - case ATA_ASC_MEDIA_UPSIDE_DOWN: - *Result = SenseMediaError; - break; - case ATA_ASC_NOT_READY: - if (SenseData->addnl_sense_code_qualifier == ATA_ASCQ_IN_PROGRESS) { - *Result = SenseDeviceNotReadyNeedRetry; - } else { - *Result = SenseDeviceNotReadyNoRetry; - } - break; - } - break; - case ATA_SK_UNIT_ATTENTION: - if (SenseData->addnl_sense_code == ATA_ASC_MEDIA_CHANGE) { - *Result = SenseMediaChange; - } - break; - case ATA_SK_MEDIUM_ERROR: - switch (SenseData->addnl_sense_code) { - case ATA_ASC_MEDIA_ERR1: - case ATA_ASC_MEDIA_ERR2: - case ATA_ASC_MEDIA_ERR3: - case ATA_ASC_MEDIA_ERR4: - *Result = SenseMediaError; - break; - } - break; - default: - break; - } - - return EFI_SUCCESS; -} - -/** - Sends out ATAPI Test Unit Ready Packet Command to the specified device - to find out whether device is accessible. - - @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param SResult Sense result for this packet command. - - @retval EFI_SUCCESS Device is accessible. - @retval EFI_DEVICE_ERROR Device is not accessible. - -**/ -EFI_STATUS -AtapiTestUnitReady ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT SENSE_RESULT *SResult - ) -{ - ATAPI_PACKET_COMMAND Packet; - EFI_STATUS Status; - UINTN SenseCount; - - // - // fill command packet - // - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY; - - // - // send command packet - // - Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = AtapiRequestSense (IdeDev, &SenseCount); - if (EFI_ERROR (Status)) { - return Status; - } - - ParseSenseData (IdeDev, SenseCount, SResult); - return EFI_SUCCESS; -} - - -/** - Sends out ATAPI Read Capacity Packet Command to the specified device. - This command will return the information regarding the capacity of the - media in the device. - - Current device status will impact device's response to the Read Capacity - Command. For example, if the device once reset, the Read Capacity - Command will fail. The Sense data record the current device status, so - if the Read Capacity Command failed, the Sense data must be requested - and be analyzed to determine if the Read Capacity Command should retry. - - @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param SResult Sense result for this packet command - - @retval EFI_SUCCESS Read Capacity Command finally completes successfully. - @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error. - @retval EFI_NOT_READY Operation succeeds but returned capacity is 0 - - @note Parameter "IdeDev" will be updated in this function. - - -**/ -EFI_STATUS -AtapiReadCapacity ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT SENSE_RESULT *SResult - ) -{ - // - // status returned by Read Capacity Packet Command - // - EFI_STATUS Status; - EFI_STATUS SenseStatus; - ATAPI_PACKET_COMMAND Packet; - UINTN SenseCount; - - // - // used for capacity data returned from ATAPI device - // - ATAPI_READ_CAPACITY_DATA Data; - ATAPI_READ_FORMAT_CAPACITY_DATA FormatData; - - ZeroMem (&Data, sizeof (Data)); - ZeroMem (&FormatData, sizeof (FormatData)); - - if (IdeDev->Type == IdeCdRom) { - - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Packet.Inquiry.opcode = ATA_CMD_READ_CAPACITY; - Status = AtapiPacketCommandIn ( - IdeDev, - &Packet, - (UINT16 *) &Data, - sizeof (ATAPI_READ_CAPACITY_DATA), - ATAPITIMEOUT - ); - - } else { - // - // Type == IdeMagnetic - // - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Packet.ReadFormatCapacity.opcode = ATA_CMD_READ_FORMAT_CAPACITY; - Packet.ReadFormatCapacity.allocation_length_lo = 12; - Status = AtapiPacketCommandIn ( - IdeDev, - &Packet, - (UINT16 *) &FormatData, - sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA), - ATAPITIMEOUT - ); - } - - if (Status == EFI_TIMEOUT) { - return Status; - } - - SenseStatus = AtapiRequestSense (IdeDev, &SenseCount); - - if (!EFI_ERROR (SenseStatus)) { - ParseSenseData (IdeDev, SenseCount, SResult); - - if (!EFI_ERROR (Status) && *SResult == SenseNoSenseKey) { - if (IdeDev->Type == IdeCdRom) { - - IdeDev->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) | - (Data.LastLba2 << 16) | - (Data.LastLba1 << 8) | - Data.LastLba0; - - IdeDev->BlkIo.Media->MediaPresent = TRUE; - - IdeDev->BlkIo.Media->ReadOnly = TRUE; - - // - // Because the user data portion in the sector of the Data CD supported - // is always 0x800 - // - IdeDev->BlkIo.Media->BlockSize = 0x800; - } - - if (IdeDev->Type == IdeMagnetic) { - - if (FormatData.DesCode == 3) { - IdeDev->BlkIo.Media->MediaPresent = FALSE; - IdeDev->BlkIo.Media->LastBlock = 0; - } else { - - IdeDev->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) | - (FormatData.LastLba2 << 16) | - (FormatData.LastLba1 << 8) | - FormatData.LastLba0; - if (IdeDev->BlkIo.Media->LastBlock != 0) { - IdeDev->BlkIo.Media->LastBlock--; - - IdeDev->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) | - (FormatData.BlockSize1 << 8) | - FormatData.BlockSize0; - - IdeDev->BlkIo.Media->MediaPresent = TRUE; - } else { - IdeDev->BlkIo.Media->MediaPresent = FALSE; - // - // Return EFI_NOT_READY operation succeeds but returned capacity is 0 - // - return EFI_NOT_READY; - } - - IdeDev->BlkIo.Media->BlockSize = 0x200; - - } - } - } - - return EFI_SUCCESS; - - } else { - return EFI_DEVICE_ERROR; - } -} -/** - This function is used to test the current media write-protected or not residing - in the LS-120 drive or ZIP drive. - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param WriteProtected if True, current media is write protected. - if FALSE, current media is writable - - @retval EFI_SUCCESS The media write-protected status is achieved successfully - @retval EFI_DEVICE_ERROR Get Media Status Command is failed. -**/ -EFI_STATUS -IsLS120orZipWriteProtected ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT BOOLEAN *WriteProtected - ) -{ - EFI_STATUS Status; - - *WriteProtected = FALSE; - - Status = LS120EnableMediaStatus (IdeDev, TRUE); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // the Get Media Status Command is only valid - // if a Set Features/Enable Media Status Command has been priviously issued. - // - if (LS120GetMediaStatus (IdeDev) == EFI_WRITE_PROTECTED) { - - *WriteProtected = TRUE; - } else { - - *WriteProtected = FALSE; - } - - // - // After Get Media Status Command completes, - // Set Features/Disable Media Command should be sent. - // - Status = LS120EnableMediaStatus (IdeDev, FALSE); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Used before read/write blocks from/to ATAPI device media. Since ATAPI device - media is removable, it is necessary to detect whether media is present and - get current present media's information, and if media has been changed, Block - I/O Protocol need to be reinstalled. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param MediaChange return value that indicates if the media of the device has been - changed. - - @retval EFI_SUCCESS media found successfully. - @retval EFI_DEVICE_ERROR any error encounters during media detection. - @retval EFI_NO_MEDIA media not found. - - @note - parameter IdeDev may be updated in this function. - -**/ -EFI_STATUS -AtapiDetectMedia ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT BOOLEAN *MediaChange - ) -{ - EFI_STATUS Status; - EFI_STATUS CleanStateStatus; - EFI_BLOCK_IO_MEDIA OldMediaInfo; - UINTN RetryTimes; - UINTN RetryNotReady; - SENSE_RESULT SResult; - BOOLEAN WriteProtected; - - CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (EFI_BLOCK_IO_MEDIA)); - *MediaChange = FALSE; - // - // Retry for SenseDeviceNotReadyNeedRetry. - // Each retry takes 1s and we limit the upper boundary to - // 120 times about 2 min. - // - RetryNotReady = 120; - - // - // Do Test Unit Ready - // - DoTUR: - // - // Retry 5 times - // - RetryTimes = 5; - while (RetryTimes != 0) { - - Status = AtapiTestUnitReady (IdeDev, &SResult); - - if (EFI_ERROR (Status)) { - // - // Test Unit Ready error without sense data. - // For some devices, this means there's extra data - // that has not been read, so we read these extra - // data out before going on. - // - CleanStateStatus = AtapiReadPendingData (IdeDev); - if (EFI_ERROR (CleanStateStatus)) { - // - // Busy wait failed, try again - // - RetryTimes--; - } - // - // Try again without counting down RetryTimes - // - continue; - } else { - switch (SResult) { - case SenseNoSenseKey: - if (IdeDev->BlkIo.Media->MediaPresent) { - goto Done; - } else { - // - // Media present but the internal structure need refreshed. - // Try Read Capacity - // - goto DoRC; - } - break; - - case SenseDeviceNotReadyNeedRetry: - if (--RetryNotReady == 0) { - return EFI_DEVICE_ERROR; - } - gBS->Stall (1000 * STALL_1_MILLI_SECOND); - continue; - break; - - case SenseNoMedia: - IdeDev->BlkIo.Media->MediaPresent = FALSE; - IdeDev->BlkIo.Media->LastBlock = 0; - goto Done; - break; - - case SenseDeviceNotReadyNoRetry: - case SenseMediaError: - return EFI_DEVICE_ERROR; - - case SenseMediaChange: - IdeDev->BlkIo.Media->MediaId++; - goto DoRC; - break; - - default: - RetryTimes--; - break; - } - } - } - - return EFI_DEVICE_ERROR; - - // - // Do Read Capacity - // - DoRC: - RetryTimes = 5; - - while (RetryTimes != 0) { - - Status = AtapiReadCapacity (IdeDev, &SResult); - - if (EFI_ERROR (Status)) { - RetryTimes--; - continue; - } else { - switch (SResult) { - case SenseNoSenseKey: - goto Done; - break; - - case SenseDeviceNotReadyNeedRetry: - // - // We use Test Unit Ready to retry which - // is faster. - // - goto DoTUR; - break; - - case SenseNoMedia: - IdeDev->BlkIo.Media->MediaPresent = FALSE; - IdeDev->BlkIo.Media->LastBlock = 0; - goto Done; - break; - - case SenseDeviceNotReadyNoRetry: - case SenseMediaError: - return EFI_DEVICE_ERROR; - - case SenseMediaChange: - IdeDev->BlkIo.Media->MediaId++; - continue; - break; - - default: - RetryTimes--; - break; - } - } - } - - return EFI_DEVICE_ERROR; - - Done: - // - // the following code is to check the write-protected for LS120 media - // - if ((IdeDev->BlkIo.Media->MediaPresent) && (IdeDev->Type == IdeMagnetic)) { - - Status = IsLS120orZipWriteProtected (IdeDev, &WriteProtected); - if (!EFI_ERROR (Status)) { - - if (WriteProtected) { - - IdeDev->BlkIo.Media->ReadOnly = TRUE; - } else { - - IdeDev->BlkIo.Media->ReadOnly = FALSE; - } - - } - } - - if (IdeDev->BlkIo.Media->MediaId != OldMediaInfo.MediaId) { - // - // Media change information got from the device - // - *MediaChange = TRUE; - } - - if (IdeDev->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) { - *MediaChange = TRUE; - IdeDev->BlkIo.Media->MediaId += 1; - } - - if (IdeDev->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) { - *MediaChange = TRUE; - IdeDev->BlkIo.Media->MediaId += 1; - } - - if (IdeDev->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) { - *MediaChange = TRUE; - IdeDev->BlkIo.Media->MediaId += 1; - } - - if (IdeDev->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) { - if (IdeDev->BlkIo.Media->MediaPresent) { - // - // when change from no media to media present, reset the MediaId to 1. - // - IdeDev->BlkIo.Media->MediaId = 1; - } else { - // - // when no media, reset the MediaId to zero. - // - IdeDev->BlkIo.Media->MediaId = 0; - } - - *MediaChange = TRUE; - } - - // - // if any change on current existing media, - // the Block I/O protocol need to be reinstalled. - // - if (*MediaChange) { - gBS->ReinstallProtocolInterface ( - IdeDev->Handle, - &gEfiBlockIoProtocolGuid, - &IdeDev->BlkIo, - &IdeDev->BlkIo - ); - } - - if (IdeDev->BlkIo.Media->MediaPresent) { - return EFI_SUCCESS; - } else { - return EFI_NO_MEDIA; - } -} - -/** - This function is called by the AtapiBlkIoReadBlocks() to perform - read from media in block unit. - - The main command used to access media here is READ(10) Command. - READ(10) Command requests that the ATAPI device media transfer - specified data to the host. Data is transferred in block(sector) - unit. The maximum number of blocks that can be transferred once is - 65536. This is the main difference between READ(10) and READ(12) - Command. The maximum number of blocks in READ(12) is 2 power 32. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param Buffer A pointer to the destination buffer for the data. - @param Lba The starting logical block address to read from on the - device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status is fully dependent on the return status of AtapiPacketCommandIn() function. - -**/ -EFI_STATUS -AtapiReadSectors ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ) -{ - - ATAPI_PACKET_COMMAND Packet; - ATAPI_READ10_CMD *Read10Packet; - EFI_STATUS Status; - UINTN BlocksRemaining; - UINT32 Lba32; - UINT32 BlockSize; - UINT32 ByteCount; - UINT16 SectorCount; - VOID *PtrBuffer; - UINT16 MaxBlock; - UINTN TimeOut; - - // - // fill command packet for Read(10) command - // - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Read10Packet = &Packet.Read10; - Lba32 = (UINT32) Lba; - PtrBuffer = Buffer; - - BlockSize = IdeDev->BlkIo.Media->BlockSize; - - // - // limit the data bytes that can be transferred by one Read(10) Command - // - MaxBlock = 65535; - - BlocksRemaining = NumberOfBlocks; - - Status = EFI_SUCCESS; - while (BlocksRemaining > 0) { - - if (BlocksRemaining <= MaxBlock) { - - SectorCount = (UINT16) BlocksRemaining; - } else { - - SectorCount = MaxBlock; - } - - // - // fill the Packet data structure - // - - Read10Packet->opcode = ATA_CMD_READ_10; - - // - // Lba0 ~ Lba3 specify the start logical block address of the data transfer. - // Lba0 is MSB, Lba3 is LSB - // - Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff); - Read10Packet->Lba2 = (UINT8) (Lba32 >> 8); - Read10Packet->Lba1 = (UINT8) (Lba32 >> 16); - Read10Packet->Lba0 = (UINT8) (Lba32 >> 24); - - // - // TranLen0 ~ TranLen1 specify the transfer length in block unit. - // TranLen0 is MSB, TranLen is LSB - // - Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff); - Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8); - - ByteCount = SectorCount * BlockSize; - - if (IdeDev->Type == IdeCdRom) { - TimeOut = CDROMLONGTIMEOUT; - } else { - TimeOut = ATAPILONGTIMEOUT; - } - - Status = AtapiPacketCommandIn ( - IdeDev, - &Packet, - (UINT16 *) PtrBuffer, - ByteCount, - TimeOut - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Lba32 += SectorCount; - PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize; - BlocksRemaining -= SectorCount; - } - - return Status; -} - -/** - This function is called by the AtapiBlkIoWriteBlocks() to perform - write onto media in block unit. - The main command used to access media here is Write(10) Command. - Write(10) Command requests that the ATAPI device media transfer - specified data to the host. Data is transferred in block (sector) - unit. The maximum number of blocks that can be transferred once is - 65536. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param Buffer A pointer to the source buffer for the data. - @param Lba The starting logical block address to write onto - the device media. - @param NumberOfBlocks The number of transfer data blocks. - - @return status is fully dependent on the return status of AtapiPacketCommandOut() function. - -**/ -EFI_STATUS -AtapiWriteSectors ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ) -{ - - ATAPI_PACKET_COMMAND Packet; - ATAPI_READ10_CMD *Read10Packet; - - EFI_STATUS Status; - UINTN BlocksRemaining; - UINT32 Lba32; - UINT32 BlockSize; - UINT32 ByteCount; - UINT16 SectorCount; - VOID *PtrBuffer; - UINT16 MaxBlock; - - // - // fill command packet for Write(10) command - // Write(10) command packet has the same data structure as - // Read(10) command packet, - // so here use the Read10Packet data structure - // for the Write(10) command packet. - // - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Read10Packet = &Packet.Read10; - - Lba32 = (UINT32) Lba; - PtrBuffer = Buffer; - - BlockSize = IdeDev->BlkIo.Media->BlockSize; - - // - // limit the data bytes that can be transferred by one Read(10) Command - // - MaxBlock = (UINT16) (65536 / BlockSize); - - BlocksRemaining = NumberOfBlocks; - - Status = EFI_SUCCESS; - while (BlocksRemaining > 0) { - - if (BlocksRemaining >= MaxBlock) { - SectorCount = MaxBlock; - } else { - SectorCount = (UINT16) BlocksRemaining; - } - - // - // Command code is WRITE_10. - // - Read10Packet->opcode = ATA_CMD_WRITE_10; - - // - // Lba0 ~ Lba3 specify the start logical block address of the data transfer. - // Lba0 is MSB, Lba3 is LSB - // - Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff); - Read10Packet->Lba2 = (UINT8) (Lba32 >> 8); - Read10Packet->Lba1 = (UINT8) (Lba32 >> 16); - Read10Packet->Lba0 = (UINT8) (Lba32 >> 24); - - // - // TranLen0 ~ TranLen1 specify the transfer length in block unit. - // TranLen0 is MSB, TranLen is LSB - // - Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff); - Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8); - - ByteCount = SectorCount * BlockSize; - - Status = AtapiPacketCommandOut ( - IdeDev, - &Packet, - (UINT16 *) PtrBuffer, - ByteCount, - ATAPILONGTIMEOUT - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Lba32 += SectorCount; - PtrBuffer = ((UINT8 *) PtrBuffer + SectorCount * BlockSize); - BlocksRemaining -= SectorCount; - } - - return Status; -} -/** - This function is used to implement the Soft Reset on the specified - ATAPI device. Different from the AtaSoftReset(), here reset is a ATA - Soft Reset Command special for ATAPI device, and it only take effects - on the specified ATAPI device, not on the whole IDE bus. - Since the ATAPI soft reset is needed when device is in exceptional - condition (such as BSY bit is always set ), I think the Soft Reset - command should be sent without waiting for the BSY clear and DRDY - set. - This function is called by IdeBlkIoReset(), - a interface function of Block I/O protocol. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS Soft reset completes successfully. - @retval EFI_DEVICE_ERROR Any step during the reset process is failed. - -**/ -EFI_STATUS -AtapiSoftReset ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - UINT8 Command; - UINT8 DeviceSelect; - EFI_STATUS Status; - - // - // for ATAPI device, no need to wait DRDY ready after device selecting. - // (bit7 and bit5 are both set to 1 for backward compatibility) - // - DeviceSelect = (UINT8) (((BIT7 | BIT5) | (IdeDev->Device << 4))); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); - - Command = ATA_CMD_SOFT_RESET; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, Command); - - // - // BSY cleared is the only status return to the host by the device - // when reset is completed. - // slave device needs at most 31s to clear BSY - // - Status = WaitForBSYClear (IdeDev, 31000); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // stall 5 seconds to make the device status stable - // - gBS->Stall (5000000); - - return EFI_SUCCESS; -} - -/** - This function is the ATAPI implementation for ReadBlocks in the - Block I/O Protocol interface. - - @param IdeBlkIoDevice Indicates the calling context. - @param MediaId The media id that the read request is for. - @param Lba The starting logical block address to read from on the device. - @param BufferSize The size of the Buffer in bytes. This must be a multiple - of the intrinsic block size of the device. - @param Buffer A pointer to the destination buffer for the data. The caller - is responsible for either having implicit or explicit - ownership of the memory that data is read into. - - @retval EFI_SUCCESS Read Blocks successfully. - @retval EFI_DEVICE_ERROR Read Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, - or the data buffer is not valid. -**/ -EFI_STATUS -AtapiBlkIoReadBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - UINTN BlockSize; - UINTN NumberOfBlocks; - EFI_STATUS Status; - - BOOLEAN MediaChange; - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - // - // ATAPI device media is removable, so it is a must - // to detect media first before read operation - // - MediaChange = FALSE; - Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange); - if (EFI_ERROR (Status)) { - - if (IdeBlkIoDevice->Cache != NULL) { - gBS->FreePool (IdeBlkIoDevice->Cache); - IdeBlkIoDevice->Cache = NULL; - } - - return Status; - } - // - // Get the intrinsic block size - // - Media = IdeBlkIoDevice->BlkIo.Media; - BlockSize = Media->BlockSize; - - NumberOfBlocks = BufferSize / BlockSize; - - if (!(Media->MediaPresent)) { - - if (IdeBlkIoDevice->Cache != NULL) { - gBS->FreePool (IdeBlkIoDevice->Cache); - IdeBlkIoDevice->Cache = NULL; - } - return EFI_NO_MEDIA; - - } - - if ((MediaId != Media->MediaId) || MediaChange) { - - if (IdeBlkIoDevice->Cache != NULL) { - gBS->FreePool (IdeBlkIoDevice->Cache); - IdeBlkIoDevice->Cache = NULL; - } - return EFI_MEDIA_CHANGED; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { - return EFI_INVALID_PARAMETER; - } - - // - // if all the parameters are valid, then perform read sectors command - // to transfer data from device to host. - // - Status = AtapiReadSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Read blocks succeeded - // - - // - // save the first block to the cache for performance - // - if (Lba == 0 && (IdeBlkIoDevice->Cache == NULL)) { - IdeBlkIoDevice->Cache = AllocatePool (BlockSize); - if (IdeBlkIoDevice->Cache!= NULL) { - CopyMem ((UINT8 *) IdeBlkIoDevice->Cache, (UINT8 *) Buffer, BlockSize); - } - } - - return EFI_SUCCESS; - -} -/** - This function is the ATAPI implementation for WriteBlocks in the - Block I/O Protocol interface. - - @param IdeBlkIoDevice Indicates the calling context. - @param MediaId The media id that the write request is for. - @param Lba The starting logical block address to write onto the device. - @param BufferSize The size of the Buffer in bytes. This must be a multiple - of the intrinsic block size of the device. - @param Buffer A pointer to the source buffer for the data. The caller - is responsible for either having implicit or explicit ownership - of the memory that data is written from. - - @retval EFI_SUCCESS Write Blocks successfully. - @retval EFI_DEVICE_ERROR Write Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, - or the data buffer is not valid. - - @retval EFI_WRITE_PROTECTED The write protected is enabled or the media does not support write -**/ -EFI_STATUS -AtapiBlkIoWriteBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - - EFI_BLOCK_IO_MEDIA *Media; - UINTN BlockSize; - UINTN NumberOfBlocks; - EFI_STATUS Status; - BOOLEAN MediaChange; - - if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) { - gBS->FreePool (IdeBlkIoDevice->Cache); - IdeBlkIoDevice->Cache = NULL; - } - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - // - // ATAPI device media is removable, - // so it is a must to detect media first before write operation - // - MediaChange = FALSE; - Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange); - if (EFI_ERROR (Status)) { - - if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) { - gBS->FreePool (IdeBlkIoDevice->Cache); - IdeBlkIoDevice->Cache = NULL; - } - return Status; - } - - // - // Get the intrinsic block size - // - Media = IdeBlkIoDevice->BlkIo.Media; - BlockSize = Media->BlockSize; - NumberOfBlocks = BufferSize / BlockSize; - - if (!(Media->MediaPresent)) { - - if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) { - gBS->FreePool (IdeBlkIoDevice->Cache); - IdeBlkIoDevice->Cache = NULL; - } - return EFI_NO_MEDIA; - } - - if ((MediaId != Media->MediaId) || MediaChange) { - - if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) { - gBS->FreePool (IdeBlkIoDevice->Cache); - IdeBlkIoDevice->Cache = NULL; - } - return EFI_MEDIA_CHANGED; - } - - if (Media->ReadOnly) { - return EFI_WRITE_PROTECTED; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { - return EFI_INVALID_PARAMETER; - } - - // - // if all the parameters are valid, - // then perform write sectors command to transfer data from host to device. - // - Status = AtapiWriteSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; - -} - - - diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c deleted file mode 100644 index 5e376d72d7..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c +++ /dev/null @@ -1,278 +0,0 @@ -/** @file - UEFI Component Name(2) protocol implementation for ConPlatform 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 "IdeBus.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName = { - IDEBusComponentNameGetDriverName, - IDEBusComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIDEBusComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IDEBusComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IDEBusComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIDEBusDriverNameTable[] = { - { "eng;en", (CHAR16 *) L"PCI IDE/ATAPI Bus Driver" }, - { NULL , NULL } -}; - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIDEBusControllerNameTable[] = { - { "eng;en", (CHAR16 *) L"PCI IDE/ATAPI Controller" }, - { 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 -IDEBusComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mIDEBusDriverNameTable, - DriverName, - (BOOLEAN)(This == &gIDEBusComponentName) - ); -} - -/** - 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 -IDEBusComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - IDE_BLK_IO_DEV *IdeBlkIoDevice; - - // - // Make sure this driver is currently managing ControllHandle - // - Status = EfiTestManagedDevice ( - ControllerHandle, - gIDEBusDriverBinding.DriverBindingHandle, - &gEfiIdeControllerInitProtocolGuid - ); - if (EFI_ERROR (Status)) { - return Status; - } - - if (ChildHandle == NULL) { - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mIDEBusControllerNameTable, - ControllerName, - (BOOLEAN)(This == &gIDEBusComponentName) - ); - } - - Status = EfiTestChildHandle ( - ControllerHandle, - ChildHandle, - &gEfiPciIoProtocolGuid - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the child context - // - Status = gBS->OpenProtocol ( - ChildHandle, - &gEfiBlockIoProtocolGuid, - (VOID **) &BlockIo, - gIDEBusDriverBinding.DriverBindingHandle, - ChildHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlockIo); - - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - IdeBlkIoDevice->ControllerNameTable, - ControllerName, - (BOOLEAN)(This == &gIDEBusComponentName) - ); -} - -/** - Add the component name for the IDE/ATAPI device - - @param IdeBlkIoDevicePtr A pointer to the IDE_BLK_IO_DEV instance. - -**/ -VOID -AddName ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr - ) -{ - UINTN StringIndex; - CHAR16 ModelName[41]; - - // - // Add Component Name for the IDE/ATAPI device that was discovered. - // - IdeBlkIoDevicePtr->ControllerNameTable = NULL; - for (StringIndex = 0; StringIndex < 41; StringIndex++) { - ModelName[StringIndex] = IdeBlkIoDevicePtr->ModelName[StringIndex]; - } - - AddUnicodeString2 ( - "eng", - gIDEBusComponentName.SupportedLanguages, - &IdeBlkIoDevicePtr->ControllerNameTable, - ModelName, - TRUE - ); - AddUnicodeString2 ( - "en", - gIDEBusComponentName2.SupportedLanguages, - &IdeBlkIoDevicePtr->ControllerNameTable, - ModelName, - FALSE - ); - -} diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h deleted file mode 100644 index 9a911a5ec9..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h +++ /dev/null @@ -1,166 +0,0 @@ -/** @file - - UEFI Component Name(2) protocol implementation header file for IDE Bus 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. - -**/ - -#ifndef _IDE_BUS_COMPONENT_NAME_H_ -#define _IDE_BUS_COMPONENT_NAME_H_ - -#define ADD_IDE_ATAPI_NAME(x) AddName ((x)); - -extern EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gIDEBusComponentName2; - - -// -// EFI Component Name Functions -// -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -IDEBusComponentNameGetDriverName ( - 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 -IDEBusComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - - -/** - Add the component name for the IDE/ATAPI device - - @param IdeBlkIoDevicePtr A pointer to the IDE_BLK_IO_DEV instance. - -**/ -VOID -AddName ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr - ); - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c deleted file mode 100644 index 999e20e016..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c +++ /dev/null @@ -1,292 +0,0 @@ -/** @file - Implementation of UEFI Driver Configuration Protocol for IDE bus driver which - provides ability to set IDE bus controller specific options. - - Copyright (c) 2006 - 2008, Intel 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 "IdeBus.h" - -CHAR16 *OptionString[4] = { - L"Enable Primary Master (Y/N)? -->", - L"Enable Primary Slave (Y/N)? -->", - L"Enable Secondary Master (Y/N)? -->", - L"Enable Secondary Slave (Y/N)? -->" -}; - -// -// EFI Driver Configuration Protocol -// -EFI_DRIVER_CONFIGURATION_PROTOCOL gIDEBusDriverConfiguration = { - IDEBusDriverConfigurationSetOptions, - IDEBusDriverConfigurationOptionsValid, - IDEBusDriverConfigurationForceDefaults, - "eng" -}; - -/** - Interprete keyboard input. - - @retval EFI_ABORTED Get an 'ESC' key inputed. - @retval EFI_SUCCESS Get an 'Y' or 'y' inputed. - @retval EFI_NOT_FOUND Get an 'N' or 'n' inputed.. - -**/ -EFI_STATUS -GetResponse ( - VOID - ) -{ - EFI_STATUS Status; - EFI_INPUT_KEY Key; - - while (TRUE) { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - if (!EFI_ERROR (Status)) { - if (Key.ScanCode == SCAN_ESC) { - return EFI_ABORTED; - } - - switch (Key.UnicodeChar) { - - // - // fall through - // - case L'y': - case L'Y': - gST->ConOut->OutputString (gST->ConOut, L"Y\n"); - return EFI_SUCCESS; - - // - // fall through - // - case L'n': - case L'N': - gST->ConOut->OutputString (gST->ConOut, L"N\n"); - return EFI_NOT_FOUND; - } - - } - } -} - -/** - Allows the user to set controller specific options for a controller that a - driver is currently managing. - - @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. - @param ControllerHandle The handle of the controller to set options on. - @param ChildHandle The handle of the child controller to set options on. - This is an optional parameter that may be NULL. - It will be NULL for device drivers, and for a bus drivers - that wish to set options for the bus controller. - It will not be NULL for a bus driver that wishes to set - options for one of its child controllers. - @param Language A pointer to a three character ISO 639-2 language identifier. - This is the language of the user interface that should be presented - to the user, 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 ActionRequired A pointer to the action that the calling agent is required - to perform when this function returns. - - - @retval EFI_SUCCESS The driver specified by This successfully set the configuration - options for the controller specified by ControllerHandle.. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ActionRequired is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support setting configuration options for - the controller specified by ControllerHandle and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the language specified by Language. - @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the configuration options for the - controller specified by ControllerHandle and ChildHandle. - @retval EFI_OUT_RESOURCES There are not enough resources available to set the configuration options for the - controller specified by ControllerHandle and ChildHandle -**/ -EFI_STATUS -EFIAPI -IDEBusDriverConfigurationSetOptions ( - IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired - ) -{ - EFI_STATUS Status; - UINT8 Value; - UINT8 NewValue; - UINTN DataSize; - UINTN Index; - - if (ChildHandle != NULL) { - return EFI_UNSUPPORTED; - } - - *ActionRequired = EfiDriverConfigurationActionNone; - - DataSize = sizeof (Value); - Status = gRT->GetVariable ( - L"Configuration", - &gEfiCallerIdGuid, - NULL, - &DataSize, - &Value - ); - - gST->ConOut->OutputString (gST->ConOut, L"IDE Bus Driver Configuration\n"); - gST->ConOut->OutputString (gST->ConOut, L"===============================\n"); - - NewValue = 0; - for (Index = 0; Index < 4; Index++) { - gST->ConOut->OutputString (gST->ConOut, OptionString[Index]); - - Status = GetResponse (); - if (Status == EFI_ABORTED) { - return EFI_SUCCESS; - } - - if (!EFI_ERROR (Status)) { - NewValue = (UINT8) (NewValue | (1 << Index)); - } - } - - if (EFI_ERROR (Status) || (NewValue != Value)) { - gRT->SetVariable ( - L"Configuration", - &gEfiCallerIdGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, - sizeof (NewValue), - &NewValue - ); - - *ActionRequired = EfiDriverConfigurationActionRestartController; - } else { - *ActionRequired = EfiDriverConfigurationActionNone; - } - - return EFI_SUCCESS; -} - -/** - Tests to see if a controller's current configuration options are valid. - - @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. - @param ControllerHandle The handle of the controller to test if it's current configuration options - are valid. - @param ChildHandle The handle of the child controller to test if it's current configuration - options are valid. 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 test the configuration options for the bus controller. It will - not be NULL for a bus driver that wishes to test configuration options for - one of its child controllers. - @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle that is being - managed by the driver specified by This has a valid set of configuration - options. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. - @retval EFI_UNSUPPORTED The driver specified by This is not currently managing the controller - specified by ControllerHandle and ChildHandle. - @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle that is being - managed by the driver specified by This has an invalid set of configuration - options. -**/ -EFI_STATUS -EFIAPI -IDEBusDriverConfigurationOptionsValid ( - IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL - ) -{ - EFI_STATUS Status; - UINT8 Value; - UINTN DataSize; - - if (ChildHandle != NULL) { - return EFI_UNSUPPORTED; - } - - DataSize = sizeof (Value); - Status = gRT->GetVariable ( - L"Configuration", - &gEfiCallerIdGuid, - NULL, - &DataSize, - &Value - ); - if (EFI_ERROR (Status) || Value > 0x0f) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} -/** - Forces a driver to set the default configuration options for a controller. - - @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. - @param ControllerHandle The handle of the controller to force default configuration options on. - @param ChildHandle The handle of the child controller to force default configuration - options on 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 force default configuration options for the bus - controller. It will not be NULL for a bus driver that wishes to force - default configuration options for one of its child controllers. - @param DefaultType The type of default configuration options to force on the controller - specified by ControllerHandle and ChildHandle. - @param ActionRequired A pointer to the action that the calling agent is required to perform - when this function returns. - - @retval EFI_SUCCESS The driver specified by This successfully forced the - default configuration options on the controller specified by - ControllerHandle and ChildHandle. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ActionRequired is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default - configuration options on the controller specified by ControllerHandle - and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type - specified by DefaultType. - @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration - options on the controller specified by ControllerHandle and ChildHandle. - @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration - options on the controller specified by ControllerHandle and ChildHandle. -**/ -EFI_STATUS -EFIAPI -IDEBusDriverConfigurationForceDefaults ( - IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN UINT32 DefaultType, - OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired - ) -{ - UINT8 Value; - - if (ChildHandle != NULL) { - return EFI_UNSUPPORTED; - } - - Value = 0x0f; - gRT->SetVariable ( - L"Configuration", - &gEfiCallerIdGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, - sizeof (Value), - &Value - ); - *ActionRequired = EfiDriverConfigurationActionRestartController; - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c deleted file mode 100644 index 73435dd7ac..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c +++ /dev/null @@ -1,245 +0,0 @@ -/** @file - Implementation of UEFI driver Dialnostics protocol which to perform diagnostic on the IDE - Bus controller. - - 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 "IdeBus.h" - -#define IDE_BUS_DIAGNOSTIC_ERROR L"PCI IDE/ATAPI Driver Diagnostics Failed" - -// -// EFI Driver Diagnostics Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics = { - IDEBusDriverDiagnosticsRunDiagnostics, - "eng" -}; - -// -// EFI Driver Diagnostics 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gIDEBusDriverDiagnostics2 = { - (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) IDEBusDriverDiagnosticsRunDiagnostics, - "en" -}; - -/** - Runs diagnostics on a controller. - - @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance. - @param ControllerHandle The handle of the controller to run diagnostics on. - @param ChildHandle The handle of the child controller to run diagnostics on - 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 run diagnostics on the bus controller. - It will not be NULL for a bus driver that wishes to run - diagnostics on one of its child controllers. - @param DiagnosticType Indicates type of diagnostics to perform on the controller - specified by ControllerHandle and ChildHandle. - @param Language A pointer to a three character ISO 639-2 language identifier. - This is the language in which the optional error message should - be returned in Buffer, 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 ErrorType A GUID that defines the format of the data returned in Buffer. - @param BufferSize The size, in bytes, of the data returned in Buffer. - @param Buffer A buffer that contains a Null-terminated Unicode string - plus some additional data whose format is defined by ErrorType. - Buffer is allocated by this function with AllocatePool(), and - it is the caller's responsibility to free it with a call to FreePool(). - - @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle passed - the diagnostic. - @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 ErrorType is NULL. - @retval EFI_INVALID_PARAMETER BufferType is NULL. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support running - diagnostics for the controller specified by ControllerHandle - and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - type of diagnostic specified by DiagnosticType. - @retval EFI_UNSUPPORTED The driver specified by This does not support the language - specified by Language. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete the - diagnostics. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return the - status information in ErrorType, BufferSize,and Buffer. - @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle - did not pass the diagnostic. -**/ -EFI_STATUS -EFIAPI -IDEBusDriverDiagnosticsRunDiagnostics ( - IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, - IN CHAR8 *Language, - OUT EFI_GUID **ErrorType, - OUT UINTN *BufferSize, - OUT CHAR16 **Buffer - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - IDE_BLK_IO_DEV *IdeBlkIoDevice; - UINT32 VendorDeviceId; - VOID *BlockBuffer; - CHAR8 *SupportedLanguages; - BOOLEAN Iso639Language; - BOOLEAN Found; - UINTN Index; - - if (Language == NULL || - ErrorType == NULL || - Buffer == NULL || - ControllerHandle == NULL || - BufferSize == NULL) { - - return EFI_INVALID_PARAMETER; - } - - SupportedLanguages = This->SupportedLanguages; - Iso639Language = (BOOLEAN)(This == &gIDEBusDriverDiagnostics); - // - // Make sure Language is in the set of Supported Languages - // - Found = FALSE; - while (*SupportedLanguages != 0) { - if (Iso639Language) { - if (CompareMem (Language, SupportedLanguages, 3) == 0) { - Found = TRUE; - break; - } - SupportedLanguages += 3; - } else { - for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++); - if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) { - Found = TRUE; - break; - } - SupportedLanguages += Index; - for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++); - } - } - // - // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED - // - if (!Found) { - return EFI_UNSUPPORTED; - } - - *ErrorType = NULL; - *BufferSize = 0; - - if (ChildHandle == NULL) { - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiCallerIdGuid, - NULL, - gIDEBusDriverBinding.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - gIDEBusDriverBinding.DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Use services of PCI I/O Protocol to test the PCI IDE/ATAPI Controller - // The following test simply reads the Device ID and Vendor ID. - // It should never fail. A real test would perform more advanced - // diagnostics. - // - - Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &VendorDeviceId); - if (EFI_ERROR (Status) || VendorDeviceId == 0xffffffff) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; - } - - Status = gBS->OpenProtocol ( - ChildHandle, - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo, - gIDEBusDriverBinding.DriverBindingHandle, - ChildHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); - - // - // Use services available from IdeBlkIoDevice to test the IDE/ATAPI device - // - Status = gBS->AllocatePool ( - EfiBootServicesData, - IdeBlkIoDevice->BlkMedia.BlockSize, - (VOID **) &BlockBuffer - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = IdeBlkIoDevice->BlkIo.ReadBlocks ( - &IdeBlkIoDevice->BlkIo, - IdeBlkIoDevice->BlkMedia.MediaId, - 0, - IdeBlkIoDevice->BlkMedia.BlockSize, - BlockBuffer - ); - - if (EFI_ERROR (Status)) { - *ErrorType = &gEfiCallerIdGuid; - *BufferSize = sizeof (IDE_BUS_DIAGNOSTIC_ERROR); - - Status = gBS->AllocatePool ( - EfiBootServicesData, - (UINTN) (*BufferSize), - (VOID **) Buffer - ); - if (EFI_ERROR (Status)) { - return Status; - } - - CopyMem (*Buffer, IDE_BUS_DIAGNOSTIC_ERROR, *BufferSize); - - Status = EFI_DEVICE_ERROR; - } - - gBS->FreePool (BlockBuffer); - - return Status; -} diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c deleted file mode 100644 index ffc818036a..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c +++ /dev/null @@ -1,1330 +0,0 @@ -/** @file - The file ontaining the helper functions implement of the Ide Bus driver - - Copyright (c) 2006 - 2008, Intel 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 "IdeBus.h" - -BOOLEAN ChannelDeviceDetected = FALSE; -BOOLEAN SlaveDeviceExist = FALSE; -UINT8 SlaveDeviceType = INVALID_DEVICE_TYPE; -BOOLEAN MasterDeviceExist = FALSE; -UINT8 MasterDeviceType = INVALID_DEVICE_TYPE; - -/** - read a one-byte data from a IDE port. - - @param PciIo The PCI IO protocol instance - @param Port the IDE Port number - - @return the one-byte data read from IDE port -**/ -UINT8 -IDEReadPortB ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port - ) -{ - UINT8 Data; - - Data = 0; - // - // perform 1-byte data read from register - // - PciIo->Io.Read ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - 1, - &Data - ); - return Data; -} -/** - Reads multiple words of data from the IDE data port. - Call the IO abstraction once to do the complete read, - not one word at a time - - @param PciIo Pointer to the EFI_PCI_IO instance - @param Port IO port to read - @param Count No. of UINT16's to read - @param Buffer Pointer to the data buffer for read - -**/ -VOID -IDEReadPortWMultiple ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINTN Count, - OUT VOID *Buffer - ) -{ - UINT16 *AlignedBuffer; - UINT16 *WorkingBuffer; - UINTN Size; - - // - // Prepare an 16-bit alligned working buffer. CpuIo will return failure and - // not perform actual I/O operations if buffer pointer passed in is not at - // natural boundary. The "Buffer" argument is passed in by user and may not - // at 16-bit natural boundary. - // - Size = sizeof (UINT16) * Count; - - gBS->AllocatePool ( - EfiBootServicesData, - Size + 1, - (VOID**)&WorkingBuffer - ); - - AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1))); - - // - // Perform UINT16 data read from FIFO - // - PciIo->Io.Read ( - PciIo, - EfiPciIoWidthFifoUint16, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - Count, - (UINT16*)AlignedBuffer - ); - - // - // Copy data to user buffer - // - CopyMem (Buffer, (UINT16*)AlignedBuffer, Size); - gBS->FreePool (WorkingBuffer); -} - -/** - write a 1-byte data to a specific IDE port. - - @param PciIo PCI IO protocol instance - @param Port The IDE port to be writen - @param Data The data to write to the port -**/ -VOID -IDEWritePortB ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINT8 Data - ) -{ - // - // perform 1-byte data write to register - // - PciIo->Io.Write ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - 1, - &Data - ); - -} - -/** - write a 1-word data to a specific IDE port. - - @param PciIo PCI IO protocol instance - @param Port The IDE port to be writen - @param Data The data to write to the port -**/ -VOID -IDEWritePortW ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINT16 Data - ) -{ - // - // perform 1-word data write to register - // - PciIo->Io.Write ( - PciIo, - EfiPciIoWidthUint16, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - 1, - &Data - ); -} - -/** - Write multiple words of data to the IDE data port. - Call the IO abstraction once to do the complete read, - not one word at a time - - @param PciIo Pointer to the EFI_PCI_IO instance - @param Port IO port to read - @param Count No. of UINT16's to read - @param Buffer Pointer to the data buffer for read - -**/ -VOID -IDEWritePortWMultiple ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINTN Count, - IN VOID *Buffer - ) -{ - UINT16 *AlignedBuffer; - UINT32 *WorkingBuffer; - UINTN Size; - - // - // Prepare an 16-bit alligned working buffer. CpuIo will return failure and - // not perform actual I/O operations if buffer pointer passed in is not at - // natural boundary. The "Buffer" argument is passed in by user and may not - // at 16-bit natural boundary. - // - Size = sizeof (UINT16) * Count; - - gBS->AllocatePool ( - EfiBootServicesData, - Size + 1, - (VOID **) &WorkingBuffer - ); - - AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1))); - - // - // Copy data from user buffer to working buffer - // - CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size); - - // - // perform UINT16 data write to the FIFO - // - PciIo->Io.Write ( - PciIo, - EfiPciIoWidthFifoUint16, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - Count, - (UINT16 *) AlignedBuffer - ); - - gBS->FreePool (WorkingBuffer); -} -/** - Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode, - use fixed addresses. In Native-PCI mode, get base addresses from BARs in - the PCI IDE controller's Configuration Space. - - The steps to get IDE IO port registers' base addresses for each channel - as follows: - - 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE - controller's Configuration Space to determine the operating mode. - - 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below. -
-  ___________________________________________
-  |           | Command Block | Control Block |
-  |  Channel  |   Registers   |   Registers   |
-  |___________|_______________|_______________|
-  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |
-  |___________|_______________|_______________|
-  | Secondary |  170h - 177h  |  376h - 377h  |
-  |___________|_______________|_______________|
-
-  Table 1. Compatibility resource mappings
-  
- - b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs - in IDE controller's PCI Configuration Space, shown in the Table 2 below. -
-  ___________________________________________________
-  |           |   Command Block   |   Control Block   |
-  |  Channel  |     Registers     |     Registers     |
-  |___________|___________________|___________________|
-  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|
-  |___________|___________________|___________________|
-  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
-  |___________|___________________|___________________|
-
-  Table 2. BARs for Register Mapping
-  
- @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for - primary, 0374h for secondary. So 2 bytes extra offset should be - added to the base addresses read from BARs. - - For more details, please refer to PCI IDE Controller Specification and Intel - ICH4 Datasheet. - - @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance - @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to - receive IDE IO port registers' base addresses - - @retval EFI_UNSUPPORTED return this value when the BARs is not IO type - @retval EFI_SUCCESS Get the Base address successfully - @retval other read the pci configureation data error - -**/ -EFI_STATUS -GetIdeRegistersBaseAddr ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr - ) -{ - EFI_STATUS Status; - PCI_TYPE00 PciData; - - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint8, - 0, - sizeof (PciData), - &PciData - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) { - IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0; - IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6; - IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr = - (UINT16)((PciData.Device.Bar[4] & 0x0000fff0)); - } else { - // - // The BARs should be of IO type - // - if ((PciData.Device.Bar[0] & BIT0) == 0 || - (PciData.Device.Bar[1] & BIT0) == 0) { - return EFI_UNSUPPORTED; - } - - IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = - (UINT16) (PciData.Device.Bar[0] & 0x0000fff8); - IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = - (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2); - IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr = - (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); - } - - if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) { - IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170; - IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376; - IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr = - (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); - } else { - // - // The BARs should be of IO type - // - if ((PciData.Device.Bar[2] & BIT0) == 0 || - (PciData.Device.Bar[3] & BIT0) == 0) { - return EFI_UNSUPPORTED; - } - - IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = - (UINT16) (PciData.Device.Bar[2] & 0x0000fff8); - IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = - (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2); - IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr = - (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); - } - - return EFI_SUCCESS; -} - -/** - This function is used to requery IDE resources. The IDE controller will - probably switch between native and legacy modes during the EFI->CSM->OS - transfer. We do this everytime before an BlkIo operation to ensure its - succeess. - - @param IdeDev The BLK_IO private data which specifies the IDE device - - @retval EFI_INVALID_PARAMETER return this value when the channel is invalid - @retval EFI_SUCCESS reassign the IDE IO resource successfully - @retval other get the IDE current base address effor - -**/ -EFI_STATUS -ReassignIdeResources ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - EFI_STATUS Status; - IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; - UINT16 CommandBlockBaseAddr; - UINT16 ControlBlockBaseAddr; - - if (IdeDev->Channel >= IdeMaxChannel) { - return EFI_INVALID_PARAMETER; - } - - // - // Requery IDE IO port registers' base addresses in case of the switch of - // native and legacy modes - // - Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr); - if (EFI_ERROR (Status)) { - return Status; - } - - ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS)); - CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr; - ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr; - - IdeDev->IoPort->Data = CommandBlockBaseAddr; - (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); - IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); - IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); - IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); - IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); - IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); - - (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); - (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr; - IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); - IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0); - - IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr; - return EFI_SUCCESS; -} - -/** - This function is called by DiscoverIdeDevice(). It is used for detect - whether the IDE device exists in the specified Channel as the specified - Device Number. - - There is two IDE channels: one is Primary Channel, the other is - Secondary Channel.(Channel is the logical name for the physical "Cable".) - Different channel has different register group. - - On each IDE channel, at most two IDE devices attach, - one is called Device 0 (Master device), the other is called Device 1 - (Slave device). The devices on the same channel co-use the same register - group, so before sending out a command for a specified device via command - register, it is a must to select the current device to accept the command - by set the device number in the Head/Device Register. - - @param IdeDev pointer to IDE_BLK_IO_DEV data structure, used to record all the - information of the IDE device. - - @retval EFI_SUCCESS successfully detects device. - - @retval other any failure during detection process will return this value. - -**/ -EFI_STATUS -DetectIDEController ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - EFI_STATUS Status; - UINT8 SectorCountReg; - UINT8 LBALowReg; - UINT8 LBAMidReg; - UINT8 LBAHighReg; - UINT8 InitStatusReg; - UINT8 StatusReg; - - // - // Select slave device - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((1 << 4) | 0xe0) - ); - gBS->Stall (100); - - // - // Save the init slave status register - // - InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - - // - // Select Master back - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((0 << 4) | 0xe0) - ); - gBS->Stall (100); - - // - // Send ATA Device Execut Diagnostic command. - // This command should work no matter DRDY is ready or not - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90); - - Status = WaitForBSYClear (IdeDev, 3500); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status)); - return Status; - } - // - // Read device signature - // - // - // Select Master - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((0 << 4) | 0xe0) - ); - gBS->Stall (100); - SectorCountReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->SectorCount - ); - LBALowReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->SectorNumber - ); - LBAMidReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->CylinderLsb - ); - LBAHighReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->CylinderMsb - ); - if ((SectorCountReg == 0x1) && - (LBALowReg == 0x1) && - (LBAMidReg == 0x0) && - (LBAHighReg == 0x0)) { - MasterDeviceExist = TRUE; - MasterDeviceType = ATA_DEVICE_TYPE; - } else { - if ((LBAMidReg == 0x14) && - (LBAHighReg == 0xeb)) { - MasterDeviceExist = TRUE; - MasterDeviceType = ATAPI_DEVICE_TYPE; - } - } - - // - // For some Hard Drive, it takes some time to get - // the right signature when operating in single slave mode. - // We stall 20ms to work around this. - // - if (!MasterDeviceExist) { - gBS->Stall (20000); - } - - // - // Select Slave - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((1 << 4) | 0xe0) - ); - gBS->Stall (100); - SectorCountReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->SectorCount - ); - LBALowReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->SectorNumber - ); - LBAMidReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->CylinderLsb - ); - LBAHighReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->CylinderMsb - ); - StatusReg = IDEReadPortB ( - IdeDev->PciIo, - IdeDev->IoPort->Reg.Status - ); - if ((SectorCountReg == 0x1) && - (LBALowReg == 0x1) && - (LBAMidReg == 0x0) && - (LBAHighReg == 0x0)) { - SlaveDeviceExist = TRUE; - SlaveDeviceType = ATA_DEVICE_TYPE; - } else { - if ((LBAMidReg == 0x14) && - (LBAHighReg == 0xeb)) { - SlaveDeviceExist = TRUE; - SlaveDeviceType = ATAPI_DEVICE_TYPE; - } - } - - // - // When single master is plugged, slave device - // will be wrongly detected. Here's the workaround - // for ATA devices by detecting DRY bit in status - // register. - // NOTE: This workaround doesn't apply to ATAPI. - // - if (MasterDeviceExist && SlaveDeviceExist && - (StatusReg & ATA_STSREG_DRDY) == 0 && - (InitStatusReg & ATA_STSREG_DRDY) == 0 && - MasterDeviceType == SlaveDeviceType && - SlaveDeviceType != ATAPI_DEVICE_TYPE) { - SlaveDeviceExist = FALSE; - } - - // - // Indicate this channel has been detected - // - ChannelDeviceDetected = TRUE; - return EFI_SUCCESS; -} -/** - Detect if there is disk attached to this port - - @param IdeDev The BLK_IO private data which specifies the IDE device. - - @retval EFI_NOT_FOUND The device or channel is not found - @retval EFI_SUCCESS The device is found - -**/ -EFI_STATUS -DiscoverIdeDevice ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - EFI_STATUS Status; - EFI_STATUS LongPhyStatus; - - // - // If a channel has not been checked, check it now. Then set it to "checked" state - // After this step, all devices in this channel have been checked. - // - if (!ChannelDeviceDetected) { - Status = DetectIDEController (IdeDev); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - } - - Status = EFI_NOT_FOUND; - - // - // Device exists. test if it is an ATA device. - // Prefer the result from DetectIDEController, - // if failed, try another device type to handle - // devices that not follow the spec. - // - if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) { - if (MasterDeviceType == ATA_DEVICE_TYPE) { - Status = ATAIdentify (IdeDev); - if (EFI_ERROR (Status)) { - Status = ATAPIIdentify (IdeDev); - if (!EFI_ERROR (Status)) { - MasterDeviceType = ATAPI_DEVICE_TYPE; - } - } - } else { - Status = ATAPIIdentify (IdeDev); - if (EFI_ERROR (Status)) { - Status = ATAIdentify (IdeDev); - if (!EFI_ERROR (Status)) { - MasterDeviceType = ATA_DEVICE_TYPE; - } - } - } - } - if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) { - if (SlaveDeviceType == ATA_DEVICE_TYPE) { - Status = ATAIdentify (IdeDev); - if (EFI_ERROR (Status)) { - Status = ATAPIIdentify (IdeDev); - if (!EFI_ERROR (Status)) { - SlaveDeviceType = ATAPI_DEVICE_TYPE; - } - } - } else { - Status = ATAPIIdentify (IdeDev); - if (EFI_ERROR (Status)) { - Status = ATAIdentify (IdeDev); - if (!EFI_ERROR (Status)) { - SlaveDeviceType = ATA_DEVICE_TYPE; - } - } - } - } - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - // - // Init Block I/O interface - // - LongPhyStatus = AtaEnableLongPhysicalSector (IdeDev); - if (!EFI_ERROR (LongPhyStatus)) { - IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; - } else { - IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; - } - IdeDev->BlkIo.Reset = IDEBlkIoReset; - IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks; - IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks; - IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks; - - IdeDev->BlkMedia.LogicalPartition = FALSE; - IdeDev->BlkMedia.WriteCaching = FALSE; - - // - // Init Disk Info interface - // - gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID)); - IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry; - IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify; - IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData; - IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde; - - return EFI_SUCCESS; -} - -/** - This interface is used to initialize all state data related to the detection of one - channel. -**/ -VOID -InitializeIDEChannelData ( - VOID - ) -{ - ChannelDeviceDetected = FALSE; - MasterDeviceExist = FALSE; - MasterDeviceType = 0xff; - SlaveDeviceExist = FALSE; - SlaveDeviceType = 0xff; -} -/** - This function is used to poll for the DRQ bit clear in the Status - Register. DRQ is cleared when the device is finished transferring data. - So this function is called after data transfer is finished. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. - - @retval EFI_SUCCESS DRQ bit clear within the time out. - - @retval EFI_TIMEOUT DRQ bit not clear within the time out. - - @note - Read Status Register will clear interrupt status. - -**/ -EFI_STATUS -DRQClear ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ) -{ - UINT32 Delay; - UINT8 StatusRegister; - UINT8 ErrorRegister; - - Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); - do { - - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - - // - // wait for BSY == 0 and DRQ == 0 - // - if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) { - break; - } - - if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - - ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; - } - } - - // - // Stall for 30 us - // - gBS->Stall (30); - - Delay--; - - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} -/** - This function is used to poll for the DRQ bit clear in the Alternate - Status Register. DRQ is cleared when the device is finished - transferring data. So this function is called after data transfer - is finished. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. - - @retval EFI_SUCCESS DRQ bit clear within the time out. - - @retval EFI_TIMEOUT DRQ bit not clear within the time out. - @note Read Alternate Status Register will not clear interrupt status. - -**/ -EFI_STATUS -DRQClear2 ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ) -{ - UINT32 Delay; - UINT8 AltRegister; - UINT8 ErrorRegister; - - Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); - do { - - AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); - - // - // wait for BSY == 0 and DRQ == 0 - // - if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) { - break; - } - - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - - ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; - } - } - - // - // Stall for 30 us - // - gBS->Stall (30); - - Delay--; - - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - This function is used to poll for the DRQ bit set in the - Status Register. - DRQ is set when the device is ready to transfer data. So this function - is called after the command is sent to the device and before required - data is transferred. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to - record all the information of the IDE device. - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS DRQ bit set within the time out. - @retval EFI_TIMEOUT DRQ bit not set within the time out. - @retval EFI_ABORTED DRQ bit not set caused by the command abort. - - @note Read Status Register will clear interrupt status. - -**/ -EFI_STATUS -DRQReady ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ) -{ - UINT32 Delay; - UINT8 StatusRegister; - UINT8 ErrorRegister; - - Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); - do { - // - // read Status Register will clear interrupt - // - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - - // - // BSY==0,DRQ==1 - // - if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { - break; - } - - if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - - ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; - } - } - - // - // Stall for 30 us - // - gBS->Stall (30); - - Delay--; - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} -/** - This function is used to poll for the DRQ bit set in the Alternate Status Register. - DRQ is set when the device is ready to transfer data. So this function is called after - the command is sent to the device and before required data is transferred. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to - record all the information of the IDE device. - - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS DRQ bit set within the time out. - @retval EFI_TIMEOUT DRQ bit not set within the time out. - @retval EFI_ABORTED DRQ bit not set caused by the command abort. - @note Read Alternate Status Register will not clear interrupt status. - -**/ -EFI_STATUS -DRQReady2 ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ) -{ - UINT32 Delay; - UINT8 AltRegister; - UINT8 ErrorRegister; - - Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); - - do { - // - // Read Alternate Status Register will not clear interrupt status - // - AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); - // - // BSY == 0 , DRQ == 1 - // - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { - break; - } - - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - - ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; - } - } - - // - // Stall for 30 us - // - gBS->Stall (30); - - Delay--; - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - This function is used to poll for the BSY bit clear in the Status Register. BSY - is clear when the device is not busy. Every command must be sent after device is not busy. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS BSY bit clear within the time out. - @retval EFI_TIMEOUT BSY bit not clear within the time out. - - @note Read Status Register will clear interrupt status. -**/ -EFI_STATUS -WaitForBSYClear ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ) -{ - UINT32 Delay; - UINT8 StatusRegister; - - Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); - do { - - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - if ((StatusRegister & ATA_STSREG_BSY) == 0x00) { - break; - } - - // - // Stall for 30 us - // - gBS->Stall (30); - - Delay--; - - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} -/** - This function is used to poll for the BSY bit clear in the Alternate Status Register. - BSY is clear when the device is not busy. Every command must be sent after device is - not busy. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS BSY bit clear within the time out. - @retval EFI_TIMEOUT BSY bit not clear within the time out. - @note Read Alternate Status Register will not clear interrupt status. - -**/ -EFI_STATUS -WaitForBSYClear2 ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ) -{ - UINT32 Delay; - UINT8 AltRegister; - - Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); - do { - AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); - if ((AltRegister & ATA_STSREG_BSY) == 0x00) { - break; - } - - gBS->Stall (30); - - Delay--; - - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} -/** - This function is used to poll for the DRDY bit set in the Status Register. DRDY - bit is set when the device is ready to accept command. Most ATA commands must be - sent after DRDY set except the ATAPI Packet Command. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS DRDY bit set within the time out. - @retval EFI_TIMEOUT DRDY bit not set within the time out. - - @note Read Status Register will clear interrupt status. -**/ -EFI_STATUS -DRDYReady ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN DelayInMilliSeconds - ) -{ - UINT32 Delay; - UINT8 StatusRegister; - UINT8 ErrorRegister; - - Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); - do { - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - // - // BSY == 0 , DRDY == 1 - // - if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) { - break; - } - - if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - - ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; - } - } - - gBS->Stall (30); - - Delay--; - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} -/** - This function is used to poll for the DRDY bit set in the Alternate Status Register. - DRDY bit is set when the device is ready to accept command. Most ATA commands must - be sent after DRDY set except the ATAPI Packet Command. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS DRDY bit set within the time out. - @retval EFI_TIMEOUT DRDY bit not set within the time out. - - @note Read Alternate Status Register will clear interrupt status. - -**/ -EFI_STATUS -DRDYReady2 ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN DelayInMilliSeconds - ) -{ - UINT32 Delay; - UINT8 AltRegister; - UINT8 ErrorRegister; - - Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); - do { - AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); - // - // BSY == 0 , DRDY == 1 - // - if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) { - break; - } - - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - - ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; - } - } - - gBS->Stall (30); - - Delay--; - } while (Delay > 0); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} -/** - Release resources of an IDE device before stopping it. - - @param IdeBlkIoDevice Standard IDE device private data structure - -**/ -VOID -ReleaseIdeResources ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice - ) -{ - if (IdeBlkIoDevice == NULL) { - return ; - } - - // - // Release all the resourses occupied by the IDE_BLK_IO_DEV - // - - if (IdeBlkIoDevice->SenseData != NULL) { - gBS->FreePool (IdeBlkIoDevice->SenseData); - IdeBlkIoDevice->SenseData = NULL; - } - - if (IdeBlkIoDevice->Cache != NULL) { - gBS->FreePool (IdeBlkIoDevice->Cache); - IdeBlkIoDevice->Cache = NULL; - } - - if (IdeBlkIoDevice->IdData != NULL) { - gBS->FreePool (IdeBlkIoDevice->IdData); - IdeBlkIoDevice->IdData = NULL; - } - - if (IdeBlkIoDevice->InquiryData != NULL) { - gBS->FreePool (IdeBlkIoDevice->InquiryData); - IdeBlkIoDevice->InquiryData = NULL; - } - - if (IdeBlkIoDevice->ControllerNameTable != NULL) { - FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable); - IdeBlkIoDevice->ControllerNameTable = NULL; - } - - if (IdeBlkIoDevice->IoPort != NULL) { - gBS->FreePool (IdeBlkIoDevice->IoPort); - } - - if (IdeBlkIoDevice->DevicePath != NULL) { - gBS->FreePool (IdeBlkIoDevice->DevicePath); - } - - if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) { - gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent); - IdeBlkIoDevice->ExitBootServiceEvent = NULL; - } - - gBS->FreePool (IdeBlkIoDevice); - IdeBlkIoDevice = NULL; - - return ; -} -/** - Set the calculated Best transfer mode to a detected device. - - @param IdeDev Standard IDE device private data structure - @param TransferMode The device transfer mode to be set - @return Set transfer mode Command execute status. - -**/ -EFI_STATUS -SetDeviceTransferMode ( - IN IDE_BLK_IO_DEV *IdeDev, - IN ATA_TRANSFER_MODE *TransferMode - ) -{ - EFI_STATUS Status; - UINT8 DeviceSelect; - UINT8 SectorCount; - - DeviceSelect = 0; - DeviceSelect = (UINT8) ((IdeDev->Device) << 4); - SectorCount = *((UINT8 *) TransferMode); - - // - // Send SET FEATURE command (sub command 0x03) to set pio mode. - // - Status = AtaNonDataCommandIn ( - IdeDev, - ATA_CMD_SET_FEATURES, - DeviceSelect, - 0x03, - SectorCount, - 0, - 0, - 0 - ); - - return Status; -} -/** - Set drive parameters for devices not support PACKETS command. - - @param IdeDev Standard IDE device private data structure - @param DriveParameters The device parameters to be set into the disk - @return SetParameters Command execute status. - -**/ -EFI_STATUS -SetDriveParameters ( - IN IDE_BLK_IO_DEV *IdeDev, - IN ATA_DRIVE_PARMS *DriveParameters - ) -{ - EFI_STATUS Status; - UINT8 DeviceSelect; - - DeviceSelect = 0; - DeviceSelect = (UINT8) ((IdeDev->Device) << 4); - - // - // Send Init drive parameters - // - Status = AtaNonDataCommandIn ( - IdeDev, - ATA_CMD_INIT_DRIVE_PARAM, - (UINT8) (DeviceSelect + DriveParameters->Heads), - 0, - DriveParameters->Sector, - 0, - 0, - 0 - ); - - // - // Send Set Multiple parameters - // - Status = AtaNonDataCommandIn ( - IdeDev, - ATA_CMD_SET_MULTIPLE_MODE, - DeviceSelect, - 0, - DriveParameters->MultipleSector, - 0, - 0, - 0 - ); - return Status; -} - -/** - Enable Interrupt on IDE controller. - - @param IdeDev Standard IDE device private data structure - - @retval EFI_SUCCESS Enable Interrupt successfully -**/ -EFI_STATUS -EnableInterrupt ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - UINT8 DeviceControl; - - // - // Enable interrupt for DMA operation - // - DeviceControl = 0; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h deleted file mode 100644 index 2b7e6ea5eb..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h +++ /dev/null @@ -1,835 +0,0 @@ -/** @file - Header file for IDE Bus Driver, containing the helper functions' - prototype. - - Copyright (c) 2006 - 2007, Intel 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. - - @par Revision Reference: - 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including - Add - IDEBlkIoReadBlocksExt() func definition - Add - IDEBlkIoWriteBlocksExt() func definition - -**/ - -#ifndef _IDE_H_ -#define _IDE_H_ - -// -// Helper functions Prototype -// -/** - read a one-byte data from a IDE port. - - @param PciIo The PCI IO protocol instance - @param Port the IDE Port number - - return the one-byte data read from IDE port -**/ -UINT8 -IDEReadPortB ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port - ); - -/** - Reads multiple words of data from the IDE data port. - Call the IO abstraction once to do the complete read, - not one word at a time. - - @param PciIo Pointer to the EFI_PCI_IO instance - @param Port IO port to read - @param Count No. of UINT16's to read - @param Buffer Pointer to the data buffer for read - -**/ -VOID -IDEReadPortWMultiple ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINTN Count, - OUT VOID *Buffer - ); - -/** - write a 1-byte data to a specific IDE port. - - @param PciIo PCI IO protocol instance - @param Port The IDE port to be writen - @param Data The data to write to the port -**/ -VOID -IDEWritePortB ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINT8 Data - ); - -/** - write a 1-word data to a specific IDE port. - - @param PciIo PCI IO protocol instance - @param Port The IDE port to be writen - @param Data The data to write to the port -**/ -VOID -IDEWritePortW ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINT16 Data - ); - -/** - Write multiple words of data to the IDE data port. - Call the IO abstraction once to do the complete read, - not one word at a time. - - @param PciIo Pointer to the EFI_PCI_IO instance - @param Port IO port to read - @param Count No. of UINT16's to read - @param Buffer Pointer to the data buffer for read - -**/ -VOID -IDEWritePortWMultiple ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINTN Count, - IN VOID *Buffer - ); - -/** - Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode, - use fixed addresses. In Native-PCI mode, get base addresses from BARs in - the PCI IDE controller's Configuration Space. - - The steps to get IDE IO port registers' base addresses for each channel - as follows: - - 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE - controller's Configuration Space to determine the operating mode. - - 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below. -
-  ___________________________________________
-  |           | Command Block | Control Block |
-  |  Channel  |   Registers   |   Registers   |
-  |___________|_______________|_______________|
-  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |
-  |___________|_______________|_______________|
-  | Secondary |  170h - 177h  |  376h - 377h  |
-  |___________|_______________|_______________|
-
-  Table 1. Compatibility resource mappings
-  
- - b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs - in IDE controller's PCI Configuration Space, shown in the Table 2 below. -
-  ___________________________________________________
-  |           |   Command Block   |   Control Block   |
-  |  Channel  |     Registers     |     Registers     |
-  |___________|___________________|___________________|
-  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|
-  |___________|___________________|___________________|
-  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
-  |___________|___________________|___________________|
-
-  Table 2. BARs for Register Mapping
-  
- @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for - primary, 0374h for secondary. So 2 bytes extra offset should be - added to the base addresses read from BARs. - - For more details, please refer to PCI IDE Controller Specification and Intel - ICH4 Datasheet. - - @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance - @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to - receive IDE IO port registers' base addresses - - @retval EFI_UNSUPPORTED return this value when the BARs is not IO type - @retval EFI_SUCCESS Get the Base address successfully - @retval other read the pci configureation data error - -**/ -EFI_STATUS -GetIdeRegistersBaseAddr ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr - ); - -/** - This function is used to requery IDE resources. The IDE controller will - probably switch between native and legacy modes during the EFI->CSM->OS - transfer. We do this everytime before an BlkIo operation to ensure its - succeess. - - @param IdeDev The BLK_IO private data which specifies the IDE device - - @retval EFI_INVALID_PARAMETER return this value when the channel is invalid - @retval EFI_SUCCESS reassign the IDE IO resource successfully - @retval other get the IDE current base address effor - -**/ -EFI_STATUS -ReassignIdeResources ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - Detect if there is disk attached to this port. - - @param IdeDev The BLK_IO private data which specifies the IDE device. - - @retval EFI_NOT_FOUND The device or channel is not found - @retval EFI_SUCCESS The device is found - -**/ -EFI_STATUS -DiscoverIdeDevice ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - This interface is used to initialize all state data related to the - detection of one channel. - -**/ -VOID -InitializeIDEChannelData ( - VOID - ); - -/** - This function is used to poll for the DRQ bit clear in the Status - Register. DRQ is cleared when the device is finished transferring data. - So this function is called after data transfer is finished. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. - - @retval EFI_SUCCESS DRQ bit clear within the time out. - - @retval EFI_TIMEOUT DRQ bit not clear within the time out. - - @note - Read Status Register will clear interrupt status. - -**/ -EFI_STATUS -DRQClear ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ); - -/** - This function is used to poll for the DRQ bit clear in the Alternate - Status Register. DRQ is cleared when the device is finished - transferring data. So this function is called after data transfer - is finished. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. - - @retval EFI_SUCCESS DRQ bit clear within the time out. - - @retval EFI_TIMEOUT DRQ bit not clear within the time out. - @note - Read Alternate Status Register will not clear interrupt status. - -**/ -EFI_STATUS -DRQClear2 ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ); - -/** - This function is used to poll for the DRQ bit set in the - Status Register. - DRQ is set when the device is ready to transfer data. So this function - is called after the command is sent to the device and before required - data is transferred. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to - record all the information of the IDE device. - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS DRQ bit set within the time out. - @retval EFI_TIMEOUT DRQ bit not set within the time out. - @retval EFI_ABORTED DRQ bit not set caused by the command abort. - - @note Read Status Register will clear interrupt status. - -**/ -EFI_STATUS -DRQReady ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ); - -/** - This function is used to poll for the DRQ bit set in the Alternate Status Register. - DRQ is set when the device is ready to transfer data. So this function is called after - the command is sent to the device and before required data is transferred. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to - record all the information of the IDE device. - - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS DRQ bit set within the time out. - @retval EFI_TIMEOUT DRQ bit not set within the time out. - @retval EFI_ABORTED DRQ bit not set caused by the command abort. - @note Read Alternate Status Register will not clear interrupt status. - -**/ -EFI_STATUS -DRQReady2 ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ); - -/** - This function is used to poll for the BSY bit clear in the Status Register. BSY - is clear when the device is not busy. Every command must be sent after device is not busy. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS BSY bit clear within the time out. - @retval EFI_TIMEOUT BSY bit not clear within the time out. - - @note Read Status Register will clear interrupt status. -**/ -EFI_STATUS -WaitForBSYClear ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ); - -/** - This function is used to poll for the BSY bit clear in the Alternate Status Register. - BSY is clear when the device is not busy. Every command must be sent after device is - not busy. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS BSY bit clear within the time out. - @retval EFI_TIMEOUT BSY bit not clear within the time out. - @note Read Alternate Status Register will not clear interrupt status. - -**/ -EFI_STATUS -WaitForBSYClear2 ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN TimeoutInMilliSeconds - ); - -/** - This function is used to poll for the DRDY bit set in the Status Register. DRDY - bit is set when the device is ready to accept command. Most ATA commands must be - sent after DRDY set except the ATAPI Packet Command. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS DRDY bit set within the time out. - @retval EFI_TIMEOUT DRDY bit not set within the time out. - - @note Read Status Register will clear interrupt status. -**/ -EFI_STATUS -DRDYReady ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN DelayInMilliSeconds - ); - -/** - This function is used to poll for the DRDY bit set in the Alternate Status Register. - DRDY bit is set when the device is ready to accept command. Most ATA commands must - be sent after DRDY set except the ATAPI Packet Command. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS DRDY bit set within the time out. - @retval EFI_TIMEOUT DRDY bit not set within the time out. - - @note Read Alternate Status Register will clear interrupt status. - -**/ -EFI_STATUS -DRDYReady2 ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN DelayInMilliSeconds - ); - -// -// ATA device functions' prototype -// -/** - Sends out an ATA Identify Command to the specified device. - - This function is called by DiscoverIdeDevice() during its device - identification. It sends out the ATA Identify Command to the - specified device. Only ATA device responses to this command. If - the command succeeds, it returns the Identify data structure which - contains information about the device. This function extracts the - information it needs to fill the IDE_BLK_IO_DEV data structure, - including device type, media block size, media capacity, and etc. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record - all the information of the IDE device. - - @retval EFI_SUCCESS Identify ATA device successfully. - @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device. - @note parameter IdeDev will be updated in this function. - -**/ -EFI_STATUS -ATAIdentify ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - This function is called by ATAIdentify() or ATAPIIdentify() to print device's module name. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. -**/ -VOID -PrintAtaModuleName ( - IN IDE_BLK_IO_DEV *IdeDev - ); -/** - This function is used to send out ATA commands conforms to the PIO Data In Protocol. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @param Buffer buffer contained data transferred from device to host. - @param ByteCount data size in byte unit of the buffer. - @param AtaCommand value of the Command Register - @param Head value of the Head/Device Register - @param SectorCount value of the Sector Count Register - @param SectorNumber value of the Sector Number Register - @param CylinderLsb value of the low byte of the Cylinder Register - @param CylinderMsb value of the high byte of the Cylinder Register - - @retval EFI_SUCCESS send out the ATA command and device send required data successfully. - @retval EFI_DEVICE_ERROR command sent failed. - -**/ -EFI_STATUS -AtaPioDataIn ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN UINT8 Head, - IN UINT8 SectorCount, - IN UINT8 SectorNumber, - IN UINT8 CylinderLsb, - IN UINT8 CylinderMsb - ); - -/** - This function is used to send out ATA commands conforms to the - PIO Data Out Protocol. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param *Buffer buffer contained data transferred from host to device. - @param ByteCount data size in byte unit of the buffer. - @param AtaCommand value of the Command Register - @param Head value of the Head/Device Register - @param SectorCount value of the Sector Count Register - @param SectorNumber value of the Sector Number Register - @param CylinderLsb value of the low byte of the Cylinder Register - @param CylinderMsb value of the high byte of the Cylinder Register - - @retval EFI_SUCCESS send out the ATA command and device received required - data successfully. - @retval EFI_DEVICE_ERROR command sent failed. - -**/ -EFI_STATUS -AtaPioDataOut ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN UINT8 Head, - IN UINT8 SectorCount, - IN UINT8 SectorNumber, - IN UINT8 CylinderLsb, - IN UINT8 CylinderMsb - ); - -/** - This function is used to analyze the Status Register and print out - some debug information and if there is ERR bit set in the Status - Register, the Error Register's value is also be parsed and print out. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to - record all the information of the IDE device. - - @retval EFI_SUCCESS No err information in the Status Register. - @retval EFI_DEVICE_ERROR Any err information in the Status Register. - -**/ -EFI_STATUS -CheckErrorStatus ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - This function is used to implement the Soft Reset on the specified device. But, - the ATA Soft Reset mechanism is so strong a reset method that it will force - resetting on both devices connected to the same cable. - - It is called by IdeBlkIoReset(), a interface function of Block - I/O protocol. - - This function can also be used by the ATAPI device to perform reset when - ATAPI Reset command is failed. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record - all the information of the IDE device. - @retval EFI_SUCCESS Soft reset completes successfully. - @retval EFI_DEVICE_ERROR Any step during the reset process is failed. - - @note The registers initial values after ATA soft reset are different - to the ATA device and ATAPI device. -**/ -EFI_STATUS -AtaSoftReset ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - This function is the ATA implementation for ReadBlocks in the - Block I/O Protocol interface. - - @param IdeBlkIoDevice Indicates the calling context. - @param MediaId The media id that the read request is for. - @param Lba The starting logical block address to read from on the device. - @param BufferSize The size of the Buffer in bytes. This must be a multiple - of the intrinsic block size of the device. - - @param Buffer A pointer to the destination buffer for the data. The caller - is responsible for either having implicit or explicit ownership - of the memory that data is read into. - - @retval EFI_SUCCESS Read Blocks successfully. - @retval EFI_DEVICE_ERROR Read Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, - or the data buffer is not valid. - - @note If Read Block error because of device error, this function will call - AtaSoftReset() function to reset device. - -**/ -EFI_STATUS -AtaBlkIoReadBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - This function is the ATA implementation for WriteBlocks in the - Block I/O Protocol interface. - - @param IdeBlkIoDevice Indicates the calling context. - @param MediaId The media id that the write request is for. - @param Lba The starting logical block address to write onto the device. - @param BufferSize The size of the Buffer in bytes. This must be a multiple - of the intrinsic block size of the device. - @param Buffer A pointer to the source buffer for the data.The caller - is responsible for either having implicit or explicit - ownership of the memory that data is written from. - - @retval EFI_SUCCESS Write Blocks successfully. - @retval EFI_DEVICE_ERROR Write Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, - or the data buffer is not valid. - - @note If Write Block error because of device error, this function will call - AtaSoftReset() function to reset device. -**/ -EFI_STATUS -AtaBlkIoWriteBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - This function is called by DiscoverIdeDevice() during its device - identification. - Its main purpose is to get enough information for the device media - to fill in the Media data structure of the Block I/O Protocol interface. - - There are 5 steps to reach such objective: - 1. Sends out the ATAPI Identify Command to the specified device. - Only ATAPI device responses to this command. If the command succeeds, - it returns the Identify data structure which filled with information - about the device. Since the ATAPI device contains removable media, - the only meaningful information is the device module name. - 2. Sends out ATAPI Inquiry Packet Command to the specified device. - This command will return inquiry data of the device, which contains - the device type information. - 3. Allocate sense data space for future use. We don't detect the media - presence here to improvement boot performance, especially when CD - media is present. The media detection will be performed just before - each BLK_IO read/write - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS Identify ATAPI device successfully. - @retval EFI_DEVICE_ERROR ATAPI Identify Device Command failed or device type - is not supported by this IDE driver. - @retval EFI_OUT_OF_RESOURCES Allocate memory for sense data failed - - @note Parameter "IdeDev" will be updated in this function. -**/ -EFI_STATUS -ATAPIIdentify ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - This function is used to implement the Soft Reset on the specified - ATAPI device. Different from the AtaSoftReset(), here reset is a ATA - Soft Reset Command special for ATAPI device, and it only take effects - on the specified ATAPI device, not on the whole IDE bus. - Since the ATAPI soft reset is needed when device is in exceptional - condition (such as BSY bit is always set ), I think the Soft Reset - command should be sent without waiting for the BSY clear and DRDY - set. - This function is called by IdeBlkIoReset(), - a interface function of Block I/O protocol. - - @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS Soft reset completes successfully. - @retval EFI_DEVICE_ERROR Any step during the reset process is failed. - -**/ -EFI_STATUS -AtapiSoftReset ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - This function is the ATAPI implementation for ReadBlocks in the - Block I/O Protocol interface. - - @param IdeBlkIoDevice Indicates the calling context. - @param MediaId The media id that the read request is for. - @param Lba The starting logical block address to read from on the device. - @param BufferSize The size of the Buffer in bytes. This must be a multiple - of the intrinsic block size of the device. - @param Buffer A pointer to the destination buffer for the data. The caller - is responsible for either having implicit or explicit - ownership of the memory that data is read into. - - @retval EFI_SUCCESS Read Blocks successfully. - @retval EFI_DEVICE_ERROR Read Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, - or the data buffer is not valid. -**/ -EFI_STATUS -AtapiBlkIoReadBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - This function is the ATAPI implementation for WriteBlocks in the - Block I/O Protocol interface. - - @param IdeBlkIoDevice Indicates the calling context. - @param MediaId The media id that the write request is for. - @param Lba The starting logical block address to write onto the device. - @param BufferSize The size of the Buffer in bytes. This must be a multiple - of the intrinsic block size of the device. - @param Buffer A pointer to the source buffer for the data. The caller - is responsible for either having implicit or explicit ownership - of the memory that data is written from. - - @retval EFI_SUCCESS Write Blocks successfully. - @retval EFI_DEVICE_ERROR Write Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, - or the data buffer is not valid. - - @retval EFI_WRITE_PROTECTED The write protected is enabled or the media does not support write -**/ -EFI_STATUS -AtapiBlkIoWriteBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - Release resources of an IDE device before stopping it. - - @param IdeBlkIoDevice Standard IDE device private data structure - -**/ -VOID -ReleaseIdeResources ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice - ); - -/** - Set the calculated Best transfer mode to a detected device - - @param IdeDev Standard IDE device private data structure - @param TransferMode The device transfer mode to be set - @return Set transfer mode Command execute status. -**/ -EFI_STATUS -SetDeviceTransferMode ( - IN IDE_BLK_IO_DEV *IdeDev, - IN ATA_TRANSFER_MODE *TransferMode - ); -/** - Send ATA command into device with NON_DATA protocol. - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaLow The value in LBA_LOW register - @param LbaMiddle The value in LBA_MIDDLE register - @param LbaHigh The value in LBA_HIGH register - - @retval EFI_SUCCESS Reading succeed - @retval EFI_ABORTED Command failed - @retval EFI_DEVICE_ERROR Device status error. - -**/ -EFI_STATUS -AtaNonDataCommandIn ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT8 Feature, - IN UINT8 SectorCount, - IN UINT8 LbaLow, - IN UINT8 LbaMiddle, - IN UINT8 LbaHigh - ); - -/** - Send ATA Ext command into device with NON_DATA protocol. - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaAddress The Lba address in 48-bit mode - - @retval EFI_SUCCESS Reading succeed - @retval EFI_ABORTED Command failed - @retval EFI_DEVICE_ERROR Device status error. - -**/ -EFI_STATUS -AtaNonDataCommandInExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ); -/** - Enable Long Physical Sector Feature for ATA device. - - @param IdeDev The IDE device data - - @retval EFI_SUCCESS The ATA device supports Long Physical Sector feature - and corresponding fields in BlockIo structure is updated. - @retval EFI_UNSUPPORTED The device is not ATA device or Long Physical Sector - feature is not supported. -**/ -EFI_STATUS -AtaEnableLongPhysicalSector ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - Set drive parameters for devices not support PACKETS command. - - @param IdeDev Standard IDE device private data structure - @param DriveParameters The device parameters to be set into the disk - @return SetParameters Command execute status. - -**/ -EFI_STATUS -SetDriveParameters ( - IN IDE_BLK_IO_DEV *IdeDev, - IN ATA_DRIVE_PARMS *DriveParameters - ); - -/** - Enable Interrupt on IDE controller. - - @param IdeDev Standard IDE device private data structure - - @retval EFI_SUCCESS Enable Interrupt successfully -**/ -EFI_STATUS -EnableInterrupt ( - IN IDE_BLK_IO_DEV *IdeDev - ); -#endif diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c deleted file mode 100644 index 82fd44f17d..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c +++ /dev/null @@ -1,1571 +0,0 @@ -/** @file - This file implement UEFI driver for IDE Bus which includes device identification, - Child device(Disk, CDROM, etc) enumeration and child handler installation, and - driver stop. - - 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 - 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. - - @par Revision Reference: - This module is modified from DXE\IDE module for Ide Contriller Init support - -**/ - -#include "IdeBus.h" - -#define PCI_CLASS_MASS_STORAGE 0x01 -#define PCI_SUB_CLASS_IDE 0x01 - - -// -// IDE Bus Driver Binding Protocol Instance -// -EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = { - IDEBusDriverBindingSupported, - IDEBusDriverBindingStart, - IDEBusDriverBindingStop, - 0xa, - NULL, - NULL -}; -/** - Deregister an IDE device and free resources - - @param This Protocol instance pointer. - @param Controller Ide device handle - @param Handle Handle of device to deregister driver on - - @retval EFI_SUCCESS Deregiter a specific IDE device successfully - - -**/ -EFI_STATUS -DeRegisterIdeDevice ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_HANDLE Handle - ) -{ - EFI_STATUS Status; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_PCI_IO_PROTOCOL *PciIo; - UINTN Index; - - Status = gBS->OpenProtocol ( - Handle, - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); - - // - // Report Status code: Device disabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE), - IdeBlkIoDevice->DevicePath - ); - - // - // Close the child handle - // - Status = gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Handle - ); - - Status = gBS->UninstallMultipleProtocolInterfaces ( - Handle, - &gEfiDevicePathProtocolGuid, - IdeBlkIoDevice->DevicePath, - &gEfiBlockIoProtocolGuid, - &IdeBlkIoDevice->BlkIo, - &gEfiDiskInfoProtocolGuid, - &IdeBlkIoDevice->DiskInfo, - NULL - ); - - if (EFI_ERROR (Status)) { - gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - return Status; - } - - // - // Release allocated resources - // - Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device; - if (Index < MAX_IDE_DEVICE) { - IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE; - } - ReleaseIdeResources (IdeBlkIoDevice); - - return EFI_SUCCESS; -} -/** - Supported function of Driver Binding protocol for this driver. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param ControllerHandle The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS Driver loaded. - @retval other Driver not loaded. - -**/ -EFI_STATUS -EFIAPI -IDEBusDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_DEV_PATH *Node; - EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 PciData; - - if (RemainingDevicePath != NULL) { - Node = (EFI_DEV_PATH *) RemainingDevicePath; - // - // Check if RemainingDevicePath is the End of Device Path Node, - // if yes, go on checking other conditions - // - if (!IsDevicePathEnd (Node)) { - // - // If RemainingDevicePath isn't the End of Device Path Node, - // check its validation - // - if (Node->DevPath.Type != MESSAGING_DEVICE_PATH || - Node->DevPath.SubType != MSG_ATAPI_DP || - DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) { - return EFI_UNSUPPORTED; - } - } - } - - // - // Verify the Ide Controller Init Protocol, which installed by the - // IdeController module. - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - (VOID **) &IdeInit, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - - if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Close the I/O Abstraction(s) used to perform the supported test - // - gBS->CloseProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Open the EFI Device Path protocol needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; - } - - // - // Close protocol, don't use device path protocol in the Support() function - // - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Get the EfiPciIoProtocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Now further check the PCI header: Base class (offset 0x0B) and - // Sub Class (offset 0x0A). This controller should be an IDE controller - // - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint8, - 0, - sizeof (PciData), - &PciData - ); - - if (!EFI_ERROR (Status)) { - // - // Examine if it is IDE mode by class code - // - if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) || (PciData.Hdr.ClassCode[1] != PCI_SUB_CLASS_IDE)) { - Status = EFI_UNSUPPORTED; - } else { - Status = EFI_SUCCESS; - } - } - - return Status; -} - - -/** - Start function of Driver binding protocol which start this driver on Controller - by detecting all disks and installing BlockIo protocol on them. - - @param This Protocol instance pointer. - @param Controller Handle of device to bind driver to. - @param RemainingDevicePath produce all possible children. - - @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 -IDEBusDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_STATUS SavedStatus; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_DEV_PATH *Node; - UINT8 IdeChannel; - UINT8 BeginningIdeChannel; - UINT8 EndIdeChannel; - UINT8 IdeDevice; - UINT8 BeginningIdeDevice; - UINT8 EndIdeDevice; - IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice]; - IDE_BLK_IO_DEV *IdeBlkIoDevicePtr; - IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; - ATA_TRANSFER_MODE TransferMode; - ATA_DRIVE_PARMS DriveParameters; - EFI_DEV_PATH NewNode; - UINT8 ConfigurationOptions; - UINT16 CommandBlockBaseAddr; - UINT16 ControlBlockBaseAddr; - UINTN DataSize; - IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; - UINT64 Supports; - - // - // Local variables declaration for IdeControllerInit support - // - EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; - BOOLEAN EnumAll; - BOOLEAN ChannelEnabled; - UINT8 MaxDevices; - EFI_IDENTIFY_DATA IdentifyData; - EFI_ATA_COLLECTIVE_MODE *SupportedModes; - - IdeBusDriverPrivateData = NULL; - SupportedModes = NULL; - - // - // Perform IdeBus initialization - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { - return Status; - } - - // - // Now open the IDE_CONTROLLER_INIT protocol. Step7.1 - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - (VOID **) &IdeInit, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - - // - // The following OpenProtocol function with _GET_PROTOCOL attribute and - // will not return EFI_ALREADY_STARTED, so save it for now - // - SavedStatus = Status; - - if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { - DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status)); - // - // open protocol is not SUCCESS or not ALREADY_STARTED, error exit - // - goto ErrorExit; - } - - // - // Save Enumall. Step7.2 - // - EnumAll = IdeInit->EnumAll; - - // - // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL - // attribute will not return EFI_ALREADY_STARTED - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status)); - goto ErrorExit; - } - - // - // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable - // - if (SavedStatus != EFI_ALREADY_STARTED) { - IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); - if (IdeBusDriverPrivateData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiCallerIdGuid, - IdeBusDriverPrivateData, - NULL - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - } else { - Status = gBS->OpenProtocol ( - Controller, - &gEfiCallerIdGuid, - (VOID **) &IdeBusDriverPrivateData, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - IdeBusDriverPrivateData = NULL; - goto ErrorExit; - } - } - - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - } - - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - // - // Read the environment variable that contains the IDEBus Driver's - // Config options that were set by the Driver Configuration Protocol - // - DataSize = sizeof (ConfigurationOptions); - Status = gRT->GetVariable ( - (CHAR16 *) L"Configuration", - &gEfiCallerIdGuid, - NULL, - &DataSize, - &ConfigurationOptions - ); - if (EFI_ERROR (Status)) { - ConfigurationOptions = 0x0f; - } - - if (EnumAll || RemainingDevicePath == NULL) { - // - // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL, - // must enumerate all IDE devices anyway - // - BeginningIdeChannel = IdePrimary; - EndIdeChannel = IdeSecondary; - BeginningIdeDevice = IdeMaster; - EndIdeDevice = IdeSlave; - - } else if (!IsDevicePathEnd (RemainingDevicePath)) { - // - // If RemainingDevicePath isn't the End of Device Path Node, - // only scan the specified device by RemainingDevicePath - // - Node = (EFI_DEV_PATH *) RemainingDevicePath; - BeginningIdeChannel = Node->Atapi.PrimarySecondary; - EndIdeChannel = BeginningIdeChannel; - BeginningIdeDevice = Node->Atapi.SlaveMaster; - EndIdeDevice = BeginningIdeDevice; - if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) { - Status = EFI_INVALID_PARAMETER; - goto ErrorExit; - } - if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) { - Status = EFI_INVALID_PARAMETER; - goto ErrorExit; - } - - } else { - // - // If RemainingDevicePath is the End of Device Path Node, - // skip enumerate any device and return EFI_SUCESSS - // - BeginningIdeChannel = IdeMaxChannel; - EndIdeChannel = IdeMaxChannel - 1; - BeginningIdeDevice = IdeMaxDevice; - EndIdeDevice = IdeMaxDevice - 1; - } - - // - // Obtain IDE IO port registers' base addresses - // - Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - // - // Report status code: begin IdeBus initialization - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), - ParentDevicePath - ); - - // - // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol - // - for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { - - IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel); - - // - // now obtain channel information fron IdeControllerInit protocol. Step9 - // - Status = IdeInit->GetChannelInfo ( - IdeInit, - IdeChannel, - &ChannelEnabled, - &MaxDevices - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status)); - continue; - } - - if (!ChannelEnabled) { - continue; - } - - EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice); - ASSERT (EndIdeDevice < IdeMaxDevice); - // - // Now inform the IDE Controller Init Module. Sept10 - // - IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel); - - // - // No reset channel function implemented. Sept11 - // - IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel); - - // - // Step13 - // - IdeInit->NotifyPhase ( - IdeInit, - EfiIdeBusBeforeDevicePresenceDetection, - IdeChannel - ); - - // - // Prepare to detect IDE device of this channel - // - InitializeIDEChannelData (); - - // - // -- 1st inner loop --- Master/Slave ------------ Step14 - // - for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { - // - // Check whether the configuration options allow this device - // - if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) { - continue; - } - - // - // The device has been scanned in another Start(), No need to scan it again - // for perf optimization. - // - if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) { - continue; - } - - // - // create child handle for the detected device. - // - IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV)); - if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) { - continue; - } - - IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; - - ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV)); - - IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE; - IdeBlkIoDevicePtr->Channel = (EFI_IDE_CHANNEL) IdeChannel; - IdeBlkIoDevicePtr->Device = (EFI_IDE_DEVICE) IdeDevice; - - // - // initialize Block IO interface's Media pointer - // - IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia; - - // - // Initialize IDE IO port addresses, including Command Block registers - // and Control Block registers - // - IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS)); - if (IdeBlkIoDevicePtr->IoPort == NULL) { - continue; - } - - ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS)); - CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr; - ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr; - - IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr; - (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); - IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); - IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); - IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); - IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); - IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); - (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); - - (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr; - IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); - - IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0); - - IdeBlkIoDevicePtr->PciIo = PciIo; - IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData; - IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr; - - // - // Report Status code: is about to detect IDE drive - // - REPORT_STATUS_CODE_EX ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT), - 0, - &gEfiCallerIdGuid, - NULL, - NULL, - 0 - ); - - // - // Discover device, now! - // - PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0); - Status = DiscoverIdeDevice (IdeBlkIoDevicePtr); - PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0); - - IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE; - IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE; - - if (!EFI_ERROR (Status)) { - // - // Set Device Path - // - ZeroMem (&NewNode, sizeof (NewNode)); - NewNode.DevPath.Type = MESSAGING_DEVICE_PATH; - NewNode.DevPath.SubType = MSG_ATAPI_DP; - SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH)); - - NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel; - NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device; - NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun; - IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode ( - ParentDevicePath, - &NewNode.DevPath - ); - if (IdeBlkIoDevicePtr->DevicePath == NULL) { - ReleaseIdeResources (IdeBlkIoDevicePtr); - continue; - } - - // - // Submit identify data to IDE controller init driver - // - CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData)); - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE; - IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData); - } else { - // - // Device detection failed - // - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; - IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL); - ReleaseIdeResources (IdeBlkIoDevicePtr); - IdeBlkIoDevicePtr = NULL; - } - // - // end of 1st inner loop --- - // - } - // - // end of 1st outer loop ========= - // - } - - // - // = 2nd outer loop == Primary/Secondary ================= - // - for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { - - // - // -- 2nd inner loop --- Master/Slave -------- - // - for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { - - ASSERT (IdeChannel * 2 + IdeDevice < MAX_IDE_DEVICE); - if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) { - continue; - } - - if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) { - continue; - } - - Status = IdeInit->CalculateMode ( - IdeInit, - IdeChannel, - IdeDevice, - &SupportedModes - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status)); - continue; - } - - ASSERT (IdeChannel < IdeMaxChannel && IdeDevice < IdeMaxDevice); - IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; - - // - // Set best supported PIO mode on this IDE device - // - if (SupportedModes->PioMode.Mode <= AtaPioMode2) { - TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO; - } else { - TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO; - } - - TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode); - - if (SupportedModes->ExtModeCount == 0){ - Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); - - if (EFI_ERROR (Status)) { - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; - ReleaseIdeResources (IdeBlkIoDevicePtr); - IdeBlkIoDevicePtr = NULL; - continue; - } - } - - // - // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't - // be set together. Only one DMA mode can be set to a device. If setting - // DMA mode operation fails, we can continue moving on because we only use - // PIO mode at boot time. DMA modes are used by certain kind of OS booting - // - if (SupportedModes->UdmaMode.Valid) { - - TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA; - TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode); - Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); - - if (EFI_ERROR (Status)) { - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; - ReleaseIdeResources (IdeBlkIoDevicePtr); - IdeBlkIoDevicePtr = NULL; - continue; - } - // - // Record Udma Mode - // - IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE; - IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode; - EnableInterrupt (IdeBlkIoDevicePtr); - } else if (SupportedModes->MultiWordDmaMode.Valid) { - - TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA; - TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode; - Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); - - if (EFI_ERROR (Status)) { - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; - ReleaseIdeResources (IdeBlkIoDevicePtr); - IdeBlkIoDevicePtr = NULL; - continue; - } - - EnableInterrupt (IdeBlkIoDevicePtr); - } - // - // Init driver parameters - // - DriveParameters.Sector = (UINT8) ((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->sectors_per_track; - DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->heads - 1); - DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt; - // - // Set Parameters for the device: - // 1) Init - // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command - // - if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) { - Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters); - } - - // - // Record PIO mode used in private data - // - IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode; - - // - // Set IDE controller Timing Blocks in the PCI Configuration Space - // - IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes); - - // - // Add Component Name for the IDE/ATAPI device that was discovered. - // - IdeBlkIoDevicePtr->ControllerNameTable = NULL; - ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr); - - Status = gBS->InstallMultipleProtocolInterfaces ( - &IdeBlkIoDevicePtr->Handle, - &gEfiDevicePathProtocolGuid, - IdeBlkIoDevicePtr->DevicePath, - &gEfiBlockIoProtocolGuid, - &IdeBlkIoDevicePtr->BlkIo, - &gEfiDiskInfoProtocolGuid, - &IdeBlkIoDevicePtr->DiskInfo, - NULL - ); - - if (EFI_ERROR (Status)) { - ReleaseIdeResources (IdeBlkIoDevicePtr); - } - - gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - IdeBlkIoDevicePtr->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - - IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE; - - // - // Report status code: device eanbled! - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE), - IdeBlkIoDevicePtr->DevicePath - ); - - // - // Create event to clear pending IDE interrupt - // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - ClearInterrupt, - IdeBlkIoDevicePtr, - &gEfiEventExitBootServicesGuid, - &IdeBlkIoDevicePtr->ExitBootServiceEvent - ); - - // - // end of 2nd inner loop ---- - // - } - // - // end of 2nd outer loop ========== - // - } - - // - // All configurations done! Notify IdeController to do post initialization - // work such as saving IDE controller PCI settings for S3 resume - // - IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0); - - if (SupportedModes != NULL) { - FreePool (SupportedModes); - } - - PERF_START (NULL, "Finish IDE detection", "IDE", 1); - PERF_END (NULL, "Finish IDE detection", "IDE", 0); - - return EFI_SUCCESS; - -ErrorExit: - - // - // Report error code: controller error - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR), - ParentDevicePath - ); - - gBS->CloseProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiCallerIdGuid, - IdeBusDriverPrivateData, - NULL - ); - - if (IdeBusDriverPrivateData != NULL) { - gBS->FreePool (IdeBusDriverPrivateData); - } - - if (SupportedModes != NULL) { - gBS->FreePool (SupportedModes); - } - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; - -} -/** - Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all - child handle attached to the controller handle if there are. - - @param This Protocol instance pointer. - @param Controller Handle of device to stop driver on - @param NumberOfChildren Not used - @param ChildHandleBuffer Not used - - @retval EFI_SUCCESS This driver is removed DeviceHandle - @retval other This driver was not removed from this device - -**/ -EFI_STATUS -EFIAPI -IDEBusDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - BOOLEAN AllChildrenStopped; - UINTN Index; - IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; - UINT64 Supports; - - IdeBusDriverPrivateData = NULL; - - if (NumberOfChildren == 0) { - - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE); - PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationDisable, - Supports, - NULL - ); - } - } - - gBS->OpenProtocol ( - Controller, - &gEfiCallerIdGuid, - (VOID **) &IdeBusDriverPrivateData, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiCallerIdGuid, - IdeBusDriverPrivateData, - NULL - ); - - if (IdeBusDriverPrivateData != NULL) { - gBS->FreePool (IdeBusDriverPrivateData); - } - // - // Close the bus driver - // - gBS->CloseProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return EFI_SUCCESS; - } - - AllChildrenStopped = TRUE; - - for (Index = 0; Index < NumberOfChildren; Index++) { - - Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]); - - if (EFI_ERROR (Status)) { - AllChildrenStopped = FALSE; - } - } - - if (!AllChildrenStopped) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - issue ATA or ATAPI command to reset a block IO device. - @param This Block IO protocol instance pointer. - @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method - If TRUE, for ATAPI device, driver need invoke ATA reset method after - invoke ATAPI reset method - - @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device. - @retval EFI_SUCCESS The device reset successfully - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoReset ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_STATUS Status; - EFI_TPL OldTpl; - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); - // - // Requery IDE IO resources in case of the switch of native and legacy modes - // - ReassignIdeResources (IdeBlkIoDevice); - - // - // for ATA device, using ATA reset method - // - if (IdeBlkIoDevice->Type == IdeHardDisk || - IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - Status = AtaSoftReset (IdeBlkIoDevice); - goto Done; - } - - if (IdeBlkIoDevice->Type == IdeUnknown) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - - // - // for ATAPI device, using ATAPI reset method - // - Status = AtapiSoftReset (IdeBlkIoDevice); - if (ExtendedVerification) { - Status = AtaSoftReset (IdeBlkIoDevice); - } - -Done: - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - Read data from a block IO device - - @param This Block IO protocol instance pointer. - @param MediaId The media ID of the device - @param Lba Starting LBA address to read data - @param BufferSize The size of data to be read - @param Buffer Caller supplied buffer to save data - - @retval EFI_DEVICE_ERROR unknown device type - @retval other read data status. - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_STATUS Status; - EFI_TPL OldTpl; - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); - - // - // Requery IDE IO resources in case of the switch of native and legacy modes - // - ReassignIdeResources (IdeBlkIoDevice); - - // - // For ATA compatible device, use ATA read block's mechanism - // - if (IdeBlkIoDevice->Type == IdeHardDisk || - IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - Status = AtaBlkIoReadBlocks ( - IdeBlkIoDevice, - MediaId, - Lba, - BufferSize, - Buffer - ); - goto Done; - } - - if (IdeBlkIoDevice->Type == IdeUnknown) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - - // - // for ATAPI device, using ATAPI read block's mechanism - // - Status = AtapiBlkIoReadBlocks ( - IdeBlkIoDevice, - MediaId, - Lba, - BufferSize, - Buffer - ); - -Done: - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Write data to block io device. - - @param This Protocol instance pointer. - @param MediaId The media ID of the device - @param Lba Starting LBA address to write data - @param BufferSize The size of data to be written - @param Buffer Caller supplied buffer to save data - - @retval EFI_DEVICE_ERROR unknown device type - @retval other write data status - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - IN VOID *Buffer - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_STATUS Status; - EFI_TPL OldTpl; - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); - // - // Requery IDE IO resources in case of the switch of native and legacy modes - // - ReassignIdeResources (IdeBlkIoDevice); - - // - // for ATA device, using ATA write block's mechanism - // - if (IdeBlkIoDevice->Type == IdeHardDisk || - IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - - Status = AtaBlkIoWriteBlocks ( - IdeBlkIoDevice, - MediaId, - Lba, - BufferSize, - Buffer - ); - goto Done; - } - - if (IdeBlkIoDevice->Type == IdeUnknown) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - - // - // for ATAPI device, using ATAPI write block's mechanism - // - Status = AtapiBlkIoWriteBlocks ( - IdeBlkIoDevice, - MediaId, - Lba, - BufferSize, - Buffer - ); - -Done: - gBS->RestoreTPL (OldTpl); - return Status; -} -/** - Flushes all modified data to a physical block devices - - @param This Indicates a pointer to the calling context which to sepcify a - sepcific block device - - @retval EFI_SUCCESS Always return success. -**/ -EFI_STATUS -EFIAPI -IDEBlkIoFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ) -{ - // - // return directly - // - return EFI_SUCCESS; -} - -/** - This function is used by the IDE bus driver to get inquiry data. - Data format of Identify data is defined by the Interface GUID. - - @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param InquiryData Pointer to a buffer for the inquiry data. - @param InquiryDataSize Pointer to the value for the inquiry data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading InquiryData from device - @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoInquiry ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *InquiryData, - IN OUT UINT32 *InquiryDataSize - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); - - if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) { - *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA); - return EFI_BUFFER_TOO_SMALL; - } - - if (IdeBlkIoDevice->InquiryData == NULL) { - return EFI_NOT_FOUND; - } - - gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA)); - *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA); - - return EFI_SUCCESS; -} - -/** - This function is used by the IDE bus driver to get identify data. - Data format of Identify data is defined by the Interface GUID. - - @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param IdentifyData Pointer to a buffer for the identify data. - @param IdentifyDataSize Pointer to the value for the identify data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading IdentifyData from device - @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoIdentify ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *IdentifyData, - IN OUT UINT32 *IdentifyDataSize - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); - - if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) { - *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA); - return EFI_BUFFER_TOO_SMALL; - } - - if (IdeBlkIoDevice->IdData == NULL) { - return EFI_NOT_FOUND; - } - - gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA)); - *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA); - - return EFI_SUCCESS; -} - -/** - This function is used by the IDE bus driver to get sense data. - Data format of Sense data is defined by the Interface GUID. - - @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param SenseData Pointer to the SenseData. - @param SenseDataSize Size of SenseData in bytes. - @param SenseDataNumber Pointer to the value for the identify data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading InquiryData from device - @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoSenseData ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *SenseData, - IN OUT UINT32 *SenseDataSize, - OUT UINT8 *SenseDataNumber - ) -{ - return EFI_NOT_FOUND; -} - -/** - This function is used by the IDE bus driver to get controller information. - - @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param IdeChannel Pointer to the Ide Channel number. Primary or secondary. - @param IdeDevice Pointer to the Ide Device number. Master or slave. - - @retval EFI_SUCCESS IdeChannel and IdeDevice are valid - @retval EFI_UNSUPPORTED This is not an IDE device - -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoWhichIde ( - IN EFI_DISK_INFO_PROTOCOL *This, - OUT UINT32 *IdeChannel, - OUT UINT32 *IdeDevice - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); - *IdeChannel = IdeBlkIoDevice->Channel; - *IdeDevice = IdeBlkIoDevice->Device; - - return EFI_SUCCESS; -} - -/** - The is an event(generally the event is exitBootService event) call back function. - Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. - - @param Event Pointer to this event - @param Context Event handler private data - -**/ -VOID -EFIAPI -ClearInterrupt ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - UINT64 IoPortForBmis; - UINT8 RegisterValue; - IDE_BLK_IO_DEV *IdeDev; - - // - // Get our context - // - IdeDev = (IDE_BLK_IO_DEV *) Context; - - // - // Obtain IDE IO port registers' base addresses - // - Status = ReassignIdeResources (IdeDev); - if (EFI_ERROR (Status)) { - return; - } - - // - // Check whether interrupt is pending - // - - // - // Reset IDE device to force it de-assert interrupt pin - // Note: this will reset all devices on this IDE channel - // - Status = AtaSoftReset (IdeDev); - if (EFI_ERROR (Status)) { - return; - } - - // - // Get base address of IDE Bus Master Status Regsiter - // - if (IdePrimary == IdeDev->Channel) { - IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; - } else { - if (IdeSecondary == IdeDev->Channel) { - IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; - } else { - return; - } - } - // - // Read BMIS register and clear ERROR and INTR bit - // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - - RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); - - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - - // - // Select the other device on this channel to ensure this device to release the interrupt pin - // - if (IdeDev->Device == 0) { - RegisterValue = (1 << 4) | 0xe0; - } else { - RegisterValue = (0 << 4) | 0xe0; - } - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - RegisterValue - ); - -} - -/** - The user Entry Point for module IdeBus. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -InitializeIdeBus( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallAllDriverProtocols2 ( - ImageHandle, - SystemTable, - &gIDEBusDriverBinding, - ImageHandle, - &gIDEBusComponentName, - &gIDEBusComponentName2, - NULL, - NULL, - &gIDEBusDriverDiagnostics, - &gIDEBusDriverDiagnostics2 - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h deleted file mode 100644 index a3db16ca85..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h +++ /dev/null @@ -1,540 +0,0 @@ -/** @file - Header file for IDE Bus 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. - -**/ - -#ifndef _IDE_BUS_H_ -#define _IDE_BUS_H_ - - - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include "IdeData.h" - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding; -extern EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics; -extern EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gIDEBusDriverDiagnostics2; - -// -// Extra Definition to porting -// -#define MAX_IDE_DEVICE 4 -#define MAX_IDE_CHANNELS 2 -#define MAX_IDE_DRIVES 2 - -#define INVALID_DEVICE_TYPE 0xff -#define ATA_DEVICE_TYPE 0x00 -#define ATAPI_DEVICE_TYPE 0x01 - -typedef struct { - BOOLEAN HaveScannedDevice[MAX_IDE_DEVICE]; - BOOLEAN DeviceFound[MAX_IDE_DEVICE]; - BOOLEAN DeviceProcessed[MAX_IDE_DEVICE]; -} IDE_BUS_DRIVER_PRIVATE_DATA; - -#define IDE_BLK_IO_DEV_SIGNATURE SIGNATURE_32 ('i', 'b', 'i', 'd') - -typedef struct { - UINT32 Signature; - - EFI_HANDLE Handle; - EFI_BLOCK_IO_PROTOCOL BlkIo; - EFI_BLOCK_IO_MEDIA BlkMedia; - EFI_DISK_INFO_PROTOCOL DiskInfo; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; - IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; - - // - // Local Data for IDE interface goes here - // - EFI_IDE_CHANNEL Channel; - EFI_IDE_DEVICE Device; - UINT16 Lun; - IDE_DEVICE_TYPE Type; - - IDE_BASE_REGISTERS *IoPort; - UINT16 AtapiError; - - ATAPI_INQUIRY_DATA *InquiryData; - EFI_IDENTIFY_DATA *IdData; - ATA_PIO_MODE PioMode; - EFI_ATA_MODE UdmaMode; - CHAR8 ModelName[41]; - ATAPI_REQUEST_SENSE_DATA *SenseData; - UINT8 SenseDataNumber; - UINT8 *Cache; - - // - // ExitBootService Event, it is used to clear pending IDE interrupt - // - EFI_EVENT ExitBootServiceEvent; - - EFI_UNICODE_STRING_TABLE *ControllerNameTable; -} IDE_BLK_IO_DEV; - -#include "ComponentName.h" - -#define IDE_BLOCK_IO_DEV_FROM_THIS(a) CR (a, IDE_BLK_IO_DEV, BlkIo, IDE_BLK_IO_DEV_SIGNATURE) -#define IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS(a) CR (a, IDE_BLK_IO_DEV, DiskInfo, IDE_BLK_IO_DEV_SIGNATURE) - -#include "Ide.h" - - -/** - Supported function of Driver Binding protocol for this driver. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param ControllerHandle The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS Driver loaded. - @retval other Driver not loaded. - -**/ -EFI_STATUS -EFIAPI -IDEBusDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Start function of Driver binding protocol which start this driver on Controller - by detecting all disks and installing BlockIo protocol on them. - - @param This Protocol instance pointer. - @param Controller Handle of device to bind driver to. - @param RemainingDevicePath produce all possible children. - - @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 -IDEBusDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all - child handle attached to the controller handle if there are. - - @param This Protocol instance pointer. - @param Controller Handle of device to stop driver on - @param NumberOfChildren Not used - @param ChildHandleBuffer Not used - - @retval EFI_SUCCESS This driver is removed DeviceHandle - @retval other This driver was not removed from this device - -**/ -EFI_STATUS -EFIAPI -IDEBusDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// EFI Driver Configuration Functions -// -/** - Allows the user to set controller specific options for a controller that a - driver is currently managing. - - @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. - @param ControllerHandle The handle of the controller to set options on. - @param ChildHandle The handle of the child controller to set options on. - This is an optional parameter that may be NULL. - It will be NULL for device drivers, and for a bus drivers - that wish to set options for the bus controller. - It will not be NULL for a bus driver that wishes to set - options for one of its child controllers. - @param Language A pointer to a three character ISO 639-2 language identifier. - This is the language of the user interface that should be presented - to the user, 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 ActionRequired A pointer to the action that the calling agent is required - to perform when this function returns. - - - @retval EFI_SUCCESS The driver specified by This successfully set the configuration - options for the controller specified by ControllerHandle.. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ActionRequired is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support setting configuration options for - the controller specified by ControllerHandle and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the language specified by Language. - @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the configuration options for the - controller specified by ControllerHandle and ChildHandle. - @retval EFI_OUT_RESOURCES There are not enough resources available to set the configuration options for the - controller specified by ControllerHandle and ChildHandle -**/ -EFI_STATUS -EFIAPI -IDEBusDriverConfigurationSetOptions ( - IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired - ); - -/** - Tests to see if a controller's current configuration options are valid. - - @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. - @param ControllerHandle The handle of the controller to test if it's current configuration options - are valid. - @param ChildHandle The handle of the child controller to test if it's current configuration - options are valid. 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 test the configuration options for the bus controller. It will - not be NULL for a bus driver that wishes to test configuration options for - one of its child controllers. - @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle that is being - managed by the driver specified by This has a valid set of configuration - options. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. - @retval EFI_UNSUPPORTED The driver specified by This is not currently managing the controller - specified by ControllerHandle and ChildHandle. - @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle that is being - managed by the driver specified by This has an invalid set of configuration - options. -**/ -EFI_STATUS -EFIAPI -IDEBusDriverConfigurationOptionsValid ( - IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL - ); - -/** - Forces a driver to set the default configuration options for a controller. - - @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. - @param ControllerHandle The handle of the controller to force default configuration options on. - @param ChildHandle The handle of the child controller to force default configuration - options on 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 force default configuration options for the bus - controller. It will not be NULL for a bus driver that wishes to force - default configuration options for one of its child controllers. - @param DefaultType The type of default configuration options to force on the controller - specified by ControllerHandle and ChildHandle. - @param ActionRequired A pointer to the action that the calling agent is required to perform - when this function returns. - - @retval EFI_SUCCESS The driver specified by This successfully forced the - default configuration options on the controller specified by - ControllerHandle and ChildHandle. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ActionRequired is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default - configuration options on the controller specified by ControllerHandle - and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type - specified by DefaultType. - @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration - options on the controller specified by ControllerHandle and ChildHandle. - @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration - options on the controller specified by ControllerHandle and ChildHandle. -**/ -EFI_STATUS -EFIAPI -IDEBusDriverConfigurationForceDefaults ( - IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN UINT32 DefaultType, - OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired - ); - -// -// EFI Driver Diagnostics Functions -// -/** - Runs diagnostics on a controller. - - @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance. - @param ControllerHandle The handle of the controller to run diagnostics on. - @param ChildHandle The handle of the child controller to run diagnostics on - 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 run diagnostics on the bus controller. - It will not be NULL for a bus driver that wishes to run - diagnostics on one of its child controllers. - @param DiagnosticType Indicates type of diagnostics to perform on the controller - specified by ControllerHandle and ChildHandle. - @param Language A pointer to a three character ISO 639-2 language identifier. - This is the language in which the optional error message should - be returned in Buffer, 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 ErrorType A GUID that defines the format of the data returned in Buffer. - @param BufferSize The size, in bytes, of the data returned in Buffer. - @param Buffer A buffer that contains a Null-terminated Unicode string - plus some additional data whose format is defined by ErrorType. - Buffer is allocated by this function with AllocatePool(), and - it is the caller's responsibility to free it with a call to FreePool(). - - @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle passed - the diagnostic. - @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 ErrorType is NULL. - @retval EFI_INVALID_PARAMETER BufferType is NULL. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support running - diagnostics for the controller specified by ControllerHandle - and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - type of diagnostic specified by DiagnosticType. - @retval EFI_UNSUPPORTED The driver specified by This does not support the language - specified by Language. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete the - diagnostics. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return the - status information in ErrorType, BufferSize,and Buffer. - @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle - did not pass the diagnostic. -**/ -EFI_STATUS -EFIAPI -IDEBusDriverDiagnosticsRunDiagnostics ( - IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, - IN CHAR8 *Language, - OUT EFI_GUID **ErrorType, - OUT UINTN *BufferSize, - OUT CHAR16 **Buffer - ); - -/** - issue ATA or ATAPI command to reset a block IO device. - @param This Block IO protocol instance pointer. - @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method - If TRUE, for ATAPI device, driver need invoke ATA reset method after - invoke ATAPI reset method - - @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device. - @retval EFI_SUCCESS The device reset successfully - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoReset ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Read data from a block IO device. - - @param This Block IO protocol instance pointer. - @param MediaId The media ID of the device - @param Lba Starting LBA address to read data - @param BufferSize The size of data to be read - @param Buffer Caller supplied buffer to save data - - @retval EFI_DEVICE_ERROR unknown device type - @retval EFI_SUCCESS read the data successfully. - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - Write data to block io device - - @param This Protocol instance pointer. - @param MediaId The media ID of the device - @param Lba Starting LBA address to write data - @param BufferSize The size of data to be written - @param Buffer Caller supplied buffer to save data - - @retval EFI_DEVICE_ERROR unknown device type - @retval other write data status - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - IN VOID *Buffer - ); - -/** - Flushes all modified data to a physical block devices - - @param This Indicates a pointer to the calling context which to sepcify a - sepcific block device - - @retval EFI_SUCCESS Always return success. -**/ -EFI_STATUS -EFIAPI -IDEBlkIoFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ); -/** - This function is used by the IDE bus driver to get inquiry data. - Data format of Identify data is defined by the Interface GUID. - - @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param InquiryData Pointer to a buffer for the inquiry data. - @param InquiryDataSize Pointer to the value for the inquiry data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading InquiryData from device - @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoInquiry ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *InquiryData, - IN OUT UINT32 *InquiryDataSize - ); - -/** - This function is used by the IDE bus driver to get identify data. - Data format of Identify data is defined by the Interface GUID. - - @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param IdentifyData Pointer to a buffer for the identify data. - @param IdentifyDataSize Pointer to the value for the identify data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading IdentifyData from device - @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoIdentify ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *IdentifyData, - IN OUT UINT32 *IdentifyDataSize - ); - -/** - This function is used by the IDE bus driver to get sense data. - Data format of Sense data is defined by the Interface GUID. - - @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param SenseData Pointer to the SenseData. - @param SenseDataSize Size of SenseData in bytes. - @param SenseDataNumber Pointer to the value for the identify data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading InquiryData from device - @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoSenseData ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *SenseData, - IN OUT UINT32 *SenseDataSize, - OUT UINT8 *SenseDataNumber - ); - -/** - This function is used by the IDE bus driver to get controller information. - - @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param IdeChannel Pointer to the Ide Channel number. Primary or secondary. - @param IdeDevice Pointer to the Ide Device number. Master or slave. - - @retval EFI_SUCCESS IdeChannel and IdeDevice are valid - @retval EFI_UNSUPPORTED This is not an IDE device - -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoWhichIde ( - IN EFI_DISK_INFO_PROTOCOL *This, - OUT UINT32 *IdeChannel, - OUT UINT32 *IdeDevice - ); -/** - The is an event(generally the event is exitBootService event) call back function. - Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. - - @param Event Pointer to this event - @param Context Event handler private data - -**/ -VOID -EFIAPI -ClearInterrupt ( - IN EFI_EVENT Event, - IN VOID *Context - ); -#endif diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf deleted file mode 100644 index 8beea2d9ca..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf +++ /dev/null @@ -1,88 +0,0 @@ -## @file -# IDE bus driver. -# -# This driver will enumerate IDE device and export the blockIo protocol for every device. -# -# 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 -# 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 = IdeBusDxe - MODULE_UNI_FILE = IdeBusDxe.uni - FILE_GUID = 69FD8E47-A161-4550-B01A-5594CEB2B2B2 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializeIdeBus - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# -# DRIVER_BINDING = gIDEBusDriverBinding -# COMPONENT_NAME = gIDEBusComponentName -# COMPONENT_NAME2 = gIDEBusComponentName2 -# Variable Guid C Name: gConfigurationGuid Variable Name: L"Configuration" -# -# - -[Sources] - DriverDiagnostics.c - DriverConfiguration.c - ComponentName.h - ComponentName.c - Atapi.c - Ata.c - Ide.c - IdeBus.c - IdeData.h - Ide.h - IdeBus.h - - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - - -[LibraryClasses] - DevicePathLib - UefiRuntimeServicesTableLib - UefiBootServicesTableLib - PerformanceLib - MemoryAllocationLib - ReportStatusCodeLib - BaseMemoryLib - UefiLib - BaseLib - UefiDriverEntryPoint - DebugLib - - -[Guids] - gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # DiskInfo Interface Guid - gEfiEventExitBootServicesGuid ## CONSUMES ## Event - - -[Protocols] - gEfiDiskInfoProtocolGuid ## BY_START - gEfiBlockIoProtocolGuid ## BY_START - gEfiIdeControllerInitProtocolGuid ## TO_START - gEfiPciIoProtocolGuid ## TO_START - ## TO_START - ## BY_START - gEfiDevicePathProtocolGuid - -[UserExtensions.TianoCore."ExtraFiles"] - IdeBusDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.uni b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.uni deleted file mode 100644 index ebe7f19e75..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni deleted file mode 100644 index 24ad99a10e..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeData.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeData.h deleted file mode 100644 index 487fe6f3ea..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeData.h +++ /dev/null @@ -1,311 +0,0 @@ -/** @file - Header file for IDE Bus Driver's Data Structures - - Copyright (c) 2006 - 2007, Intel 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 _IDE_DATA_H_ -#define _IDE_DATA_H_ - -#include - -// -// common constants -// -#define STALL_1_MILLI_SECOND 1000 // stall 1 ms -#define STALL_1_SECOND 1000000 // stall 1 second -typedef enum { - IdePrimary = 0, - IdeSecondary = 1, - IdeMaxChannel = 2 -} EFI_IDE_CHANNEL; - -typedef enum { - IdeMaster = 0, - IdeSlave = 1, - IdeMaxDevice = 2 -} EFI_IDE_DEVICE; - -typedef enum { - IdeMagnetic, /* ZIP Drive or LS120 Floppy Drive */ - IdeCdRom, /* ATAPI CDROM */ - IdeHardDisk, /* Hard Disk */ - Ide48bitAddressingHardDisk, /* Hard Disk larger than 120GB */ - IdeUnknown -} IDE_DEVICE_TYPE; - -typedef enum { - SenseNoSenseKey, - SenseDeviceNotReadyNoRetry, - SenseDeviceNotReadyNeedRetry, - SenseNoMedia, - SenseMediaChange, - SenseMediaError, - SenseOtherSense -} SENSE_RESULT; - -typedef enum { - AtaUdmaReadOp, - AtaUdmaReadExtOp, - AtaUdmaWriteOp, - AtaUdmaWriteExtOp -} ATA_UDMA_OPERATION; - -// -// IDE Registers -// -typedef union { - UINT16 Command; /* when write */ - UINT16 Status; /* when read */ -} IDE_CMD_OR_STATUS; - -typedef union { - UINT16 Error; /* when read */ - UINT16 Feature; /* when write */ -} IDE_ERROR_OR_FEATURE; - -typedef union { - UINT16 AltStatus; /* when read */ - UINT16 DeviceControl; /* when write */ -} IDE_ALTSTATUS_OR_DEVICECONTROL; - -// -// IDE registers set -// -typedef struct { - UINT16 Data; - IDE_ERROR_OR_FEATURE Reg1; - UINT16 SectorCount; - UINT16 SectorNumber; - UINT16 CylinderLsb; - UINT16 CylinderMsb; - UINT16 Head; - IDE_CMD_OR_STATUS Reg; - - IDE_ALTSTATUS_OR_DEVICECONTROL Alt; - UINT16 DriveAddress; - - UINT16 MasterSlave; - UINT16 BusMasterBaseAddr; -} IDE_BASE_REGISTERS; - -// -// IDE registers' base addresses -// -typedef struct { - UINT16 CommandBlockBaseAddr; - UINT16 ControlBlockBaseAddr; - UINT16 BusMasterBaseAddr; -} IDE_REGISTERS_BASE_ADDR; - -// -// Bit definitions in Programming Interface byte of the Class Code field -// in PCI IDE controller's Configuration Space -// -#define IDE_PRIMARY_OPERATING_MODE BIT0 -#define IDE_PRIMARY_PROGRAMMABLE_INDICATOR BIT1 -#define IDE_SECONDARY_OPERATING_MODE BIT2 -#define IDE_SECONDARY_PROGRAMMABLE_INDICATOR BIT3 - - -// -// Bus Master Reg -// -#define BMIC_NREAD BIT3 -#define BMIC_START BIT0 -#define BMIS_INTERRUPT BIT2 -#define BMIS_ERROR BIT1 - -#define BMICP_OFFSET 0x00 -#define BMISP_OFFSET 0x02 -#define BMIDP_OFFSET 0x04 -#define BMICS_OFFSET 0x08 -#define BMISS_OFFSET 0x0A -#define BMIDS_OFFSET 0x0C - -// -// Time Out Value For IDE Device Polling -// - -// -// ATATIMEOUT is used for waiting time out for ATA device -// - -// -// 1 second -// -#define ATATIMEOUT 1000 - -// -// ATAPITIMEOUT is used for waiting operation -// except read and write time out for ATAPI device -// - -// -// 1 second -// -#define ATAPITIMEOUT 1000 - -// -// ATAPILONGTIMEOUT is used for waiting read and -// write operation timeout for ATAPI device -// - -// -// 2 seconds -// -#define CDROMLONGTIMEOUT 2000 - -// -// 5 seconds -// -#define ATAPILONGTIMEOUT 5000 - -// -// 10 seconds -// -#define ATASMARTTIMEOUT 10000 - - -// -// ATAPI6 related data structure definition -// - -// -// The maximum sectors count in 28 bit addressing mode -// -#define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff - -#pragma pack(1) - -typedef struct { - UINT32 RegionBaseAddr; - UINT16 ByteCount; - UINT16 EndOfTable; -} IDE_DMA_PRD; - -#pragma pack() - -#define SETFEATURE TRUE -#define CLEARFEATURE FALSE - -/// -/// PIO mode definition -/// -typedef enum _ATA_PIO_MODE_ { - AtaPioModeBelow2, - AtaPioMode2, - AtaPioMode3, - AtaPioMode4 -} ATA_PIO_MODE; - -// -// Multi word DMA definition -// -typedef enum _ATA_MDMA_MODE_ { - AtaMdmaMode0, - AtaMdmaMode1, - AtaMdmaMode2 -} ATA_MDMA_MODE; - -// -// UDMA mode definition -// -typedef enum _ATA_UDMA_MODE_ { - AtaUdmaMode0, - AtaUdmaMode1, - AtaUdmaMode2, - AtaUdmaMode3, - AtaUdmaMode4, - AtaUdmaMode5 -} ATA_UDMA_MODE; - -#define ATA_MODE_CATEGORY_DEFAULT_PIO 0x00 -#define ATA_MODE_CATEGORY_FLOW_PIO 0x01 -#define ATA_MODE_CATEGORY_MDMA 0x04 -#define ATA_MODE_CATEGORY_UDMA 0x08 - -#pragma pack(1) - -typedef struct { - UINT8 ModeNumber : 3; - UINT8 ModeCategory : 5; -} ATA_TRANSFER_MODE; - -typedef struct { - UINT8 Sector; - UINT8 Heads; - UINT8 MultipleSector; -} ATA_DRIVE_PARMS; - -#pragma pack() -// -// IORDY Sample Point field value -// -#define ISP_5_CLK 0 -#define ISP_4_CLK 1 -#define ISP_3_CLK 2 -#define ISP_2_CLK 3 - -// -// Recovery Time field value -// -#define RECVY_4_CLK 0 -#define RECVY_3_CLK 1 -#define RECVY_2_CLK 2 -#define RECVY_1_CLK 3 - -// -// Slave IDE Timing Register Enable -// -#define SITRE BIT14 - -// -// DMA Timing Enable Only Select 1 -// -#define DTE1 BIT7 - -// -// Pre-fetch and Posting Enable Select 1 -// -#define PPE1 BIT6 - -// -// IORDY Sample Point Enable Select 1 -// -#define IE1 BIT5 - -// -// Fast Timing Bank Drive Select 1 -// -#define TIME1 BIT4 - -// -// DMA Timing Enable Only Select 0 -// -#define DTE0 BIT3 - -// -// Pre-fetch and Posting Enable Select 0 -// -#define PPE0 BIT2 - -// -// IOREY Sample Point Enable Select 0 -// -#define IE0 BIT1 - -// -// Fast Timing Bank Drive Select 0 -// -#define TIME0 BIT0 - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/ComponentName.c deleted file mode 100644 index e495d96af8..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/ComponentName.c +++ /dev/null @@ -1,168 +0,0 @@ -/** @file - Implements EFI Component Name Protocol for VGA Mini Port 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 "VgaMiniPort.h" - - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPciVgaMiniPortComponentName = { - PciVgaMiniPortComponentNameGetDriverName, - PciVgaMiniPortComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciVgaMiniPortComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciVgaMiniPortComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciVgaMiniPortComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPciVgaMiniPortDriverNameTable[] = { - { - "eng;en", - L"PCI VGA Mini Port Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - @param Language 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 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 -PciVgaMiniPortComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mPciVgaMiniPortDriverNameTable, - DriverName, - (BOOLEAN)(This == &gPciVgaMiniPortComponentName) - ); -} - -/** - 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 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - 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 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 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 -PciVgaMiniPortComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c b/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c deleted file mode 100644 index 25d1e3beb7..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.c +++ /dev/null @@ -1,331 +0,0 @@ -/** @file - Implements EFI Driver Binding Protocol and VGA Mini Port Protocol for VGA Mini Port Driver. - -Copyright (c) 2006 - 2009, Intel 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 "VgaMiniPort.h" - -// -// EFI Driver Binding Protocol Instance -// -// This driver has a version value of 0x00000000. This is the -// lowest possible priority for a driver. This is done on purpose to help -// the developers of UGA drivers. This driver can bind if no UGA driver -// is present, so a console is available. Then, when a UGA driver is loaded -// this driver can be disconnected, and the UGA driver can be connected. -// As long as the UGA driver has a version value greater than 0x00000000, it -// will be connected first and will block this driver from connecting. -// -EFI_DRIVER_BINDING_PROTOCOL gPciVgaMiniPortDriverBinding = { - PciVgaMiniPortDriverBindingSupported, - PciVgaMiniPortDriverBindingStart, - PciVgaMiniPortDriverBindingStop, - 0x00000000, - NULL, - NULL -}; - -/** - Entrypoint of VGA Mini Port Driver. - - This function is the entrypoint of UVGA Mini Port Driver. It installs Driver Binding - Protocols together with Component Name Protocols. - - @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. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortDriverEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gPciVgaMiniPortDriverBinding, - ImageHandle, - &gPciVgaMiniPortComponentName, - &gPciVgaMiniPortComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - return EFI_SUCCESS; -} - - -/** - Check whether VGA Mini Port driver supports this device. - - @param This The driver binding protocol. - @param Controller The controller handle to check. - @param RemainingDevicePath The remaining device path. - - @retval EFI_SUCCESS The driver supports this controller. - @retval EFI_UNSUPPORTED This device isn't supported. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // See if this is a PCI VGA Controller by looking at the Command register and - // Class Code Register - // - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (Pci) / sizeof (UINT32), - &Pci - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = EFI_UNSUPPORTED; - // - // See if the device is an enabled VGA device. - // Most systems can only have on VGA device on at a time. - // - if (((Pci.Hdr.Command & 0x03) == 0x03) && IS_PCI_VGA (&Pci)) { - Status = EFI_SUCCESS; - } - -Done: - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - - -/** - Starts the VGA device with this driver. - - This function consumes PCI I/O Protocol, and installs VGA Mini Port Protocol - onto the VGA device handle. - - @param This The driver binding instance. - @param Controller The controller to check. - @param RemainingDevicePath The remaining device patch. - - @retval EFI_SUCCESS The controller is controlled by the driver. - @retval EFI_ALREADY_STARTED The controller is already controlled by the driver. - @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_VGA_MINI_PORT_DEV *PciVgaMiniPortPrivate; - - PciVgaMiniPortPrivate = NULL; - PciIo = NULL; - // - // Open the IO Abstraction(s) needed - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Allocate the private device structure - // - PciVgaMiniPortPrivate = AllocateZeroPool (sizeof (PCI_VGA_MINI_PORT_DEV)); - ASSERT (PciVgaMiniPortPrivate != NULL); - - // - // Initialize the private device structure - // - PciVgaMiniPortPrivate->Signature = PCI_VGA_MINI_PORT_DEV_SIGNATURE; - PciVgaMiniPortPrivate->Handle = Controller; - PciVgaMiniPortPrivate->PciIo = PciIo; - - PciVgaMiniPortPrivate->VgaMiniPort.SetMode = PciVgaMiniPortSetMode; - PciVgaMiniPortPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000; - PciVgaMiniPortPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4; - PciVgaMiniPortPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5; - PciVgaMiniPortPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR; - PciVgaMiniPortPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; - PciVgaMiniPortPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; - PciVgaMiniPortPrivate->VgaMiniPort.MaxMode = 1; - - // - // Install VGA Mini Port Protocol - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiVgaMiniPortProtocolGuid, - &PciVgaMiniPortPrivate->VgaMiniPort, - NULL - ); -Done: - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - if (PciVgaMiniPortPrivate != NULL) { - FreePool (PciVgaMiniPortPrivate); - } - } - - return Status; -} - - -/** - Stop the VGA device with this driver. - - This function uninstalls VGA Mini Port Protocol from the VGA device handle, - and closes PCI I/O Protocol. - - @param This The driver binding protocol. - @param Controller The controller to release. - @param NumberOfChildren The child number that opened controller - BY_CHILD. - @param ChildHandleBuffer The array of child handle. - - @retval EFI_SUCCESS The controller or children are stopped. - @retval EFI_DEVICE_ERROR Failed to stop the driver. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; - PCI_VGA_MINI_PORT_DEV *PciVgaMiniPortPrivate; - - Status = gBS->OpenProtocol ( - Controller, - &gEfiVgaMiniPortProtocolGuid, - (VOID **) &VgaMiniPort, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - PciVgaMiniPortPrivate = PCI_VGA_MINI_PORT_DEV_FROM_THIS (VgaMiniPort); - - Status = gBS->UninstallProtocolInterface ( - Controller, - &gEfiVgaMiniPortProtocolGuid, - &PciVgaMiniPortPrivate->VgaMiniPort - ); - if (EFI_ERROR (Status)) { - return Status; - } - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - FreePool (PciVgaMiniPortPrivate); - - return EFI_SUCCESS; -} -// -// VGA Mini Port Protocol Functions -// - -/** - Sets the text display mode of a VGA controller. - - This function implements EFI_VGA_MINI_PORT_PROTOCOL.SetMode(). - If ModeNumber exceeds the valid range, then EFI_UNSUPPORTED is returned. - Otherwise, EFI_SUCCESS is directly returned without real operation. - - @param This Protocol instance pointer. - @param ModeNumber Mode number. 0 - 80x25 1-80x50 - - @retval EFI_SUCCESS The mode was set - @retval EFI_UNSUPPORTED ModeNumber is not supported. - @retval EFI_DEVICE_ERROR The device is not functioning properly. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortSetMode ( - IN EFI_VGA_MINI_PORT_PROTOCOL *This, - IN UINTN ModeNumber - ) -{ - if (ModeNumber > This->MaxMode) { - return EFI_UNSUPPORTED; - } - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h b/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h deleted file mode 100644 index f39c00364b..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.h +++ /dev/null @@ -1,271 +0,0 @@ -/** @file - Internal include file for VGA Mini Port 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. - -**/ - -#ifndef _VGA_MINIPORT_H_ -#define _VGA_MINIPORT_H_ - -// -// The package level header files this module uses -// -#include -// -// The protocols, PPI and GUID defintions for this module -// -#include -#include -#include - - -// -// The Library classes this module consumes -// -#include -#include -#include -#include -#include -#include - -#include - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gPciVgaMiniPortDriverBinding; -extern EFI_COMPONENT_NAME_PROTOCOL gPciVgaMiniPortComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gPciVgaMiniPortComponentName2; - -// -// PCI VGA MiniPort Device Structure -// -#define PCI_VGA_MINI_PORT_DEV_SIGNATURE SIGNATURE_32('P','V','M','P') - -typedef struct { - UINTN Signature; - EFI_HANDLE Handle; - EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort; - EFI_PCI_IO_PROTOCOL *PciIo; -} PCI_VGA_MINI_PORT_DEV; - -#define PCI_VGA_MINI_PORT_DEV_FROM_THIS(a) CR(a, PCI_VGA_MINI_PORT_DEV, VgaMiniPort, PCI_VGA_MINI_PORT_DEV_SIGNATURE) - -// -// Driver Binding Protocol functions -// -/** - Check whether VGA Mini Port driver supports this device. - - @param This The driver binding protocol. - @param Controller The controller handle to check. - @param RemainingDevicePath The remaining device path. - - @retval EFI_SUCCESS The driver supports this controller. - @retval EFI_UNSUPPORTED This device isn't supported. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Starts the VGA device with this driver. - - This function consumes PCI I/O Protocol, and installs VGA Mini Port Protocol - onto the VGA device handle. - - @param This The driver binding instance. - @param Controller The controller to check. - @param RemainingDevicePath The remaining device patch. - - @retval EFI_SUCCESS The controller is controlled by the driver. - @retval EFI_ALREADY_STARTED The controller is already controlled by the driver. - @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Stop the VGA device with this driver. - - This function uninstalls VGA Mini Port Protocol from the VGA device handle, - and closes PCI I/O Protocol. - - @param This The driver binding protocol. - @param Controller The controller to release. - @param NumberOfChildren The child number that opened controller - BY_CHILD. - @param ChildHandleBuffer The array of child handle. - - @retval EFI_SUCCESS The controller or children are stopped. - @retval EFI_DEVICE_ERROR Failed to stop the driver. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// EFI Component Name Functions -// -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - @param Language 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 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 -PciVgaMiniPortComponentNameGetDriverName ( - 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 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - 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 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 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 -PciVgaMiniPortComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -// -// VGA Mini Port Protocol functions -// -/** - Sets the text display mode of a VGA controller. - - This function implements EFI_VGA_MINI_PORT_PROTOCOL.SetMode(). - If ModeNumber exceeds the valid range, then EFI_UNSUPPORTED is returned. - Otherwise, EFI_SUCCESS is directly returned without real operation. - - @param This Protocol instance pointer. - @param ModeNumber Mode number. 0 - 80x25 1-80x50 - - @retval EFI_SUCCESS The mode was set - @retval EFI_UNSUPPORTED ModeNumber is not supported. - @retval EFI_DEVICE_ERROR The device is not functioning properly. - -**/ -EFI_STATUS -EFIAPI -PciVgaMiniPortSetMode ( - IN EFI_VGA_MINI_PORT_PROTOCOL *This, - IN UINTN ModeNumber - ); - -#endif diff --git a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni b/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni deleted file mode 100644 index ca9d2446d6..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPort.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf b/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf deleted file mode 100644 index d3c35faa6c..0000000000 --- a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf +++ /dev/null @@ -1,57 +0,0 @@ -## @file -# VGA Mini Port Driver that manages VGA device and produces VGA Mini Port 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 -# 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 = VgaMiniPort - MODULE_UNI_FILE = VgaMiniPort.uni - FILE_GUID = 15C5E761-58D8-461a-9173-CAB020916264 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = PciVgaMiniPortDriverEntryPoint - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# DRIVER_BINDING = gPciVgaMiniPortDriverBinding; -# COMPONENT_NAME = gPciVgaMiniPortComponentName; -# COMPONENT_NAME2 = gPciVgaMiniPortComponentName2; -# - -[Sources] - ComponentName.c - VgaMiniPort.c - VgaMiniPort.h - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - UefiLib - DebugLib - UefiBootServicesTableLib - UefiDriverEntryPoint - BaseMemoryLib - MemoryAllocationLib - -[Protocols] - gEfiPciIoProtocolGuid ## TO_START - gEfiVgaMiniPortProtocolGuid ## BY_START - -[UserExtensions.TianoCore."ExtraFiles"] - VgaMiniPortExtra.uni diff --git a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni b/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni deleted file mode 100644 index 731713fbc6..0000000000 Binary files a/IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Contributions.txt b/IntelFrameworkModulePkg/Contributions.txt deleted file mode 100644 index f87cbd73c6..0000000000 --- a/IntelFrameworkModulePkg/Contributions.txt +++ /dev/null @@ -1,218 +0,0 @@ - -====================== -= Code Contributions = -====================== - -To make a contribution to a TianoCore project, follow these steps. -1. Create a change description in the format specified below to - use in the source control commit log. -2. Your commit message must include your "Signed-off-by" signature, - and "Contributed-under" message. -3. Your "Contributed-under" message explicitly states that the - contribution is made under the terms of the specified - contribution agreement. Your "Contributed-under" message - must include the name of contribution agreement and version. - For example: Contributed-under: TianoCore Contribution Agreement 1.0 - The "TianoCore Contribution Agreement" is included below in - this document. -4. Submit your code to the TianoCore project using the process - that the project documents on its web page. If the process is - not documented, then submit the code on development email list - for the project. -5. It is preferred that contributions are submitted using the same - copyright license as the base project. When that is not possible, - then contributions using the following licenses can be accepted: - * BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause - * BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause - * MIT: http://opensource.org/licenses/MIT - * Python-2.0: http://opensource.org/licenses/Python-2.0 - * Zlib: http://opensource.org/licenses/Zlib - - Contributions of code put into the public domain can also be - accepted. - - Contributions using other licenses might be accepted, but further - review will be required. - -===================================================== -= Change Description / Commit Message / Patch Email = -===================================================== - -Your change description should use the standard format for a -commit message, and must include your "Signed-off-by" signature -and the "Contributed-under" message. - -== Sample Change Description / Commit Message = - -=== Start of sample patch email message === - -From: Contributor Name -Subject: [PATCH] CodeModule: Brief-single-line-summary - -Full-commit-message - -Contributed-under: TianoCore Contribution Agreement 1.0 -Signed-off-by: Contributor Name ---- - -An extra message for the patch email which will not be considered part -of the commit message can be added here. - -Patch content inline or attached - -=== End of sample patch email message === - -=== Notes for sample patch email === - -* The first line of commit message is taken from the email's subject - line following [PATCH]. The remaining portion of the commit message - is the email's content until the '---' line. -* git format-patch is one way to create this format - -=== Definitions for sample patch email === - -* "CodeModule" is a short idenfier for the affected code. For - example MdePkg, or MdeModulePkg UsbBusDxe. -* "Brief-single-line-summary" is a short summary of the change. -* The entire first line should be less than ~70 characters. -* "Full-commit-message" a verbose multiple line comment describing - the change. Each line should be less than ~70 characters. -* "Contributed-under" explicitely states that the contribution is - made under the terms of the contribtion agreement. This - agreement is included below in this document. -* "Signed-off-by" is the contributor's signature identifying them - by their real/legal name and their email address. - -======================================== -= TianoCore Contribution Agreement 1.0 = -======================================== - -INTEL CORPORATION ("INTEL") MAKES AVAILABLE SOFTWARE, DOCUMENTATION, -INFORMATION AND/OR OTHER MATERIALS FOR USE IN THE TIANOCORE OPEN SOURCE -PROJECT (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE -TERMS AND CONDITIONS OF THIS AGREEMENT BETWEEN YOU AND INTEL AND/OR THE -TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR -REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE -CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS -OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED -BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS -AGREEMENT AND THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE -AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT -USE THE CONTENT. - -Unless otherwise indicated, all Content made available on the TianoCore -site is provided to you under the terms and conditions of the BSD -License ("BSD"). A copy of the BSD License is available at -http://opensource.org/licenses/bsd-license.php -or when applicable, in the associated License.txt file. - -Certain other content may be made available under other licenses as -indicated in or with such Content. (For example, in a License.txt file.) - -You accept and agree to the following terms and conditions for Your -present and future Contributions submitted to TianoCore site. Except -for the license granted to Intel hereunder, You reserve all right, -title, and interest in and to Your Contributions. - -== SECTION 1: Definitions == -* "You" or "Contributor" shall mean the copyright owner or legal - entity authorized by the copyright owner that is making a - Contribution hereunder. All other entities that control, are - controlled by, or are under common control with that entity are - considered to be a single Contributor. For the purposes of this - definition, "control" means (i) the power, direct or indirect, to - cause the direction or management of such entity, whether by - contract or otherwise, or (ii) ownership of fifty percent (50%) - or more of the outstanding shares, or (iii) beneficial ownership - of such entity. -* "Contribution" shall mean any original work of authorship, - including any modifications or additions to an existing work, - that is intentionally submitted by You to the TinaoCore site for - inclusion in, or documentation of, any of the Content. For the - purposes of this definition, "submitted" means any form of - electronic, verbal, or written communication sent to the - TianoCore site or its representatives, including but not limited - to communication on electronic mailing lists, source code - control systems, and issue tracking systems that are managed by, - or on behalf of, the TianoCore site for the purpose of - discussing and improving the Content, but excluding - communication that is conspicuously marked or otherwise - designated in writing by You as "Not a Contribution." - -== SECTION 2: License for Contributions == -* Contributor hereby agrees that redistribution and use of the - Contribution in source and binary forms, with or without - modification, are permitted provided that the following - conditions are met: -** Redistributions of source code must retain the Contributor's - copyright notice, this list of conditions and the following - disclaimer. -** Redistributions in binary form must reproduce the Contributor's - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. -* Disclaimer. None of the names of Contributor, Intel, or the names - of their respective contributors may be used to endorse or - promote products derived from this software without specific - prior written permission. -* Contributor grants a license (with the right to sublicense) under - claims of Contributor's patents that Contributor can license that - are infringed by the Contribution (as delivered by Contributor) to - make, use, distribute, sell, offer for sale, and import the - Contribution and derivative works thereof solely to the minimum - extent necessary for licensee to exercise the granted copyright - license; this patent license applies solely to those portions of - the Contribution that are unmodified. No hardware per se is - licensed. -* EXCEPT AS EXPRESSLY SET FORTH IN SECTION 3 BELOW, THE - CONTRIBUTION IS PROVIDED BY THE CONTRIBUTOR "AS IS" AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE - CONTRIBUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. - -== SECTION 3: Representations == -* You represent that You are legally entitled to grant the above - license. If your employer(s) has rights to intellectual property - that You create that includes Your Contributions, You represent - that You have received permission to make Contributions on behalf - of that employer, that Your employer has waived such rights for - Your Contributions. -* You represent that each of Your Contributions is Your original - creation (see Section 4 for submissions on behalf of others). - You represent that Your Contribution submissions include complete - details of any third-party license or other restriction - (including, but not limited to, related patents and trademarks) - of which You are personally aware and which are associated with - any part of Your Contributions. - -== SECTION 4: Third Party Contributions == -* Should You wish to submit work that is not Your original creation, - You may submit it to TianoCore site separately from any - Contribution, identifying the complete details of its source - and of any license or other restriction (including, but not - limited to, related patents, trademarks, and license agreements) - of which You are personally aware, and conspicuously marking the - work as "Submitted on behalf of a third-party: [named here]". - -== SECTION 5: Miscellaneous == -* Applicable Laws. Any claims arising under or relating to this - Agreement shall be governed by the internal substantive laws of - the State of Delaware or federal courts located in Delaware, - without regard to principles of conflict of laws. -* Language. This Agreement is in the English language only, which - language shall be controlling in all respects, and all versions - of this Agreement in any other language shall be for accommodation - only and shall not be binding. All communications and notices made - or given pursuant to this Agreement, and all documentation and - support to be provided, unless otherwise noted, shall be in the - English language. - diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c deleted file mode 100644 index e8ea11c4f8..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c +++ /dev/null @@ -1,780 +0,0 @@ -/** @file - EFI glue for BIOS INT 13h block devices. - - This file is coded to EDD 3.0 as defined by T13 D1386 Revision 4 - Availible on http://www.t13.org/#Project drafts - Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r4.pdf - -Copyright (c) 1999 - 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 "BiosBlkIo.h" - -// -// Global data declaration -// -// -// EFI Driver Binding Protocol Instance -// -EFI_DRIVER_BINDING_PROTOCOL gBiosBlockIoDriverBinding = { - BiosBlockIoDriverBindingSupported, - BiosBlockIoDriverBindingStart, - BiosBlockIoDriverBindingStop, - 0x3, - NULL, - NULL -}; - -// -// Semaphore to control access to global variables mActiveInstances and mBufferUnder1Mb -// -EFI_LOCK mGlobalDataLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_APPLICATION); - -// -// Number of active instances of this protocol. This is used to allocate/free -// the shared buffer. You must acquire the semaphore to modify. -// -UINTN mActiveInstances = 0; - -// -// Pointer to the beginning of the buffer used for real mode thunk -// You must acquire the semaphore to modify. -// -EFI_PHYSICAL_ADDRESS mBufferUnder1Mb = 0; - -// -// Address packet is a buffer under 1 MB for all version EDD calls -// -EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb; - -// -// This is a buffer for INT 13h func 48 information -// -BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb; - -// -// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB -// 0xFE00 bytes is the max transfer size supported. -// -VOID *mEdd11Buffer; - -/** - Driver entry point. - - @param ImageHandle Handle of driver image. - @param SystemTable Pointer to system table. - - @retval EFI_SUCCESS Entrypoint successfully executed. - @retval Others Fail to execute entrypoint. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoDriverEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install protocols - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gBiosBlockIoDriverBinding, - ImageHandle, - &gBiosBlockIoComponentName, - &gBiosBlockIoComponentName2 - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver - // - return gBS->InstallMultipleProtocolInterfaces ( - &ImageHandle, - &gEfiLegacyBiosGuid, - NULL, - NULL - ); -} - -/** - Check whether the driver supports this device. - - @param This The Udriver binding protocol. - @param Controller The controller handle to check. - @param RemainingDevicePath The remaining device path. - - @retval EFI_SUCCESS The driver supports this controller. - @retval other This device isn't supported. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - PCI_TYPE00 Pci; - - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // See if this is a PCI VGA Controller by looking at the Command register and - // Class Code Register - // - Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci); - if (EFI_ERROR (Status)) { - Status = EFI_UNSUPPORTED; - goto Done; - } - - Status = EFI_UNSUPPORTED; - if (Pci.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE || - (Pci.Hdr.ClassCode[2] == PCI_BASE_CLASS_INTELLIGENT && Pci.Hdr.ClassCode[1] == PCI_SUB_CLASS_INTELLIGENT) - ) { - Status = EFI_SUCCESS; - } - -Done: - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Starts the device with this driver. - - @param This The driver binding instance. - @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 The controller is controlled by the driver. - @retval Other This controller cannot be started. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT8 DiskStart; - UINT8 DiskEnd; - BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; - EFI_DEVICE_PATH_PROTOCOL *PciDevPath; - UINTN Index; - UINTN Flags; - UINTN TmpAddress; - BOOLEAN DeviceEnable; - - // - // Initialize variables - // - PciIo = NULL; - PciDevPath = NULL; - - DeviceEnable = FALSE; - - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - goto Error; - } - // - // Open the IO Abstraction(s) needed - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - goto Error; - } - - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &PciDevPath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - - if (EFI_ERROR (Status)) { - goto Error; - } - // - // Enable the device and make sure VGA cycles are being forwarded to this VGA device - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_DEVICE_ENABLE, - NULL - ); - if (EFI_ERROR (Status)) { - goto Error; - } - - DeviceEnable = TRUE; - - // - // Check to see if there is a legacy option ROM image associated with this PCI device - // - Status = LegacyBios->CheckPciRom ( - LegacyBios, - Controller, - NULL, - NULL, - &Flags - ); - if (EFI_ERROR (Status)) { - goto Error; - } - // - // Post the legacy option ROM if it is available. - // - Status = LegacyBios->InstallPciRom ( - LegacyBios, - Controller, - NULL, - &Flags, - &DiskStart, - &DiskEnd, - NULL, - NULL - ); - if (EFI_ERROR (Status)) { - goto Error; - } - // - // All instances share a buffer under 1MB to put real mode thunk code in - // If it has not been allocated, then we allocate it. - // - if (mBufferUnder1Mb == 0) { - // - // Should only be here if there are no active instances - // - ASSERT (mActiveInstances == 0); - - // - // Acquire the lock - // - EfiAcquireLock (&mGlobalDataLock); - - // - // Allocate below 1MB - // - mBufferUnder1Mb = 0x00000000000FFFFF; - Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb); - - // - // Release the lock - // - EfiReleaseLock (&mGlobalDataLock); - - // - // Check memory allocation success - // - if (EFI_ERROR (Status)) { - // - // In checked builds we want to assert if the allocate failed. - // - ASSERT_EFI_ERROR (Status); - Status = EFI_OUT_OF_RESOURCES; - mBufferUnder1Mb = 0; - goto Error; - } - - TmpAddress = (UINTN) mBufferUnder1Mb; - // - // Adjusting the value to be on proper boundary - // - mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress); - - TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER; - // - // Adjusting the value to be on proper boundary - // - mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress); - - TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE); - // - // Adjusting the value to be on proper boundary - // - mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress); - } - // - // Allocate the private device structure for each disk - // - for (Index = DiskStart; Index < DiskEnd; Index++) { - - Status = gBS->AllocatePool ( - EfiBootServicesData, - sizeof (BIOS_BLOCK_IO_DEV), - (VOID **) &BiosBlockIoPrivate - ); - if (EFI_ERROR (Status)) { - goto Error; - } - // - // Zero the private device structure - // - ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV)); - - // - // Initialize the private device structure - // - BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE; - BiosBlockIoPrivate->ControllerHandle = Controller; - BiosBlockIoPrivate->LegacyBios = LegacyBios; - BiosBlockIoPrivate->PciIo = PciIo; - - BiosBlockIoPrivate->Bios.Floppy = FALSE; - BiosBlockIoPrivate->Bios.Number = (UINT8) Index; - BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C'); - BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE; - - if (BiosInitBlockIo (BiosBlockIoPrivate)) { - SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath); - - // - // Install the Block Io Protocol onto a new child handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &BiosBlockIoPrivate->Handle, - &gEfiBlockIoProtocolGuid, - &BiosBlockIoPrivate->BlockIo, - &gEfiDevicePathProtocolGuid, - BiosBlockIoPrivate->DevicePath, - NULL - ); - if (EFI_ERROR (Status)) { - gBS->FreePool (BiosBlockIoPrivate); - } - // - // Open For Child Device - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &BiosBlockIoPrivate->PciIo, - This->DriverBindingHandle, - BiosBlockIoPrivate->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - - } else { - gBS->FreePool (BiosBlockIoPrivate); - } - } - -Error: - if (EFI_ERROR (Status)) { - if (PciIo != NULL) { - if (DeviceEnable) { - PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationDisable, - EFI_PCI_DEVICE_ENABLE, - NULL - ); - } - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - if (PciDevPath != NULL) { - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - } - if (mBufferUnder1Mb != 0 && mActiveInstances == 0) { - gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); - - // - // Clear the buffer back to 0 - // - EfiAcquireLock (&mGlobalDataLock); - mBufferUnder1Mb = 0; - EfiReleaseLock (&mGlobalDataLock); - } - } - } else { - // - // Successfully installed, so increment the number of active instances - // - EfiAcquireLock (&mGlobalDataLock); - mActiveInstances++; - EfiReleaseLock (&mGlobalDataLock); - } - - return Status; -} - -/** - Stop the device handled by this driver. - - @param This The driver binding protocol. - @param Controller The controller to release. - @param NumberOfChildren The number of handles in ChildHandleBuffer. - @param ChildHandleBuffer The array of child handle. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - @retval Others Fail to uninstall protocols attached on the device. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - BOOLEAN AllChildrenStopped; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; - UINTN Index; - - // - // Decrement the number of active instances - // - if (mActiveInstances != 0) { - // - // Add a check since the stop function will be called 2 times for each handle - // - EfiAcquireLock (&mGlobalDataLock); - mActiveInstances--; - EfiReleaseLock (&mGlobalDataLock); - } - - if ((mActiveInstances == 0) && (mBufferUnder1Mb != 0)) { - // - // Free our global buffer - // - Status = gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); - ASSERT_EFI_ERROR (Status); - - EfiAcquireLock (&mGlobalDataLock); - mBufferUnder1Mb = 0; - EfiReleaseLock (&mGlobalDataLock); - } - - AllChildrenStopped = TRUE; - - for (Index = 0; Index < NumberOfChildren; Index++) { - Status = gBS->OpenProtocol ( - ChildHandleBuffer[Index], - &gEfiBlockIoProtocolGuid, - (VOID **) &BlockIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - BiosBlockIoPrivate = BIOS_BLOCK_IO_FROM_THIS (BlockIo); - - // - // Release PCI I/O and Block IO Protocols on the clild handle. - // - Status = gBS->UninstallMultipleProtocolInterfaces ( - ChildHandleBuffer[Index], - &gEfiBlockIoProtocolGuid, - &BiosBlockIoPrivate->BlockIo, - &gEfiDevicePathProtocolGuid, - BiosBlockIoPrivate->DevicePath, - NULL - ); - if (EFI_ERROR (Status)) { - AllChildrenStopped = FALSE; - } - // - // Shutdown the hardware - // - BiosBlockIoPrivate->PciIo->Attributes ( - BiosBlockIoPrivate->PciIo, - EfiPciIoAttributeOperationDisable, - EFI_PCI_DEVICE_ENABLE, - NULL - ); - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - ChildHandleBuffer[Index] - ); - - gBS->FreePool (BiosBlockIoPrivate); - } - - if (!AllChildrenStopped) { - return EFI_DEVICE_ERROR; - } - - Status = gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - Status = gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return EFI_SUCCESS; -} - -/** - Build device path for device. - - @param BaseDevicePath Base device path. - @param Drive Legacy drive. - @param DevicePath Device path for output. - -**/ -VOID -SetBiosInitBlockIoDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, - IN BIOS_LEGACY_DRIVE *Drive, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath - ) -{ - EFI_STATUS Status; - BLOCKIO_VENDOR_DEVICE_PATH VendorNode; - - Status = EFI_UNSUPPORTED; - - // - // BugBug: Check for memory leaks! - // - if (Drive->EddVersion == EDD_VERSION_30) { - // - // EDD 3.0 case. - // - Status = BuildEdd30DevicePath (BaseDevicePath, Drive, DevicePath); - } - - if (EFI_ERROR (Status)) { - // - // EDD 1.1 device case or it is unrecognized EDD 3.0 device - // - ZeroMem (&VendorNode, sizeof (VendorNode)); - VendorNode.DevicePath.Header.Type = HARDWARE_DEVICE_PATH; - VendorNode.DevicePath.Header.SubType = HW_VENDOR_DP; - SetDevicePathNodeLength (&VendorNode.DevicePath.Header, sizeof (VendorNode)); - CopyMem (&VendorNode.DevicePath.Guid, &gBlockIoVendorGuid, sizeof (EFI_GUID)); - VendorNode.LegacyDriveLetter = Drive->Number; - *DevicePath = AppendDevicePathNode (BaseDevicePath, &VendorNode.DevicePath.Header); - } -} - -/** - Build device path for EDD 3.0. - - @param BaseDevicePath Base device path. - @param Drive Legacy drive. - @param DevicePath Device path for output. - - @retval EFI_SUCCESS The device path is built successfully. - @retval EFI_UNSUPPORTED It is failed to built device path. - -**/ -EFI_STATUS -BuildEdd30DevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, - IN BIOS_LEGACY_DRIVE *Drive, - IN EFI_DEVICE_PATH_PROTOCOL **DevicePath - ) -{ - // - // AVL UINT64 Address; - // AVL EFI_HANDLE Handle; - // - EFI_DEV_PATH Node; - UINT32 Controller; - - Controller = (UINT32) Drive->Parameters.InterfacePath.Pci.Controller; - - ZeroMem (&Node, sizeof (Node)); - if ((AsciiStrnCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) || - (AsciiStrnCmp ("ATA", Drive->Parameters.InterfaceType, 3) == 0) - ) { - // - // ATA or ATAPI drive found - // - Node.Atapi.Header.Type = MESSAGING_DEVICE_PATH; - Node.Atapi.Header.SubType = MSG_ATAPI_DP; - SetDevicePathNodeLength (&Node.Atapi.Header, sizeof (ATAPI_DEVICE_PATH)); - Node.Atapi.SlaveMaster = Drive->Parameters.DevicePath.Atapi.Master; - Node.Atapi.Lun = Drive->Parameters.DevicePath.Atapi.Lun; - Node.Atapi.PrimarySecondary = (UINT8) Controller; - } else { - // - // Not an ATA/ATAPI drive - // - if (Controller != 0) { - ZeroMem (&Node, sizeof (Node)); - Node.Controller.Header.Type = HARDWARE_DEVICE_PATH; - Node.Controller.Header.SubType = HW_CONTROLLER_DP; - SetDevicePathNodeLength (&Node.Controller.Header, sizeof (CONTROLLER_DEVICE_PATH)); - Node.Controller.ControllerNumber = Controller; - *DevicePath = AppendDevicePathNode (*DevicePath, &Node.DevPath); - } - - ZeroMem (&Node, sizeof (Node)); - - if (AsciiStrnCmp ("SCSI", Drive->Parameters.InterfaceType, 4) == 0) { - // - // SCSI drive - // - Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH; - Node.Scsi.Header.SubType = MSG_SCSI_DP; - SetDevicePathNodeLength (&Node.Scsi.Header, sizeof (SCSI_DEVICE_PATH)); - - // - // Lun is miss aligned in both EDD and Device Path data structures. - // thus we do a byte copy, to prevent alignment traps on IA-64. - // - CopyMem (&Node.Scsi.Lun, &Drive->Parameters.DevicePath.Scsi.Lun, sizeof (UINT16)); - Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.Pun; - - } else if (AsciiStrnCmp ("USB", Drive->Parameters.InterfaceType, 3) == 0) { - // - // USB drive - // - Node.Usb.Header.Type = MESSAGING_DEVICE_PATH; - Node.Usb.Header.SubType = MSG_USB_DP; - SetDevicePathNodeLength (&Node.Usb.Header, sizeof (USB_DEVICE_PATH)); - Node.Usb.ParentPortNumber = (UINT8) Drive->Parameters.DevicePath.Usb.Reserved; - - } else if (AsciiStrnCmp ("1394", Drive->Parameters.InterfaceType, 4) == 0) { - // - // 1394 drive - // - Node.F1394.Header.Type = MESSAGING_DEVICE_PATH; - Node.F1394.Header.SubType = MSG_1394_DP; - SetDevicePathNodeLength (&Node.F1394.Header, sizeof (F1394_DEVICE_PATH)); - Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid; - - } else if (AsciiStrnCmp ("FIBRE", Drive->Parameters.InterfaceType, 5) == 0) { - // - // Fibre drive - // - Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH; - Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP; - SetDevicePathNodeLength (&Node.FibreChannel.Header, sizeof (FIBRECHANNEL_DEVICE_PATH)); - Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn; - Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun; - - } else { - DEBUG ( - ( - DEBUG_BLKIO, "It is unrecognized EDD 3.0 device, Drive Number = %x, InterfaceType = %s\n", - Drive->Number, - Drive->Parameters.InterfaceType - ) - ); - } - } - - if (Node.DevPath.Type == 0) { - return EFI_UNSUPPORTED; - } - - *DevicePath = AppendDevicePathNode (BaseDevicePath, &Node.DevPath); - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h deleted file mode 100644 index 91617b79d9..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h +++ /dev/null @@ -1,432 +0,0 @@ -/** @file - -Copyright (c) 1999 - 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 _BIOS_BLOCK_IO_H_ -#define _BIOS_BLOCK_IO_H_ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Edd.h" - -// -// Global Variables -// -extern EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2; - - -// -// Define the I2O class code -// -#define PCI_BASE_CLASS_INTELLIGENT 0x0e -#define PCI_SUB_CLASS_INTELLIGENT 0x00 - -// -// Number of pages needed for our buffer under 1MB -// -#define BLOCK_IO_BUFFER_PAGE_SIZE (((sizeof (EDD_DEVICE_ADDRESS_PACKET) + sizeof (BIOS_LEGACY_DRIVE) + MAX_EDD11_XFER) / EFI_PAGE_SIZE) + 1 \ - ) - -// -// Driver Binding Protocol functions -// - -/** - Check whether the driver supports this device. - - @param This The Udriver binding protocol. - @param Controller The controller handle to check. - @param RemainingDevicePath The remaining device path. - - @retval EFI_SUCCESS The driver supports this controller. - @retval other This device isn't supported. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - - -/** - Starts the device with this driver. - - @param This The driver binding instance. - @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 The controller is controlled by the driver. - @retval Other This controller cannot be started. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Stop the device handled by this driver. - - @param This The driver binding protocol. - @param Controller The controller to release. - @param NumberOfChildren The number of handles in ChildHandleBuffer. - @param ChildHandleBuffer The array of child handle. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - @retval Others Fail to uninstall protocols attached on the device. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// Other internal functions -// - -/** - Build device path for EDD 3.0. - - @param BaseDevicePath Base device path. - @param Drive Legacy drive. - @param DevicePath Device path for output. - - @retval EFI_SUCCESS The device path is built successfully. - @retval EFI_UNSUPPORTED It is failed to built device path. - -**/ -EFI_STATUS -BuildEdd30DevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, - IN BIOS_LEGACY_DRIVE *Drive, - IN EFI_DEVICE_PATH_PROTOCOL **DevicePath - ); - -/** - Initialize block I/O device instance - - @param Dev Instance of block I/O device instance - - @retval TRUE Initialization succeeds. - @retval FALSE Initialization fails. - -**/ -BOOLEAN -BiosInitBlockIo ( - IN BIOS_BLOCK_IO_DEV *Dev - ); - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -Edd30BiosReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *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. - -**/ -EFI_STATUS -EFIAPI -Edd30BiosWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT 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. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ); - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoReset ( - IN EFI_BLOCK_IO_PROTOCOL *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. - -**/ -EFI_STATUS -EFIAPI -Edd11BiosReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *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. - -**/ -EFI_STATUS -EFIAPI -Edd11BiosWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -BiosReadLegacyDrive ( - IN EFI_BLOCK_IO_PROTOCOL *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. - -**/ -EFI_STATUS -EFIAPI -BiosWriteLegacyDrive ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - Gets parameters of block I/O device. - - @param BiosBlockIoDev Instance of block I/O device. - @param Drive Legacy drive. - - @return Result of device parameter retrieval. - -**/ -UINTN -Int13GetDeviceParameters ( - IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, - IN BIOS_LEGACY_DRIVE *Drive - ); - -/** - Extension of INT13 call. - - @param BiosBlockIoDev Instance of block I/O device. - @param Drive Legacy drive. - - @return Result of this extension. - -**/ -UINTN -Int13Extensions ( - IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, - IN BIOS_LEGACY_DRIVE *Drive - ); - -/** - Gets parameters of legacy drive. - - @param BiosBlockIoDev Instance of block I/O device. - @param Drive Legacy drive. - - @return Result of drive parameter retrieval. - -**/ -UINTN -GetDriveParameters ( - IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, - IN BIOS_LEGACY_DRIVE *Drive - ); - -/** - Build device path for device. - - @param BaseDevicePath Base device path. - @param Drive Legacy drive. - @param DevicePath Device path for output. - -**/ -VOID -SetBiosInitBlockIoDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, - IN BIOS_LEGACY_DRIVE *Drive, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath - ); - -#endif diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c deleted file mode 100644 index 698bb620e8..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c +++ /dev/null @@ -1,1495 +0,0 @@ -/** @file - Routines that use BIOS to support INT 13 devices. - -Copyright (c) 1999 - 2015, Intel 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 "BiosBlkIo.h" - -// -// Module global variables -// -// -// Address packet is a buffer under 1 MB for all version EDD calls -// -extern EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb; - -// -// This is a buffer for INT 13h func 48 information -// -extern BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb; - -// -// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB -// 0xFE00 bytes is the max transfer size supported. -// -extern VOID *mEdd11Buffer; - - -/** - Initialize block I/O device instance - - @param Dev Instance of block I/O device instance - - @retval TRUE Initialization succeeds. - @retval FALSE Initialization fails. - -**/ -BOOLEAN -BiosInitBlockIo ( - IN BIOS_BLOCK_IO_DEV *Dev - ) -{ - EFI_BLOCK_IO_PROTOCOL *BlockIo; - EFI_BLOCK_IO_MEDIA *BlockMedia; - BIOS_LEGACY_DRIVE *Bios; - - BlockIo = &Dev->BlockIo; - BlockIo->Media = &Dev->BlockMedia; - BlockMedia = BlockIo->Media; - Bios = &Dev->Bios; - - if (Int13GetDeviceParameters (Dev, Bios) != 0) { - if (Int13Extensions (Dev, Bios) != 0) { - BlockMedia->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; - BlockMedia->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; - - if ((Bios->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) { - BlockMedia->RemovableMedia = TRUE; - } - - } else { - // - // Legacy Interfaces - // - BlockMedia->BlockSize = 512; - BlockMedia->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; - } - - DEBUG ((DEBUG_INIT, "BlockSize = %d LastBlock = %d\n", BlockMedia->BlockSize, BlockMedia->LastBlock)); - - BlockMedia->LogicalPartition = FALSE; - BlockMedia->WriteCaching = FALSE; - - // - // BugBug: Need to set this for removable media devices if they do not - // have media present - // - BlockMedia->ReadOnly = FALSE; - BlockMedia->MediaPresent = TRUE; - - BlockIo->Reset = BiosBlockIoReset; - BlockIo->FlushBlocks = BiosBlockIoFlushBlocks; - - if (!Bios->ExtendedInt13) { - // - // Legacy interfaces - // - BlockIo->ReadBlocks = BiosReadLegacyDrive; - BlockIo->WriteBlocks = BiosWriteLegacyDrive; - } else if ((Bios->EddVersion == EDD_VERSION_30) && (Bios->Extensions64Bit)) { - // - // EDD 3.0 Required for Device path, but extended reads are not required. - // - BlockIo->ReadBlocks = Edd30BiosReadBlocks; - BlockIo->WriteBlocks = Edd30BiosWriteBlocks; - } else { - // - // Assume EDD 1.1 - Read and Write functions. - // This could be EDD 3.0 without Extensions64Bit being set. - // If it's EDD 1.1 this will work, but the device path will not - // be correct. This will cause confusion to EFI OS installation. - // - BlockIo->ReadBlocks = Edd11BiosReadBlocks; - BlockIo->WriteBlocks = Edd11BiosWriteBlocks; - } - - BlockMedia->LogicalPartition = FALSE; - BlockMedia->WriteCaching = FALSE; - - return TRUE; - } - - return FALSE; -} - -/** - Gets parameters of block I/O device. - - @param BiosBlockIoDev Instance of block I/O device. - @param Drive Legacy drive. - - @return Result of device parameter retrieval. - -**/ -UINTN -Int13GetDeviceParameters ( - IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, - IN BIOS_LEGACY_DRIVE *Drive - ) -{ - UINTN CarryFlag; - UINT16 Cylinder; - EFI_IA32_REGISTER_SET Regs; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - Regs.H.AH = 0x08; - Regs.H.DL = Drive->Number; - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ((DEBUG_INIT, "Int13GetDeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); - if (CarryFlag != 0 || Regs.H.AH != 0x00) { - Drive->ErrorCode = Regs.H.AH; - return FALSE; - } - - if (Drive->Floppy) { - if (Regs.H.BL == 0x10) { - Drive->AtapiFloppy = TRUE; - } else { - Drive->MaxHead = Regs.H.DH; - Drive->MaxSector = Regs.H.CL; - Drive->MaxCylinder = Regs.H.CH; - if (Drive->MaxSector == 0) { - // - // BugBug: You can not trust the Carry flag. - // - return FALSE; - } - } - } else { - Drive->MaxHead = (UINT8) (Regs.H.DH & 0x3f); - Cylinder = (UINT16) (((UINT16) Regs.H.DH & 0xc0) << 4); - Cylinder = (UINT16) (Cylinder | ((UINT16) Regs.H.CL & 0xc0) << 2); - Drive->MaxCylinder = (UINT16) (Cylinder + Regs.H.CH); - Drive->MaxSector = (UINT8) (Regs.H.CL & 0x3f); - } - - return TRUE; -} - -/** - Extension of INT13 call. - - @param BiosBlockIoDev Instance of block I/O device. - @param Drive Legacy drive. - - @return Result of this extension. - -**/ -UINTN -Int13Extensions ( - IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, - IN BIOS_LEGACY_DRIVE *Drive - ) -{ - INTN CarryFlag; - EFI_IA32_REGISTER_SET Regs; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - Regs.H.AH = 0x41; - Regs.X.BX = 0x55aa; - Regs.H.DL = Drive->Number; - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ((DEBUG_INIT, "Int13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX)); - if (CarryFlag != 0 || Regs.X.BX != 0xaa55) { - Drive->ExtendedInt13 = FALSE; - Drive->DriveLockingAndEjecting = FALSE; - Drive->Edd = FALSE; - return FALSE; - } - - Drive->EddVersion = Regs.H.AH; - Drive->ExtendedInt13 = (BOOLEAN) ((Regs.X.CX & 0x01) == 0x01); - Drive->DriveLockingAndEjecting = (BOOLEAN) ((Regs.X.CX & 0x02) == 0x02); - Drive->Edd = (BOOLEAN) ((Regs.X.CX & 0x04) == 0x04); - Drive->Extensions64Bit = (BOOLEAN) (Regs.X.CX & 0x08); - - Drive->ParametersValid = (UINT8) GetDriveParameters (BiosBlockIoDev, Drive); - return TRUE; -} - -/** - Gets parameters of legacy drive. - - @param BiosBlockIoDev Instance of block I/O device. - @param Drive Legacy drive. - - @return Result of drive parameter retrieval. - -**/ -UINTN -GetDriveParameters ( - IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, - IN BIOS_LEGACY_DRIVE *Drive - ) -{ - INTN CarryFlag; - EFI_IA32_REGISTER_SET Regs; - UINTN PointerMath; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - Regs.H.AH = 0x48; - Regs.H.DL = Drive->Number; - - // - // EDD Buffer must be passed in with max buffer size as first entry in the buffer - // - mLegacyDriverUnder1Mb->Parameters.StructureSize = (UINT16) sizeof (EDD_DRIVE_PARAMETERS); - Regs.X.DS = EFI_SEGMENT ((UINTN)(&mLegacyDriverUnder1Mb->Parameters)); - Regs.X.SI = EFI_OFFSET ((UINTN)(&mLegacyDriverUnder1Mb->Parameters)); - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 48 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); - if (CarryFlag != 0 || Regs.H.AH != 0x00) { - Drive->ErrorCode = Regs.H.AH; - SetMem (&Drive->Parameters, sizeof (Drive->Parameters), 0xaf); - return FALSE; - } - // - // We only have one buffer < 1MB, so copy into our instance data - // - CopyMem ( - &Drive->Parameters, - &mLegacyDriverUnder1Mb->Parameters, - sizeof (Drive->Parameters) - ); - - if (Drive->AtapiFloppy) { - // - // Sense Media Type - // - Regs.H.AH = 0x20; - Regs.H.DL = Drive->Number; - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 20 DL=%02x : CF=%d AL=%02x\n", Drive->Number, CarryFlag, Regs.H.AL)); - if (CarryFlag != 0) { - // - // Media not present or unknown media present - // - if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) { - Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1); - Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack; - ASSERT (Drive->MaxSector != 0); - Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1); - } else { - Drive->MaxHead = 0; - Drive->MaxSector = 1; - Drive->MaxCylinder = 0; - } - - } else { - // - // Media Present - // - switch (Regs.H.AL) { - case 0x03: - // - // 720 KB - // - Drive->MaxHead = 1; - Drive->MaxSector = 9; - Drive->MaxCylinder = 79; - break; - - case 0x04: - // - // 1.44MB - // - Drive->MaxHead = 1; - Drive->MaxSector = 18; - Drive->MaxCylinder = 79; - break; - - case 0x06: - // - // 2.88MB - // - Drive->MaxHead = 1; - Drive->MaxSector = 36; - Drive->MaxCylinder = 79; - break; - - case 0x0C: - // - // 360 KB - // - Drive->MaxHead = 1; - Drive->MaxSector = 9; - Drive->MaxCylinder = 39; - break; - - case 0x0D: - // - // 1.2 MB - // - Drive->MaxHead = 1; - Drive->MaxSector = 15; - Drive->MaxCylinder = 79; - break; - - case 0x0E: - // - // Toshiba 3 mode - // - case 0x0F: - // - // NEC 3 mode - // - case 0x10: - // - // Default Media - // - if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) { - Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1); - Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack; - ASSERT (Drive->MaxSector != 0); - Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1); - } else { - Drive->MaxHead = 0; - Drive->MaxSector = 1; - Drive->MaxCylinder = 0; - } - break; - - default: - // - // Unknown media type. - // - Drive->MaxHead = 0; - Drive->MaxSector = 1; - Drive->MaxCylinder = 0; - break; - } - } - - Drive->Parameters.PhysicalSectors = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1); - Drive->Parameters.BytesPerSector = 512; - } - // - // This data comes from the BIOS so it may not allways be valid - // since the BIOS may reuse this buffer for future accesses - // - PointerMath = EFI_SEGMENT (Drive->Parameters.Fdpt) << 4; - PointerMath += EFI_OFFSET (Drive->Parameters.Fdpt); - Drive->FdptPointer = (VOID *) PointerMath; - - return TRUE; -} -// -// Block IO Routines -// - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -Edd30BiosReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - BIOS_BLOCK_IO_DEV *BiosBlockIoDev; - EDD_DEVICE_ADDRESS_PACKET *AddressPacket; - // - // I exist only for readability - // - EFI_IA32_REGISTER_SET Regs; - UINT64 TransferBuffer; - UINTN NumberOfBlocks; - UINTN TransferByteSize; - UINTN BlockSize; - BIOS_LEGACY_DRIVE *Bios; - UINTN CarryFlag; - UINTN MaxTransferBlocks; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - - Media = This->Media; - BlockSize = Media->BlockSize; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); - AddressPacket = mEddBufferUnder1Mb; - - MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; - - TransferBuffer = (UINT64)(UINTN) Buffer; - for (; BufferSize > 0;) { - NumberOfBlocks = BufferSize / BlockSize; - NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; - // - // Max transfer MaxTransferBlocks - // - AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); - AddressPacket->Zero = 0; - AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; - AddressPacket->Zero2 = 0; - AddressPacket->SegOffset = 0xffffffff; - AddressPacket->Lba = (UINT64) Lba; - AddressPacket->TransferBuffer = TransferBuffer; - - Regs.H.AH = 0x42; - Regs.H.DL = BiosBlockIoDev->Bios.Number; - Regs.X.SI = EFI_OFFSET (AddressPacket); - Regs.X.DS = EFI_SEGMENT (AddressPacket); - - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ( - ( - DEBUG_BLKIO, "Edd30BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, - CarryFlag, Regs.H.AH - ) - ); - - Media->MediaPresent = TRUE; - if (CarryFlag != 0) { - // - // Return Error Status - // - BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; - if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { - Media->MediaId++; - Bios = &BiosBlockIoDev->Bios; - if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { - if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { - Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; - Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; - } else { - ASSERT (FALSE); - } - - Media->ReadOnly = FALSE; - gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); - gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); - return EFI_MEDIA_CHANGED; - } - } - - if (Media->RemovableMedia) { - Media->MediaPresent = FALSE; - } - - return EFI_DEVICE_ERROR; - } - - TransferByteSize = NumberOfBlocks * BlockSize; - BufferSize = BufferSize - TransferByteSize; - TransferBuffer += TransferByteSize; - Lba += NumberOfBlocks; - } - - return EFI_SUCCESS; -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -Edd30BiosWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - BIOS_BLOCK_IO_DEV *BiosBlockIoDev; - EDD_DEVICE_ADDRESS_PACKET *AddressPacket; - // - // I exist only for readability - // - EFI_IA32_REGISTER_SET Regs; - UINT64 TransferBuffer; - UINTN NumberOfBlocks; - UINTN TransferByteSize; - UINTN BlockSize; - BIOS_LEGACY_DRIVE *Bios; - UINTN CarryFlag; - UINTN MaxTransferBlocks; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - - Media = This->Media; - BlockSize = Media->BlockSize; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (Lba > Media->LastBlock) { - return EFI_DEVICE_ERROR; - } - - if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); - AddressPacket = mEddBufferUnder1Mb; - - MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; - - TransferBuffer = (UINT64)(UINTN) Buffer; - for (; BufferSize > 0;) { - NumberOfBlocks = BufferSize / BlockSize; - NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; - // - // Max transfer MaxTransferBlocks - // - AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); - AddressPacket->Zero = 0; - AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; - AddressPacket->Zero2 = 0; - AddressPacket->SegOffset = 0xffffffff; - AddressPacket->Lba = (UINT64) Lba; - AddressPacket->TransferBuffer = TransferBuffer; - - Regs.H.AH = 0x43; - Regs.H.AL = 0x00; - // - // Write Verify Off - // - Regs.H.DL = (UINT8) (BiosBlockIoDev->Bios.Number); - Regs.X.SI = EFI_OFFSET (AddressPacket); - Regs.X.DS = EFI_SEGMENT (AddressPacket); - - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ( - ( - DEBUG_BLKIO, "Edd30BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, - CarryFlag, Regs.H.AH - ) - ); - - Media->MediaPresent = TRUE; - if (CarryFlag != 0) { - // - // Return Error Status - // - BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; - if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { - Media->MediaId++; - Bios = &BiosBlockIoDev->Bios; - if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { - if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { - Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; - Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; - } else { - ASSERT (FALSE); - } - - Media->ReadOnly = FALSE; - gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); - gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); - return EFI_MEDIA_CHANGED; - } - } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { - Media->ReadOnly = TRUE; - return EFI_WRITE_PROTECTED; - } - - if (Media->RemovableMedia) { - Media->MediaPresent = FALSE; - } - - return EFI_DEVICE_ERROR; - } - - Media->ReadOnly = FALSE; - TransferByteSize = NumberOfBlocks * BlockSize; - BufferSize = BufferSize - TransferByteSize; - TransferBuffer += TransferByteSize; - Lba += NumberOfBlocks; - } - - return EFI_SUCCESS; -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ) -{ - return EFI_SUCCESS; -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoReset ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - BIOS_BLOCK_IO_DEV *BiosBlockIoDev; - EFI_IA32_REGISTER_SET Regs; - UINTN CarryFlag; - - BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - Regs.H.AH = 0x00; - Regs.H.DL = BiosBlockIoDev->Bios.Number; - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ( - ( - DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag, - Regs.H.AH - ) - ); - if (CarryFlag != 0) { - if (Regs.H.AL == BIOS_RESET_FAILED) { - Regs.H.AH = 0x00; - Regs.H.DL = BiosBlockIoDev->Bios.Number; - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ( - ( - DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag, - Regs.H.AH - ) - ); - if (CarryFlag != 0) { - BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; - return EFI_DEVICE_ERROR; - } - } - } - - return EFI_SUCCESS; -} -// -// -// These functions need to double buffer all data under 1MB! -// -// - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -Edd11BiosReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - BIOS_BLOCK_IO_DEV *BiosBlockIoDev; - EDD_DEVICE_ADDRESS_PACKET *AddressPacket; - // - // I exist only for readability - // - EFI_IA32_REGISTER_SET Regs; - UINT64 TransferBuffer; - UINTN NumberOfBlocks; - UINTN TransferByteSize; - UINTN BlockSize; - BIOS_LEGACY_DRIVE *Bios; - UINTN CarryFlag; - UINTN MaxTransferBlocks; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - - Media = This->Media; - BlockSize = Media->BlockSize; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); - AddressPacket = mEddBufferUnder1Mb; - - MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; - - TransferBuffer = (UINT64)(UINTN) mEdd11Buffer; - for (; BufferSize > 0;) { - NumberOfBlocks = BufferSize / BlockSize; - NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; - // - // Max transfer MaxTransferBlocks - // - AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); - AddressPacket->Zero = 0; - AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; - AddressPacket->Zero2 = 0; - // - // TransferBuffer has been 4KB alignment. Normalize TransferBuffer to make offset as 0 in seg:offset - // format to transfer maximum 127 blocks of data. - // Otherwise when offset adding data size exceeds 0xFFFF, if OpROM does not normalize TransferBuffer, - // INT13 function 42H will return data boundary error 09H. - // - AddressPacket->SegOffset = (UINT32) LShiftU64 (RShiftU64(TransferBuffer, 4), 16); - AddressPacket->Lba = (UINT64) Lba; - - Regs.H.AH = 0x42; - Regs.H.DL = BiosBlockIoDev->Bios.Number; - Regs.X.SI = EFI_OFFSET (AddressPacket); - Regs.X.DS = EFI_SEGMENT (AddressPacket); - - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ( - ( - DEBUG_BLKIO, "Edd11BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n", - BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks - ) - ); - Media->MediaPresent = TRUE; - if (CarryFlag != 0) { - // - // Return Error Status - // - BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; - if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { - Media->MediaId++; - Bios = &BiosBlockIoDev->Bios; - if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { - if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { - Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; - Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; - } else { - ASSERT (FALSE); - } - - Media->ReadOnly = FALSE; - gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); - gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); - return EFI_MEDIA_CHANGED; - } - } - - if (Media->RemovableMedia) { - Media->MediaPresent = FALSE; - } - - return EFI_DEVICE_ERROR; - } - - TransferByteSize = NumberOfBlocks * BlockSize; - CopyMem (Buffer, (VOID *) (UINTN) TransferBuffer, TransferByteSize); - BufferSize = BufferSize - TransferByteSize; - Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); - Lba += NumberOfBlocks; - } - - return EFI_SUCCESS; -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -Edd11BiosWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - BIOS_BLOCK_IO_DEV *BiosBlockIoDev; - EDD_DEVICE_ADDRESS_PACKET *AddressPacket; - // - // I exist only for readability - // - EFI_IA32_REGISTER_SET Regs; - UINT64 TransferBuffer; - UINTN NumberOfBlocks; - UINTN TransferByteSize; - UINTN BlockSize; - BIOS_LEGACY_DRIVE *Bios; - UINTN CarryFlag; - UINTN MaxTransferBlocks; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - - Media = This->Media; - BlockSize = Media->BlockSize; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); - AddressPacket = mEddBufferUnder1Mb; - - MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; - - TransferBuffer = (UINT64)(UINTN) mEdd11Buffer; - for (; BufferSize > 0;) { - NumberOfBlocks = BufferSize / BlockSize; - NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; - // - // Max transfer MaxTransferBlocks - // - AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); - AddressPacket->Zero = 0; - AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; - AddressPacket->Zero2 = 0; - // - // TransferBuffer has been 4KB alignment. Normalize TransferBuffer to make offset as 0 in seg:offset - // format to transfer maximum 127 blocks of data. - // Otherwise when offset adding data size exceeds 0xFFFF, if OpROM does not normalize TransferBuffer, - // INT13 function 42H will return data boundary error 09H. - // - AddressPacket->SegOffset = (UINT32) LShiftU64 (RShiftU64(TransferBuffer, 4), 16); - AddressPacket->Lba = (UINT64) Lba; - - Regs.H.AH = 0x43; - Regs.H.AL = 0x00; - // - // Write Verify disable - // - Regs.H.DL = BiosBlockIoDev->Bios.Number; - Regs.X.SI = EFI_OFFSET (AddressPacket); - Regs.X.DS = EFI_SEGMENT (AddressPacket); - - TransferByteSize = NumberOfBlocks * BlockSize; - CopyMem ((VOID *) (UINTN) TransferBuffer, Buffer, TransferByteSize); - - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ( - ( - DEBUG_BLKIO, "Edd11BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n", - BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks - ) - ); - Media->MediaPresent = TRUE; - if (CarryFlag != 0) { - // - // Return Error Status - // - BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; - if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { - Media->MediaId++; - Bios = &BiosBlockIoDev->Bios; - if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { - if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { - Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; - Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; - } else { - ASSERT (FALSE); - } - - Media->ReadOnly = FALSE; - gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); - gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); - return EFI_MEDIA_CHANGED; - } - } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { - Media->ReadOnly = TRUE; - return EFI_WRITE_PROTECTED; - } - - if (Media->RemovableMedia) { - Media->MediaPresent = FALSE; - } - - return EFI_DEVICE_ERROR; - } - - Media->ReadOnly = FALSE; - BufferSize = BufferSize - TransferByteSize; - Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); - Lba += NumberOfBlocks; - } - - return EFI_SUCCESS; -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -BiosReadLegacyDrive ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - BIOS_BLOCK_IO_DEV *BiosBlockIoDev; - EFI_IA32_REGISTER_SET Regs; - UINTN UpperCylinder; - UINTN Temp; - UINTN Cylinder; - UINTN Head; - UINTN Sector; - UINTN NumberOfBlocks; - UINTN TransferByteSize; - UINTN ShortLba; - UINTN CheckLba; - UINTN BlockSize; - BIOS_LEGACY_DRIVE *Bios; - UINTN CarryFlag; - UINTN Retry; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - - Media = This->Media; - BlockSize = Media->BlockSize; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); - ShortLba = (UINTN) Lba; - - while (BufferSize != 0) { - // - // Compute I/O location in Sector, Head, Cylinder format - // - Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1; - Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector; - Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1); - Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1); - - // - // Limit transfer to this Head & Cylinder - // - NumberOfBlocks = BufferSize / BlockSize; - Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1; - NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks; - - Retry = 3; - do { - // - // Perform the IO - // - Regs.H.AH = 2; - Regs.H.AL = (UINT8) NumberOfBlocks; - Regs.H.DL = BiosBlockIoDev->Bios.Number; - - UpperCylinder = (Cylinder & 0x0f00) >> 2; - - CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head; - CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1; - - DEBUG ( - (DEBUG_BLKIO, - "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n", - ShortLba, - CheckLba, - Sector, - BiosBlockIoDev->Bios.MaxSector, - Head, - BiosBlockIoDev->Bios.MaxHead, - Cylinder, - UpperCylinder) - ); - ASSERT (CheckLba == ShortLba); - - Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)); - Regs.H.DH = (UINT8) (Head & 0x3f); - Regs.H.CH = (UINT8) (Cylinder & 0xff); - - Regs.X.BX = EFI_OFFSET (mEdd11Buffer); - Regs.X.ES = EFI_SEGMENT (mEdd11Buffer); - - DEBUG ( - (DEBUG_BLKIO, - "INT 13h: AX:(02%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n", - Regs.H.AL, - (UINT8) (Head & 0x3f), - Regs.H.DL, - (UINT8) (Cylinder & 0xff), - (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)), - EFI_OFFSET (mEdd11Buffer), - EFI_SEGMENT (mEdd11Buffer)) - ); - - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ( - ( - DEBUG_BLKIO, "BiosReadLegacyDrive: INT 13 02 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, - CarryFlag, Regs.H.AH - ) - ); - Retry--; - } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED); - - Media->MediaPresent = TRUE; - if (CarryFlag != 0) { - // - // Return Error Status - // - BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; - if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { - Media->MediaId++; - Bios = &BiosBlockIoDev->Bios; - if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { - // - // If the size of the media changed we need to reset the disk geometry - // - if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { - Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; - Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; - } else { - // - // Legacy Interfaces - // - Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; - Media->BlockSize = 512; - } - - Media->ReadOnly = FALSE; - gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); - gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); - return EFI_MEDIA_CHANGED; - } - } - - if (Media->RemovableMedia) { - Media->MediaPresent = FALSE; - } - - return EFI_DEVICE_ERROR; - } - - TransferByteSize = NumberOfBlocks * BlockSize; - CopyMem (Buffer, mEdd11Buffer, TransferByteSize); - - ShortLba = ShortLba + NumberOfBlocks; - BufferSize = BufferSize - TransferByteSize; - Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); - } - - return EFI_SUCCESS; -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -BiosWriteLegacyDrive ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - EFI_BLOCK_IO_MEDIA *Media; - BIOS_BLOCK_IO_DEV *BiosBlockIoDev; - EFI_IA32_REGISTER_SET Regs; - UINTN UpperCylinder; - UINTN Temp; - UINTN Cylinder; - UINTN Head; - UINTN Sector; - UINTN NumberOfBlocks; - UINTN TransferByteSize; - UINTN ShortLba; - UINTN CheckLba; - UINTN BlockSize; - BIOS_LEGACY_DRIVE *Bios; - UINTN CarryFlag; - UINTN Retry; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - - Media = This->Media; - BlockSize = Media->BlockSize; - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (Lba > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize == 0) { - return EFI_SUCCESS; - } - - BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); - ShortLba = (UINTN) Lba; - - while (BufferSize != 0) { - // - // Compute I/O location in Sector, Head, Cylinder format - // - Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1; - Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector; - Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1); - Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1); - - // - // Limit transfer to this Head & Cylinder - // - NumberOfBlocks = BufferSize / BlockSize; - Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1; - NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks; - - Retry = 3; - do { - // - // Perform the IO - // - Regs.H.AH = 3; - Regs.H.AL = (UINT8) NumberOfBlocks; - Regs.H.DL = BiosBlockIoDev->Bios.Number; - - UpperCylinder = (Cylinder & 0x0f00) >> 2; - - CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head; - CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1; - - DEBUG ( - (DEBUG_BLKIO, - "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n", - ShortLba, - CheckLba, - Sector, - BiosBlockIoDev->Bios.MaxSector, - Head, - BiosBlockIoDev->Bios.MaxHead, - Cylinder, - UpperCylinder) - ); - ASSERT (CheckLba == ShortLba); - - Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)); - Regs.H.DH = (UINT8) (Head & 0x3f); - Regs.H.CH = (UINT8) (Cylinder & 0xff); - - Regs.X.BX = EFI_OFFSET (mEdd11Buffer); - Regs.X.ES = EFI_SEGMENT (mEdd11Buffer); - - TransferByteSize = NumberOfBlocks * BlockSize; - CopyMem (mEdd11Buffer, Buffer, TransferByteSize); - - DEBUG ( - (DEBUG_BLKIO, - "INT 13h: AX:(03%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n", - Regs.H.AL, - (UINT8) (Head & 0x3f), - Regs.H.DL, - (UINT8) (Cylinder & 0xff), - (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)), - EFI_OFFSET (mEdd11Buffer), - EFI_SEGMENT (mEdd11Buffer)) - ); - - CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); - DEBUG ( - ( - DEBUG_BLKIO, "BiosWriteLegacyDrive: INT 13 03 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, - CarryFlag, Regs.H.AH - ) - ); - Retry--; - } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED); - - Media->MediaPresent = TRUE; - if (CarryFlag != 0) { - // - // Return Error Status - // - BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; - if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { - Media->MediaId++; - Bios = &BiosBlockIoDev->Bios; - if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { - if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { - Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; - Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; - } else { - // - // Legacy Interfaces - // - Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; - Media->BlockSize = 512; - } - // - // If the size of the media changed we need to reset the disk geometry - // - Media->ReadOnly = FALSE; - gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); - gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); - return EFI_MEDIA_CHANGED; - } - } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { - Media->ReadOnly = TRUE; - return EFI_WRITE_PROTECTED; - } - - if (Media->RemovableMedia) { - Media->MediaPresent = FALSE; - } - - return EFI_DEVICE_ERROR; - } - - Media->ReadOnly = FALSE; - ShortLba = ShortLba + NumberOfBlocks; - BufferSize = BufferSize - TransferByteSize; - Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); - } - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf deleted file mode 100644 index 86dd325d23..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf +++ /dev/null @@ -1,65 +0,0 @@ -## @file -# BIOS Block IO module. -# -# This is the UEFI driver to thunk legacy BIOS int13 interface into UEFI block IO interface. -# Once connected it installs EfiBlockIoProtocol on top of legacy BIOS int13. -# -# 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 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 = BlockIoDxe - MODULE_UNI_FILE = BlockIoDxe.uni - FILE_GUID = 4495E47E-42A9-4007-8c17-B6664F909D04 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - - ENTRY_POINT = BiosBlockIoDriverEntryPoint - -[Sources] - BiosBlkIo.h - Edd.h - BiosBlkIo.c - BiosInt13.c - ComponentName.c - -[LibraryClasses] - UefiDriverEntryPoint - DebugLib - BaseMemoryLib - UefiBootServicesTableLib - UefiLib - DevicePathLib - MemoryAllocationLib - - -[Protocols] - gEfiBlockIoProtocolGuid ## BY_START - gEfiDevicePathProtocolGuid ## BY_START - gEfiDevicePathProtocolGuid ## TO_START - gEfiPciIoProtocolGuid ## TO_START - gEfiLegacyBiosProtocolGuid ## TO_START - - -[Guids] - gEfiLegacyBiosGuid ## PRODUCES ## UNDEFINED - gBlockIoVendorGuid ## SOMETIMES_CONSUMES ## UNDEFINED - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[UserExtensions.TianoCore."ExtraFiles"] - BlockIoDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni deleted file mode 100644 index 6698430ee1..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni deleted file mode 100644 index 900682d090..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c deleted file mode 100644 index 21d17305fa..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c +++ /dev/null @@ -1,309 +0,0 @@ -/** @file - -Copyright (c) 1999 - 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 "BiosBlkIo.h" - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoComponentNameGetDriverName ( - 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 -BiosBlockIoComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName = { - BiosBlockIoComponentNameGetDriverName, - BiosBlockIoComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosBlockIoComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosBlockIoComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosBlockIoDriverNameTable[] = { - { - "eng;en", - L"BIOS[INT13] Block Io Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -BiosBlockIoComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mBiosBlockIoDriverNameTable, - DriverName, - (BOOLEAN)(This == &gBiosBlockIoComponentName) - ); -} - -/** - 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 -BiosBlockIoComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h deleted file mode 100644 index be4d8302cf..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h +++ /dev/null @@ -1,209 +0,0 @@ -/** @file - Include file to suport EDD 3.0. - This file is coded to T13 D1386 Revision 3 - Availible on http://www.t13.org/#Project drafts - Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r3.pdf - -Copyright (c) 1999 - 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 _EDD_H_ -#define _EDD_H_ - -// -// packing with no compiler padding, so that the fields -// of the following architected structures can be -// properly accessed from C code. -// -#pragma pack(1) - -typedef struct { - UINT8 Bus; - UINT8 Device; - UINT8 Function; - UINT8 Controller; - UINT32 Reserved; -} EDD_PCI; - -typedef struct { - UINT16 Base; - UINT16 Reserved; - UINT32 Reserved2; -} EDD_LEGACY; - -typedef union { - EDD_PCI Pci; - EDD_LEGACY Legacy; -} EDD_INTERFACE_PATH; - -typedef struct { - UINT8 Master; - UINT8 Reserved[15]; -} EDD_ATA; - -typedef struct { - UINT8 Master; - UINT8 Lun; - UINT8 Reserved[14]; -} EDD_ATAPI; - -typedef struct { - UINT16 Pun; - UINT64 Lun; - UINT8 Reserved[6]; -} EDD_SCSI; - -typedef struct { - UINT64 SerialNumber; - UINT64 Reserved; -} EDD_USB; - -typedef struct { - UINT64 Guid; - UINT64 Reserved; -} EDD_1394; - -typedef struct { - UINT64 Wwn; - UINT64 Lun; -} EDD_FIBRE; - -typedef union { - EDD_ATA Ata; - EDD_ATAPI Atapi; - EDD_SCSI Scsi; - EDD_USB Usb; - EDD_1394 FireWire; - EDD_FIBRE FibreChannel; -} EDD_DEVICE_PATH; - -typedef struct { - UINT16 StructureSize; - UINT16 Flags; - UINT32 MaxCylinders; - UINT32 MaxHeads; - UINT32 SectorsPerTrack; - UINT64 PhysicalSectors; - UINT16 BytesPerSector; - UINT32 Fdpt; - UINT16 Key; - UINT8 DevicePathLength; - UINT8 Reserved1; - UINT16 Reserved2; - CHAR8 HostBusType[4]; - CHAR8 InterfaceType[8]; - EDD_INTERFACE_PATH InterfacePath; - EDD_DEVICE_PATH DevicePath; - UINT8 Reserved3; - UINT8 Checksum; -} EDD_DRIVE_PARAMETERS; - -// -// EDD_DRIVE_PARAMETERS.Flags defines -// -#define EDD_GEOMETRY_VALID 0x02 -#define EDD_DEVICE_REMOVABLE 0x04 -#define EDD_WRITE_VERIFY_SUPPORTED 0x08 -#define EDD_DEVICE_CHANGE 0x10 -#define EDD_DEVICE_LOCKABLE 0x20 - -// -// BUGBUG: This bit does not follow the spec. It tends to be always set -// to work properly with Win98. -// -#define EDD_DEVICE_GEOMETRY_MAX 0x40 - -typedef struct { - UINT8 PacketSizeInBytes; // 0x18 - UINT8 Zero; - UINT8 NumberOfBlocks; // Max 0x7f - UINT8 Zero2; - UINT32 SegOffset; - UINT64 Lba; - UINT64 TransferBuffer; - UINT32 ExtendedBlockCount; // Max 0xffffffff - UINT32 Zero3; -} EDD_DEVICE_ADDRESS_PACKET; - -#define EDD_VERSION_30 0x30 - -// -// Int 13 BIOS Errors -// -#define BIOS_PASS 0x00 -#define BIOS_WRITE_PROTECTED 0x03 -#define BIOS_SECTOR_NOT_FOUND 0x04 -#define BIOS_RESET_FAILED 0x05 -#define BIOS_DISK_CHANGED 0x06 -#define BIOS_DRIVE_DOES_NOT_EXIST 0x07 -#define BIOS_DMA_ERROR 0x08 -#define BIOS_DATA_BOUNDRY_ERROR 0x09 -#define BIOS_BAD_SECTOR 0x0a -#define BIOS_BAD_TRACK 0x0b -#define BIOS_MEADIA_TYPE_NOT_FOUND 0x0c -#define BIOS_INVALED_FORMAT 0x0d -#define BIOS_ECC_ERROR 0x10 -#define BIOS_ECC_CORRECTED_ERROR 0x11 -#define BIOS_HARD_DRIVE_FAILURE 0x20 -#define BIOS_SEEK_FAILED 0x40 -#define BIOS_DRIVE_TIMEOUT 0x80 -#define BIOS_DRIVE_NOT_READY 0xaa -#define BIOS_UNDEFINED_ERROR 0xbb -#define BIOS_WRITE_FAULT 0xcc -#define BIOS_SENSE_FAILED 0xff - -#define MAX_EDD11_XFER 0xfe00 - -#pragma pack() -// -// Internal Data Structures -// -typedef struct { - CHAR8 Letter; - UINT8 Number; - UINT8 EddVersion; - BOOLEAN ExtendedInt13; - BOOLEAN DriveLockingAndEjecting; - BOOLEAN Edd; - BOOLEAN Extensions64Bit; - BOOLEAN ParametersValid; - UINT8 ErrorCode; - VOID *FdptPointer; - BOOLEAN Floppy; - BOOLEAN AtapiFloppy; - UINT8 MaxHead; - UINT8 MaxSector; - UINT16 MaxCylinder; - UINT16 Pad; - EDD_DRIVE_PARAMETERS Parameters; -} BIOS_LEGACY_DRIVE; - -#define BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE SIGNATURE_32 ('b', 'b', 'i', 'o') -typedef struct { - UINTN Signature; - - EFI_HANDLE Handle; - EFI_HANDLE ControllerHandle; - EFI_BLOCK_IO_PROTOCOL BlockIo; - EFI_BLOCK_IO_MEDIA BlockMedia; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - - BIOS_LEGACY_DRIVE Bios; - -} BIOS_BLOCK_IO_DEV; - -#define BIOS_BLOCK_IO_FROM_THIS(a) CR (a, BIOS_BLOCK_IO_DEV, BlockIo, BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE) - -#endif diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c deleted file mode 100644 index 8c7019f4f6..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c +++ /dev/null @@ -1,2428 +0,0 @@ -/** @file - ConsoleOut Routines that speak VGA. - -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 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 "BiosKeyboard.h" - -// -// EFI Driver Binding Protocol Instance -// -EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding = { - BiosKeyboardDriverBindingSupported, - BiosKeyboardDriverBindingStart, - BiosKeyboardDriverBindingStop, - 0x3, - NULL, - NULL -}; - - -/** - Enqueue the key. - - @param Queue The queue to be enqueued. - @param KeyData The key data to be enqueued. - - @retval EFI_NOT_READY The queue is full. - @retval EFI_SUCCESS Successfully enqueued the key data. - -**/ -EFI_STATUS -Enqueue ( - IN SIMPLE_QUEUE *Queue, - IN EFI_KEY_DATA *KeyData - ) -{ - if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) { - return EFI_NOT_READY; - } - - CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA)); - Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT; - - return EFI_SUCCESS; -} - - -/** - Dequeue the key. - - @param Queue The queue to be dequeued. - @param KeyData The key data to be dequeued. - - @retval EFI_NOT_READY The queue is empty. - @retval EFI_SUCCESS Successfully dequeued the key data. - -**/ -EFI_STATUS -Dequeue ( - IN SIMPLE_QUEUE *Queue, - IN EFI_KEY_DATA *KeyData - ) -{ - if (Queue->Front == Queue->Rear) { - return EFI_NOT_READY; - } - - CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA)); - Queue->Front = (Queue->Front + 1) % QUEUE_MAX_COUNT; - - return EFI_SUCCESS; -} - - -/** - Check whether the queue is empty. - - @param Queue The queue to be checked. - - @retval EFI_NOT_READY The queue is empty. - @retval EFI_SUCCESS The queue is not empty. - -**/ -EFI_STATUS -CheckQueue ( - IN SIMPLE_QUEUE *Queue - ) -{ - if (Queue->Front == Queue->Rear) { - return EFI_NOT_READY; - } - - return EFI_SUCCESS; -} - -// -// EFI Driver Binding Protocol Functions -// - -/** - Check whether the driver supports this device. - - @param This The Udriver binding protocol. - @param Controller The controller handle to check. - @param RemainingDevicePath The remaining device path. - - @retval EFI_SUCCESS The driver supports this controller. - @retval other This device isn't supported. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_ISA_IO_PROTOCOL *IsaIo; - - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol ( - &gEfiLegacyBiosProtocolGuid, - NULL, - (VOID **) &LegacyBios - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Use the ISA I/O Protocol to see if Controller is the Keyboard controller - // - if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) { - Status = EFI_UNSUPPORTED; - } - - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Starts the device with this driver. - - @param This The driver binding instance. - @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 The controller is controlled by the driver. - @retval Other This controller cannot be started. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_ISA_IO_PROTOCOL *IsaIo; - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - EFI_IA32_REGISTER_SET Regs; - BOOLEAN CarryFlag; - EFI_PS2_POLICY_PROTOCOL *Ps2Policy; - UINT8 Command; - EFI_STATUS_CODE_VALUE StatusCode; - - BiosKeyboardPrivate = NULL; - IsaIo = NULL; - StatusCode = 0; - - // - // Get Ps2 policy to set. Will be use if present. - // - gBS->LocateProtocol ( - &gEfiPs2PolicyProtocolGuid, - NULL, - (VOID **) &Ps2Policy - ); - - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol ( - &gEfiLegacyBiosProtocolGuid, - NULL, - (VOID **) &LegacyBios - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Open the IO Abstraction(s) needed - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Allocate the private device structure - // - BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV)); - if (NULL == BiosKeyboardPrivate) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - // - // Initialize the private device structure - // - BiosKeyboardPrivate->Signature = BIOS_KEYBOARD_DEV_SIGNATURE; - BiosKeyboardPrivate->Handle = Controller; - BiosKeyboardPrivate->LegacyBios = LegacyBios; - BiosKeyboardPrivate->IsaIo = IsaIo; - - BiosKeyboardPrivate->SimpleTextIn.Reset = BiosKeyboardReset; - BiosKeyboardPrivate->SimpleTextIn.ReadKeyStroke = BiosKeyboardReadKeyStroke; - - BiosKeyboardPrivate->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER; - BiosKeyboardPrivate->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER; - BiosKeyboardPrivate->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER; - BiosKeyboardPrivate->ExtendedKeyboard = TRUE; - - BiosKeyboardPrivate->Queue.Front = 0; - BiosKeyboardPrivate->Queue.Rear = 0; - BiosKeyboardPrivate->SimpleTextInputEx.Reset = BiosKeyboardResetEx; - BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx; - BiosKeyboardPrivate->SimpleTextInputEx.SetState = BiosKeyboardSetState; - BiosKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify = BiosKeyboardRegisterKeyNotify; - BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify; - InitializeListHead (&BiosKeyboardPrivate->NotifyList); - - // - // Report that the keyboard is being enabled - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE - ); - - // - // Setup the WaitForKey event - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_WAIT, - TPL_NOTIFY, - BiosKeyboardWaitForKey, - &(BiosKeyboardPrivate->SimpleTextIn), - &((BiosKeyboardPrivate->SimpleTextIn).WaitForKey) - ); - if (EFI_ERROR (Status)) { - (BiosKeyboardPrivate->SimpleTextIn).WaitForKey = NULL; - goto Done; - } - Status = gBS->CreateEvent ( - EVT_NOTIFY_WAIT, - TPL_NOTIFY, - BiosKeyboardWaitForKeyEx, - &(BiosKeyboardPrivate->SimpleTextInputEx), - &(BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx) - ); - if (EFI_ERROR (Status)) { - BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL; - goto Done; - } - - // - // Setup a periodic timer, used for reading keystrokes at a fixed interval - // - Status = gBS->CreateEvent ( - EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - BiosKeyboardTimerHandler, - BiosKeyboardPrivate, - &BiosKeyboardPrivate->TimerEvent - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; - goto Done; - } - - Status = gBS->SetTimer ( - BiosKeyboardPrivate->TimerEvent, - TimerPeriodic, - KEYBOARD_TIMER_INTERVAL - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; - goto Done; - } - - // - // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT - ); - - // - // Reset the keyboard device - // - Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset ( - &BiosKeyboardPrivate->SimpleTextInputEx, - FeaturePcdGet (PcdPs2KbdExtendedVerification) - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status)); - StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; - goto Done; - } - // - // Do platform specific policy like port swapping and keyboard light default - // - if (Ps2Policy != NULL) { - - Ps2Policy->Ps2InitHardware (Controller); - - Command = 0; - if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) { - Command |= 4; - } - - if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) { - Command |= 2; - } - - if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) { - Command |= 1; - } - - KeyboardWrite (BiosKeyboardPrivate, 0xed); - KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT); - KeyboardWrite (BiosKeyboardPrivate, Command); - // - // Call Legacy BIOS Protocol to set whatever is necessary - // - LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command); - } - // - // Get Configuration - // - Regs.H.AH = 0xc0; - CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 ( - BiosKeyboardPrivate->LegacyBios, - 0x15, - &Regs - ); - - if (!CarryFlag) { - // - // Check bit 6 of Feature Byte 2. - // If it is set, then Int 16 Func 09 is supported - // - if (*(UINT8 *)(UINTN) ((Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) { - // - // Get Keyboard Functionality - // - Regs.H.AH = 0x09; - CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 ( - BiosKeyboardPrivate->LegacyBios, - 0x16, - &Regs - ); - - if (!CarryFlag) { - // - // Check bit 5 of AH. - // If it is set, then INT 16 Finc 10-12 are supported. - // - if ((Regs.H.AL & 0x40) != 0) { - // - // Set the flag to use INT 16 Func 10-12 - // - BiosKeyboardPrivate->ExtendedKeyboard = TRUE; - } - } - } - } - DEBUG ((EFI_D_INFO, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN)BiosKeyboardPrivate->ExtendedKeyboard)); - // - // Install protocol interfaces for the keyboard device. - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiSimpleTextInProtocolGuid, - &BiosKeyboardPrivate->SimpleTextIn, - &gEfiSimpleTextInputExProtocolGuid, - &BiosKeyboardPrivate->SimpleTextInputEx, - NULL - ); - -Done: - if (StatusCode != 0) { - // - // Report an Error Code for failing to start the keyboard device - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - StatusCode - ); - } - - if (EFI_ERROR (Status)) { - - if (BiosKeyboardPrivate != NULL) { - if ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) { - gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey); - } - - if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) { - gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx); - } - BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList); - - if (BiosKeyboardPrivate->TimerEvent != NULL) { - gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent); - } - - FreePool (BiosKeyboardPrivate); - } - - if (IsaIo != NULL) { - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - } - } - - return Status; -} - -/** - Stop the device handled by this driver. - - @param This The driver binding protocol. - @param Controller The controller to release. - @param NumberOfChildren The number of handles in ChildHandleBuffer. - @param ChildHandleBuffer The array of child handle. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - @retval Others Fail to uninstall protocols attached on the device. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn; - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - - // - // Disable Keyboard - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiSimpleTextInProtocolGuid, - (VOID **) &SimpleTextIn, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->OpenProtocol ( - Controller, - &gEfiSimpleTextInputExProtocolGuid, - NULL, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (SimpleTextIn); - - Status = gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiSimpleTextInProtocolGuid, - &BiosKeyboardPrivate->SimpleTextIn, - &gEfiSimpleTextInputExProtocolGuid, - &BiosKeyboardPrivate->SimpleTextInputEx, - NULL - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Release the IsaIo protocol on the controller handle - // - gBS->CloseProtocol ( - Controller, - &gEfiIsaIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Free other resources - // - gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey); - gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent); - gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx); - BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList); - - FreePool (BiosKeyboardPrivate); - - return EFI_SUCCESS; -} - -/** - Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer-empty state. - - @param BiosKeyboardPrivate Keyboard instance pointer. - - @return The data byte read from output buffer of Keyboard Controller from data port which often is port 60H. - -**/ -UINT8 -KeyReadDataRegister ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate - ) -{ - UINT8 Data; - - // - // Use IsaIo protocol to perform IO operations - // - BiosKeyboardPrivate->IsaIo->Io.Read ( - BiosKeyboardPrivate->IsaIo, - EfiIsaIoWidthUint8, - BiosKeyboardPrivate->DataRegisterAddress, - 1, - &Data - ); - - return Data; -} - -/** - Read status byte from status register of Keyboard Controller without delay and waiting for buffer-empty state. - - @param BiosKeyboardPrivate Keyboard instance pointer. - - @return The status byte read from status register of Keyboard Controller from command port which often is port 64H. - -**/ -UINT8 -KeyReadStatusRegister ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate - ) -{ - UINT8 Data; - - // - // Use IsaIo protocol to perform IO operations - // - BiosKeyboardPrivate->IsaIo->Io.Read ( - BiosKeyboardPrivate->IsaIo, - EfiIsaIoWidthUint8, - BiosKeyboardPrivate->StatusRegisterAddress, - 1, - &Data - ); - - return Data; -} - -/** - Write command byte to control register of Keyboard Controller without delay and waiting for buffer-empty state. - - @param BiosKeyboardPrivate Keyboard instance pointer. - @param Data Data byte to write. - -**/ -VOID -KeyWriteCommandRegister ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - IN UINT8 Data - ) -{ - // - // Use IsaIo protocol to perform IO operations - // - BiosKeyboardPrivate->IsaIo->Io.Write ( - BiosKeyboardPrivate->IsaIo, - EfiIsaIoWidthUint8, - BiosKeyboardPrivate->CommandRegisterAddress, - 1, - &Data - ); -} - -/** - Write data byte to input buffer or input/output ports of Keyboard Controller without delay and waiting for buffer-empty state. - - @param BiosKeyboardPrivate Keyboard instance pointer. - @param Data Data byte to write. - -**/ -VOID -KeyWriteDataRegister ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - IN UINT8 Data - ) -{ - // - // Use IsaIo protocol to perform IO operations - // - BiosKeyboardPrivate->IsaIo->Io.Write ( - BiosKeyboardPrivate->IsaIo, - EfiIsaIoWidthUint8, - BiosKeyboardPrivate->DataRegisterAddress, - 1, - &Data - ); -} - -/** - Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer-empty state. - - @param BiosKeyboardPrivate Keyboard instance pointer. - @param Data The pointer for data that being read out. - - @retval EFI_SUCCESS The data byte read out successfully. - @retval EFI_TIMEOUT Timeout occurred during reading out data byte. - -**/ -EFI_STATUS -KeyboardRead ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - OUT UINT8 *Data - ) -{ - UINT32 TimeOut; - UINT32 RegFilled; - - TimeOut = 0; - RegFilled = 0; - - // - // wait till output buffer full then perform the read - // - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) { - RegFilled = 1; - *Data = KeyReadDataRegister (BiosKeyboardPrivate); - break; - } - - gBS->Stall (30); - } - - if (RegFilled == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state. - - @param BiosKeyboardPrivate Keyboard instance pointer. - @param Data Data byte to write. - - @retval EFI_SUCCESS The data byte is written successfully. - @retval EFI_TIMEOUT Timeout occurred during writing. - -**/ -EFI_STATUS -KeyboardWrite ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - IN UINT8 Data - ) -{ - UINT32 TimeOut; - UINT32 RegEmptied; - - TimeOut = 0; - RegEmptied = 0; - - // - // wait for input buffer empty - // - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) { - RegEmptied = 1; - break; - } - - gBS->Stall (30); - } - - if (RegEmptied == 0) { - return EFI_TIMEOUT; - } - // - // Write it - // - KeyWriteDataRegister (BiosKeyboardPrivate, Data); - - return EFI_SUCCESS; -} - -/** - Write command byte to control register of Keyboard Controller with delay and waiting for buffer-empty state. - - @param BiosKeyboardPrivate Keyboard instance pointer. - @param Data Command byte to write. - - @retval EFI_SUCCESS The command byte is written successfully. - @retval EFI_TIMEOUT Timeout occurred during writing. - -**/ -EFI_STATUS -KeyboardCommand ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - IN UINT8 Data - ) -{ - UINT32 TimeOut; - UINT32 RegEmptied; - - TimeOut = 0; - RegEmptied = 0; - - // - // Wait For Input Buffer Empty - // - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) { - RegEmptied = 1; - break; - } - - gBS->Stall (30); - } - - if (RegEmptied == 0) { - return EFI_TIMEOUT; - } - // - // issue the command - // - KeyWriteCommandRegister (BiosKeyboardPrivate, Data); - - // - // Wait For Input Buffer Empty again - // - RegEmptied = 0; - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) { - RegEmptied = 1; - break; - } - - gBS->Stall (30); - } - - if (RegEmptied == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Wait for a specific value to be presented in - Data register of Keyboard Controller by keyboard and then read it, - used in keyboard commands ack - - @param BiosKeyboardPrivate Keyboard instance pointer. - @param Value The value to be waited for - @param WaitForValueTimeOut The limit of microseconds for timeout - - @retval EFI_SUCCESS The command byte is written successfully. - @retval EFI_TIMEOUT Timeout occurred during writing. - -**/ -EFI_STATUS -KeyboardWaitForValue ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - IN UINT8 Value, - IN UINTN WaitForValueTimeOut - ) -{ - UINT8 Data; - UINT32 TimeOut; - UINT32 SumTimeOut; - UINT32 GotIt; - - GotIt = 0; - TimeOut = 0; - SumTimeOut = 0; - - // - // Make sure the initial value of 'Data' is different from 'Value' - // - Data = 0; - if (Data == Value) { - Data = 1; - } - // - // Read from 8042 (multiple times if needed) - // until the expected value appears - // use SumTimeOut to control the iteration - // - while (1) { - // - // Perform a read - // - for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { - if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) { - Data = KeyReadDataRegister (BiosKeyboardPrivate); - break; - } - - gBS->Stall (30); - } - - SumTimeOut += TimeOut; - - if (Data == Value) { - GotIt = 1; - break; - } - - if (SumTimeOut >= WaitForValueTimeOut) { - break; - } - } - // - // Check results - // - if (GotIt != 0) { - return EFI_SUCCESS; - } else { - return EFI_TIMEOUT; - } - -} - -/** - 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 BiosKeyboardPrivate Bioskeyboard driver private structure. - @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 -KeyboardReadKeyStrokeWorker ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - OUT EFI_KEY_DATA *KeyData - ) -{ - EFI_STATUS Status; - EFI_TPL OldTpl; - if (KeyData == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Use TimerEvent callback funciton to check whether there's any key pressed - // - - // - // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event. - // Csm will be used to check whether there is a key pending, but the csm will disable all - // interrupt before switch to compatibility16, which mean all the efiCompatibility timer - // event will stop work during the compatibility16. And If a caller recursivly invoke this function, - // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period, - // e.g. usb keyboard driver. - // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked. - // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input. - // - gBS->Stall (1000); - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - BiosKeyboardTimerHandler (NULL, BiosKeyboardPrivate); - // - // If there's no key, just return - // - Status = CheckQueue (&BiosKeyboardPrivate->Queue); - if (EFI_ERROR (Status)) { - gBS->RestoreTPL (OldTpl); - return EFI_NOT_READY; - } - - Status = Dequeue (&BiosKeyboardPrivate->Queue, KeyData); - - gBS->RestoreTPL (OldTpl); - - return EFI_SUCCESS; -} - -// -// EFI Simple Text In Protocol Functions -// -/** - Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations. - - @param This Pointer of simple text Protocol. - @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip. - - @retval EFI_SUCCESS The command byte is written successfully. - @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardReset ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - EFI_STATUS Status; - EFI_TPL OldTpl; - UINT8 CommandByte; - BOOLEAN MouseEnable; - EFI_INPUT_KEY Key; - - MouseEnable = FALSE; - BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This); - - // - // 1 - // Report reset progress code - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET - ); - - // - // Report a Progress Code for clearing the keyboard buffer - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER - ); - - // - // 2 - // Raise TPL to avoid mouse operation impact - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // - // Exhaust output buffer data - // - do { - Status = BiosKeyboardReadKeyStroke ( - This, - &Key - ); - } while (!EFI_ERROR (Status)); - // - // 3 - // check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H - // if not skip step 4&5 and jump to step 6 to selftest KBC and report this - // else go step 4 - // - if (!PcdGetBool (PcdFastPS2Detection)) { - if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) { - // - // 4 - // CheckMouseStatus to decide enable it later or not - // - // - // Read the command byte of KBC - // - Status = KeyboardCommand ( - BiosKeyboardPrivate, - KBC_CMDREG_VIA64_CMDBYTE_R - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardRead ( - BiosKeyboardPrivate, - &CommandByte - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - // - // Check mouse enabled or not before - // - if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) { - MouseEnable = FALSE; - } else { - MouseEnable = TRUE; - } - // - // 5 - // disable mouse (via KBC) and Keyborad device - // - Status = KeyboardCommand ( - BiosKeyboardPrivate, - KBC_CMDREG_VIA64_AUX_DISABLE - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardCommand ( - BiosKeyboardPrivate, - KBC_CMDREG_VIA64_KB_DISABLE - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - } else { - // - // 6 - // KBC Self Test - // - // - // Report a Progress Code for performing a self test on the keyboard controller - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST - ); - - Status = KeyboardCommand ( - BiosKeyboardPrivate, - KBC_CMDREG_VIA64_KBC_SLFTEST - ); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardWaitForValue ( - BiosKeyboardPrivate, - KBC_CMDECHO_KBCSLFTEST_OK, - KEYBOARD_WAITFORVALUE_TIMEOUT - ); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - } - } - // - // 7 - // Disable Mouse interface, enable Keyboard interface and declare selftest success - // - // Mouse device will block keyboard interface before it be configured, so we should disable mouse first. - // - Status = KeyboardCommand ( - BiosKeyboardPrivate, - KBC_CMDREG_VIA64_CMDBYTE_W - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - // - // Write 8042 Command Byte, set System Flag - // While at the same time: - // 1. disable mouse interface, - // 2. enable kbd interface, - // 3. enable PC/XT kbd translation mode - // 4. enable mouse and kbd interrupts - // - //Command Byte bits: - // 7: Reserved - // 6: PC/XT translation mode - // 5: Disable Auxiliary device interface - // 4: Disable keyboard interface - // 3: Reserved - // 2: System Flag - // 1: Enable Auxiliary device interrupt - // 0: Enable Keyboard interrupt - // - CommandByte = 0; - Status = KeyboardWrite ( - BiosKeyboardPrivate, - (UINT8) ((CommandByte & - (~KB_CMMBYTE_DISABLE_KB)) | - KB_CMMBYTE_KSCAN2UNI_COV | - KB_CMMBYTE_ENABLE_AUXINT | - KB_CMMBYTE_ENABLE_KBINT | - KB_CMMBYTE_SLFTEST_SUCC | - KB_CMMBYTE_DISABLE_AUX) - ); - - // - // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow, - // so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped. - // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected, - // Real reset will not do. - // - if (ExtendedVerification && CheckKeyboardConnect (BiosKeyboardPrivate)) { - // - // 8 - // Send keyboard reset command then read ACK - // - Status = KeyboardWrite ( - BiosKeyboardPrivate, - KBC_INPBUF_VIA60_KBRESET - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardWaitForValue ( - BiosKeyboardPrivate, - KBC_CMDECHO_ACK, - KEYBOARD_WAITFORVALUE_TIMEOUT - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - // - // 9 - // Wait for keyboard return test OK. - // - Status = KeyboardWaitForValue ( - BiosKeyboardPrivate, - KBC_CMDECHO_BATTEST_OK, - KEYBOARD_WAITFORVALUE_TIMEOUT - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - // - // 10 - // set keyboard scan code set = 02 (standard configuration) - // - Status = KeyboardWrite ( - BiosKeyboardPrivate, - KBC_INPBUF_VIA60_KBSCODE - ); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardWaitForValue ( - BiosKeyboardPrivate, - KBC_CMDECHO_ACK, - KEYBOARD_WAITFORVALUE_TIMEOUT - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardWrite ( - BiosKeyboardPrivate, - KBC_INPBUF_VIA60_SCODESET2 - ); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardWaitForValue ( - BiosKeyboardPrivate, - KBC_CMDECHO_ACK, - KEYBOARD_WAITFORVALUE_TIMEOUT - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - // - // 11 - // enable keyboard itself (not via KBC) by writing CMD F4 via 60H - // - Status = KeyboardWrite ( - BiosKeyboardPrivate, - KBC_INPBUF_VIA60_KBEN - ); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardWaitForValue ( - BiosKeyboardPrivate, - KBC_CMDECHO_ACK, - KEYBOARD_WAITFORVALUE_TIMEOUT - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - // - // 12 - // Additional validation, do it as follow: - // 1). check for status register of PARE && TIM via 64H - // 2). perform KB checking by writing ABh via 64H - // - if ((KeyReadStatusRegister (BiosKeyboardPrivate) & (KBC_STSREG_VIA64_PARE | KBC_STSREG_VIA64_TIM)) != 0) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardCommand ( - BiosKeyboardPrivate, - KBC_CMDREG_VIA64_KB_CKECK - ); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - Status = KeyboardWaitForValue ( - BiosKeyboardPrivate, - KBC_CMDECHO_KBCHECK_OK, - KEYBOARD_WAITFORVALUE_TIMEOUT - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - } - // - // 13 - // Done for validating keyboard. Enable keyboard (via KBC) - // and recover the command byte to proper value - // - if (!PcdGetBool (PcdFastPS2Detection)) { - Status = KeyboardCommand ( - BiosKeyboardPrivate, - KBC_CMDREG_VIA64_KB_ENABLE - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - } - - // - // 14 - // conditionally enable mouse (via KBC) - // - if (MouseEnable) { - Status = KeyboardCommand ( - BiosKeyboardPrivate, - KBC_CMDREG_VIA64_AUX_ENABLE - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - - } - } - -Exit: - // - // 15 - // resume priority of task level - // - gBS->RestoreTPL (OldTpl); - - return Status; - -} - -/** - Read out the scan code of the key that has just been stroked. - - @param This Pointer of simple text Protocol. - @param Key Pointer for store the key that read out. - - @retval EFI_SUCCESS The key is read out successfully. - @retval other The key reading failed. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardReadKeyStroke ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, - OUT EFI_INPUT_KEY *Key - ) -{ - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - EFI_STATUS Status; - EFI_KEY_DATA KeyData; - - BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This); - - Status = KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, &KeyData); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Convert the Ctrl+[a-z] to Ctrl+[1-26] - // - if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { - if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { - KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); - } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { - KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); - } - } - - CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); - - return EFI_SUCCESS; -} - -/** - Waiting on the keyboard event, if there's any key pressed by the user, signal the event - - @param Event The event that be siganlled when any key has been stroked. - @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL. - -**/ -VOID -EFIAPI -BiosKeyboardWaitForKey ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event. - // Csm will be used to check whether there is a key pending, but the csm will disable all - // interrupt before switch to compatibility16, which mean all the efiCompatibility timer - // event will stop work during the compatibility16. And If a caller recursivly invoke this function, - // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period, - // e.g. usb keyboard driver. - // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked. - // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input. - // - gBS->Stall (1000); - // - // Use TimerEvent callback funciton to check whether there's any key pressed - // - BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context)); - - if (!EFI_ERROR (BiosKeyboardCheckForKey (Context))) { - gBS->SignalEvent (Event); - } -} - -/** - Check key buffer to get the key stroke status. - - @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL. - - @retval EFI_SUCCESS A key is being pressed now. - @retval Other No key is now pressed. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardCheckForKey ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This - ) -{ - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - - BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This); - - return CheckQueue (&BiosKeyboardPrivate->Queue); -} -// -// Private worker functions -// -#define TABLE_END 0x0 - -typedef struct _CONVERT_TABLE_ENTRY { - UINT16 ScanCode; - UINT16 EfiScanCode; -} CONVERT_TABLE_ENTRY; - -CONVERT_TABLE_ENTRY mConvertTable[] = { - { - 0x47, - SCAN_HOME - }, - { - 0x48, - SCAN_UP - }, - { - 0x49, - SCAN_PAGE_UP - }, - { - 0x4b, - SCAN_LEFT - }, - { - 0x4d, - SCAN_RIGHT - }, - { - 0x4f, - SCAN_END - }, - { - 0x50, - SCAN_DOWN - }, - { - 0x51, - SCAN_PAGE_DOWN - }, - { - 0x52, - SCAN_INSERT - }, - { - 0x53, - SCAN_DELETE - }, - // - // Function Keys are only valid if KeyChar == 0x00 - // This function does not require KeyChar to be 0x00 - // - { - 0x3b, - SCAN_F1 - }, - { - 0x3c, - SCAN_F2 - }, - { - 0x3d, - SCAN_F3 - }, - { - 0x3e, - SCAN_F4 - }, - { - 0x3f, - SCAN_F5 - }, - { - 0x40, - SCAN_F6 - }, - { - 0x41, - SCAN_F7 - }, - { - 0x42, - SCAN_F8 - }, - { - 0x43, - SCAN_F9 - }, - { - 0x44, - SCAN_F10 - }, - { - 0x85, - SCAN_F11 - }, - { - 0x86, - SCAN_F12 - }, - // - // Convert ALT + Fn keys - // - { - 0x68, - SCAN_F1 - }, - { - 0x69, - SCAN_F2 - }, - { - 0x6a, - SCAN_F3 - }, - { - 0x6b, - SCAN_F4 - }, - { - 0x6c, - SCAN_F5 - }, - { - 0x6d, - SCAN_F6 - }, - { - 0x6e, - SCAN_F7 - }, - { - 0x6f, - SCAN_F8 - }, - { - 0x70, - SCAN_F9 - }, - { - 0x71, - SCAN_F10 - }, - { - TABLE_END, - SCAN_NULL - }, -}; - -/** - Convert unicode combined with scan code of key to the counterpart of EFIScancode of it. - - @param KeyChar Unicode of key. - @param ScanCode Scan code of key. - - @return The value of EFI Scancode for the key. - @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key. - -**/ -UINT16 -ConvertToEFIScanCode ( - IN CHAR16 KeyChar, - IN UINT16 ScanCode - ) -{ - UINT16 EfiScanCode; - UINT16 Index; - - if (KeyChar == CHAR_ESC) { - EfiScanCode = SCAN_ESC; - } else if (KeyChar == 0x00 || KeyChar == 0xe0) { - // - // Movement & Function Keys - // - for (Index = 0; (Index < sizeof (mConvertTable) / sizeof (CONVERT_TABLE_ENTRY)) && (mConvertTable[Index].ScanCode != TABLE_END); Index += 1) { - if (ScanCode == mConvertTable[Index].ScanCode) { - return mConvertTable[Index].EfiScanCode; - } - } - // - // Reach Table end, return default value - // - return SCAN_NULL; - } else { - return SCAN_NULL; - } - - return EfiScanCode; -} - -/** - Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command - If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device - should not be in system. - - @param BiosKeyboardPrivate Keyboard Private Data Struture - - @retval TRUE Keyboard in System. - @retval FALSE Keyboard not in System. - -**/ -BOOLEAN -CheckKeyboardConnect ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate - ) -{ - EFI_STATUS Status; - - Status = EFI_SUCCESS; - // - // enable keyboard itself and wait for its ack - // If can't receive ack, Keyboard should not be connected. - // - if (!PcdGetBool (PcdFastPS2Detection)) { - Status = KeyboardWrite ( - BiosKeyboardPrivate, - KBC_INPBUF_VIA60_KBEN - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n")); - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR - ); - return FALSE; - } - - Status = KeyboardWaitForValue ( - BiosKeyboardPrivate, - KBC_CMDECHO_ACK, - KEYBOARD_WAITFORVALUE_TIMEOUT - ); - - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Timeout!\n")); - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR - ); - return FALSE; - } - return TRUE; - } else { - return TRUE; - } -} - -/** - Timer event handler: read a series of key stroke from 8042 - and put them into memory key buffer. - It is registered as running under TPL_NOTIFY - - @param Event The timer event - @param Context A BIOS_KEYBOARD_DEV pointer - -**/ -VOID -EFIAPI -BiosKeyboardTimerHandler ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_TPL OldTpl; - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - EFI_IA32_REGISTER_SET Regs; - UINT8 KbFlag1; // 0040h:0017h - KEYBOARD - STATUS FLAGS 1 - UINT8 KbFlag2; // 0040h:0018h - KEYBOARD - STATUS FLAGS 2 - EFI_KEY_DATA KeyData; - LIST_ENTRY *Link; - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; - - BiosKeyboardPrivate = Context; - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // if there is no key present, just return - // - if (BiosKeyboardPrivate->ExtendedKeyboard) { - Regs.H.AH = 0x11; - } else { - Regs.H.AH = 0x01; - } - - BiosKeyboardPrivate->LegacyBios->Int86 ( - BiosKeyboardPrivate->LegacyBios, - 0x16, - &Regs - ); - if (Regs.X.Flags.ZF != 0) { - gBS->RestoreTPL (OldTpl); - return; - } - - // - // Read the key - // - if (BiosKeyboardPrivate->ExtendedKeyboard) { - Regs.H.AH = 0x10; - } else { - Regs.H.AH = 0x00; - } - - BiosKeyboardPrivate->LegacyBios->Int86 ( - BiosKeyboardPrivate->LegacyBios, - 0x16, - &Regs - ); - - KeyData.Key.ScanCode = (UINT16) Regs.H.AH; - KeyData.Key.UnicodeChar = (UINT16) Regs.H.AL; - DEBUG (( - EFI_D_INFO, - "[KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n", - KeyData.Key.ScanCode, - KeyData.Key.UnicodeChar - )); - - KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; - KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; - // - // Leagcy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB buffer in BDA (BIOS DATE AREA), then - // Int 16 depend KB buffer and some key bits in BDA to translate the scancode to ASCII code, and return both the scancode and ASCII - // code to Int 16 caller. This translation process works well if the Int 9 could response user input in time. But in Tiano enviorment, the Int 9 - // will be disabled after the thunk call finish, which means if user crazy input during int 9 being disabled, some keystrokes will be lost when - // KB device own hardware buffer overflows. And if the lost keystroke code is CTRL or ALT or SHIFT release code, these function key flags bit - // in BDA will not be updated. So the Int 16 will believe the CTRL or ALT or SHIFT is still pressed, and Int 16 will translate later scancode - // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other dirvers - // performance, like USB. - // - // 1. If CTRL or ALT release code is missed, all later input keys will be translated to wrong ASCII codes which the Tiano cannot support. In - // this case, the KB input seems fail to work, and user input is blocked. To solve the problem, we can help to clear the CTRL or ALT flag in BDA - // after every Int 16 finish. Thus persist to press CTRL or ALT has same effection as only press one time. It is Ok, since user not often use the - // CTRL and ALT. - // - // 2. If SHIFT release code is missed, all later lowercase input will become capital. This is ugly, but not block user input. If user press the lost - // SHIFT again, the lowercase will come back to normal. Since user often use the SHIFT, it is not reasonable to help to clear the SHIFT flag in BDA, - // which will let persist to press SHIFT has same effection as only press one time. - // - //0040h:0017h - KEYBOARD - STATUS FLAGS 1 - // 7 INSert active - // 6 Caps Lock active - // 5 Num Lock active - // 4 Scroll Lock active - // 3 either Alt pressed - // 2 either Ctrl pressed - // 1 Left Shift pressed - // 0 Right Shift pressed - - - // - // Clear the CTRL and ALT BDA flag - // - KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1 - KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2 - - DEBUG_CODE ( - { - if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) { - DEBUG ((EFI_D_INFO, "[KBD]Caps Lock Key is pressed.\n")); - } - if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) { - DEBUG ((EFI_D_INFO, "[KBD]Num Lock Key is pressed.\n")); - } - if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) { - DEBUG ((EFI_D_INFO, "[KBD]Scroll Lock Key is pressed.\n")); - } - if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) { - if ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) { - DEBUG ((EFI_D_INFO, "[KBD]Left Alt Key is pressed.\n")); - } else { - DEBUG ((EFI_D_INFO, "[KBD]Right Alt Key is pressed.\n")); - } - } - if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) { - if ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) { - DEBUG ((EFI_D_INFO, "[KBD]Left Ctrl Key is pressed.\n")); - } else { - DEBUG ((EFI_D_INFO, "[KBD]Right Ctrl Key is pressed.\n")); - } - } - if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) { - DEBUG ((EFI_D_INFO, "[KBD]Left Shift Key is pressed.\n")); - } - if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) { - DEBUG ((EFI_D_INFO, "[KBD]Right Shift Key is pressed.\n")); - } - } - ); - - // - // Record toggle state - // - if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) { - KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE; - } - if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) { - KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE; - } - if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) { - KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE; - } - // - // Record shift state - // BUGBUG: Need add Menu key and Left/Right Logo key state in the future - // - if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) { - KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) ? EFI_LEFT_ALT_PRESSED : EFI_RIGHT_ALT_PRESSED; - } - if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) { - KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) ? EFI_LEFT_CONTROL_PRESSED : EFI_RIGHT_CONTROL_PRESSED; - } - if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) { - KeyData.KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED; - } - if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) { - KeyData.KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED; - } - - // - // Clear left alt and left ctrl BDA flag - // - KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED); - *((UINT8 *) (UINTN) 0x418) = KbFlag2; - KbFlag1 &= ~0x0C; - *((UINT8 *) (UINTN) 0x417) = KbFlag1; - - - // - // Output EFI input key and shift/toggle state - // - if (KeyData.Key.UnicodeChar == CHAR_NULL || KeyData.Key.UnicodeChar == CHAR_SCANCODE || KeyData.Key.UnicodeChar == CHAR_ESC) { - KeyData.Key.ScanCode = ConvertToEFIScanCode (KeyData.Key.UnicodeChar, KeyData.Key.ScanCode); - KeyData.Key.UnicodeChar = CHAR_NULL; - } else { - KeyData.Key.ScanCode = SCAN_NULL; - } - - // - // CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back. - // - if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { - if (KeyData.Key.UnicodeChar >= 1 && KeyData.Key.UnicodeChar <= 26) { - if (((KeyData.KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) == - ((KeyData.KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0) - ) { - KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'a' - 1); - } else { - KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'A' - 1); - } - } - } - - DEBUG (( - EFI_D_INFO, - "[KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n", - KeyData.Key.ScanCode, - KeyData.Key.UnicodeChar - )); - - // - // Need not return associated shift state if a class of printable characters that - // are normally adjusted by shift modifiers. - // e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'. - // - if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') || - (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') - ) { - DEBUG ((EFI_D_INFO, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n")); - KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED); - } - - // - // Invoke notification functions if exist - // - for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { - CurrentNotify = CR ( - Link, - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { - CurrentNotify->KeyNotificationFn (&KeyData); - } - } - - Enqueue (&BiosKeyboardPrivate->Queue, &KeyData); - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - - return ; -} - -/** - Free keyboard notify list. - - @param ListHead The list head - - @retval EFI_SUCCESS Free the notify list successfully - @retval EFI_INVALID_PARAMETER ListHead is invalid. - -**/ -EFI_STATUS -BiosKeyboardFreeNotifyList ( - IN OUT LIST_ENTRY *ListHead - ) -{ - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode; - - if (ListHead == NULL) { - return EFI_INVALID_PARAMETER; - } - while (!IsListEmpty (ListHead)) { - NotifyNode = CR ( - ListHead->ForwardLink, - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - RemoveEntryList (ListHead->ForwardLink); - gBS->FreePool (NotifyNode); - } - - return EFI_SUCCESS; -} - -/** - Check if key is registered. - - @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; - -} - -/** - Waiting on the keyboard event, if there's any key pressed by the user, signal the event - - @param Event The event that be siganlled when any key has been stroked. - @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. - -**/ -VOID -EFIAPI -BiosKeyboardWaitForKeyEx ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - - BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (Context); - BiosKeyboardWaitForKey (Event, &BiosKeyboardPrivate->SimpleTextIn); - -} - -/** - 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 -BiosKeyboardResetEx ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - EFI_STATUS Status; - EFI_TPL OldTpl; - - BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); - - Status = BiosKeyboardPrivate->SimpleTextIn.Reset ( - &BiosKeyboardPrivate->SimpleTextIn, - ExtendedVerification - ); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - gBS->RestoreTPL (OldTpl); - - return EFI_SUCCESS; - -} - -/** - 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 -BiosKeyboardReadKeyStrokeEx ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - OUT EFI_KEY_DATA *KeyData - ) -{ - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - - if (KeyData == NULL) { - return EFI_INVALID_PARAMETER; - } - - BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); - - return KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, 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 -BiosKeyboardSetState ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN EFI_KEY_TOGGLE_STATE *KeyToggleState - ) -{ - EFI_STATUS Status; - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - EFI_TPL OldTpl; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - UINT8 Command; - - if (KeyToggleState == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Thunk keyboard driver doesn't support partial keystroke. - // - if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID || - (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED - ) { - return EFI_UNSUPPORTED; - } - - BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol ( - &gEfiLegacyBiosProtocolGuid, - NULL, - (VOID **) &LegacyBios - ); - - ASSERT_EFI_ERROR (Status); - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - Command = 0; - if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { - Command |= 4; - } - if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) { - Command |= 2; - } - if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { - Command |= 1; - } - - Status = KeyboardWrite (BiosKeyboardPrivate, 0xed); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - Status = KeyboardWrite (BiosKeyboardPrivate, Command); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - // - // Call Legacy BIOS Protocol to set whatever is necessary - // - LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command); - - Status = EFI_SUCCESS; - -Exit: - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - - return Status; - -} - -/** - 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 NotifyHandle is NULL. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardRegisterKeyNotify ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN EFI_KEY_DATA *KeyData, - IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, - OUT VOID **NotifyHandle - ) -{ - EFI_STATUS Status; - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - EFI_TPL OldTpl; - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify; - LIST_ENTRY *Link; - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; - - if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { - return EFI_INVALID_PARAMETER; - } - - BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. - // - for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { - CurrentNotify = CR ( - Link, - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { - if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { - *NotifyHandle = CurrentNotify; - Status = EFI_SUCCESS; - goto Exit; - } - } - } - - // - // Allocate resource to save the notification function - // - - NewNotify = (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY)); - if (NewNotify == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - NewNotify->Signature = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; - NewNotify->KeyNotificationFn = KeyNotificationFunction; - CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); - InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry); - - *NotifyHandle = NewNotify; - Status = EFI_SUCCESS; - -Exit: - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - 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 -BiosKeyboardUnregisterKeyNotify ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN VOID *NotificationHandle - ) -{ - EFI_STATUS Status; - BIOS_KEYBOARD_DEV *BiosKeyboardPrivate; - EFI_TPL OldTpl; - LIST_ENTRY *Link; - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; - - // - // Check incoming notification handle - // - if (NotificationHandle == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (((BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) { - return EFI_INVALID_PARAMETER; - } - - BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); - - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { - CurrentNotify = CR ( - Link, - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, - BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - if (CurrentNotify == NotificationHandle) { - // - // Remove the notification function from NotifyList and free resources - // - RemoveEntryList (&CurrentNotify->NotifyEntry); - - Status = EFI_SUCCESS; - goto Exit; - } - } - - // - // Can not find the specified Notification Handle - // - Status = EFI_INVALID_PARAMETER; - -Exit: - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - The user Entry Point for module BiosKeyboard. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -InitializeBiosKeyboard( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gBiosKeyboardDriverBinding, - ImageHandle, - &gBiosKeyboardComponentName, - &gBiosKeyboardComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h deleted file mode 100644 index a27d2e1b23..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h +++ /dev/null @@ -1,743 +0,0 @@ -/** @file - -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 _BIOS_KEYBOARD_H_ -#define _BIOS_KEYBOARD_H_ - - -#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 gBiosKeyboardDriverBinding; -extern EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2; - - -#include - -// -// BISO Keyboard Defines -// -#define CHAR_SCANCODE 0xe0 -#define CHAR_ESC 0x1b - -#define KEYBOARD_8042_DATA_REGISTER 0x60 -#define KEYBOARD_8042_STATUS_REGISTER 0x64 -#define KEYBOARD_8042_COMMAND_REGISTER 0x64 - -#define KEYBOARD_TIMEOUT 65536 // 0.07s -#define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s -#define KEYBOARD_BAT_TIMEOUT 4000000 // 4s -#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s -// KEYBOARD COMMAND BYTE -- read by writing command KBC_CMDREG_VIA64_CMDBYTE_R to 64H, then read from 60H -// write by wrting command KBC_CMDREG_VIA64_CMDBYTE_W to 64H, then write to 60H -// 7: Reserved -// 6: PC/XT translation mode convert -// 5: Disable Auxiliary device interface -// 4: Disable keyboard interface -// 3: Reserved -// 2: System Flag: selftest successful -// 1: Enable Auxiliary device interrupt -// 0: Enable Keyboard interrupt ) -// -#define KB_CMMBYTE_KSCAN2UNI_COV (0x1 << 6) -#define KB_CMMBYTE_DISABLE_AUX (0x1 << 5) -#define KB_CMMBYTE_DISABLE_KB (0x1 << 4) -#define KB_CMMBYTE_SLFTEST_SUCC (0x1 << 2) -#define KB_CMMBYTE_ENABLE_AUXINT (0x1 << 1) -#define KB_CMMBYTE_ENABLE_KBINT (0x1 << 0) - -// -// KEYBOARD CONTROLLER STATUS REGISTER - read from 64h -// 7: Parity error -// 6: General time out -// 5: Output buffer holds data for AUX -// 4: Keyboard is not locked -// 3: Command written via 64h / Data written via 60h -// 2: KBC self-test successful / Power-on reset -// 1: Input buffer holds CPU data / empty -// 0: Output buffer holds keyboard data / empty -// -#define KBC_STSREG_VIA64_PARE (0x1 << 7) -#define KBC_STSREG_VIA64_TIM (0x1 << 6) -#define KBC_STSREG_VIA64_AUXB (0x1 << 5) -#define KBC_STSREG_VIA64_KEYL (0x1 << 4) -#define KBC_STSREG_VIA64_C_D (0x1 << 3) -#define KBC_STSREG_VIA64_SYSF (0x1 << 2) -#define KBC_STSREG_VIA64_INPB (0x1 << 1) -#define KBC_STSREG_VIA64_OUTB (0x1 << 0) - -// -// COMMANDs of KEYBOARD CONTROLLER COMMAND REGISTER - write to 64h -// -#define KBC_CMDREG_VIA64_CMDBYTE_R 0x20 -#define KBC_CMDREG_VIA64_CMDBYTE_W 0x60 -#define KBC_CMDREG_VIA64_AUX_DISABLE 0xA7 -#define KBC_CMDREG_VIA64_AUX_ENABLE 0xA8 -#define KBC_CMDREG_VIA64_KBC_SLFTEST 0xAA -#define KBC_CMDREG_VIA64_KB_CKECK 0xAB -#define KBC_CMDREG_VIA64_KB_DISABLE 0xAD -#define KBC_CMDREG_VIA64_KB_ENABLE 0xAE -#define KBC_CMDREG_VIA64_INTP_LOW_R 0xC0 -#define KBC_CMDREG_VIA64_INTP_HIGH_R 0xC2 -#define KBC_CMDREG_VIA64_OUTP_R 0xD0 -#define KBC_CMDREG_VIA64_OUTP_W 0xD1 -#define KBC_CMDREG_VIA64_OUTB_KB_W 0xD2 -#define KBC_CMDREG_VIA64_OUTB_AUX_W 0xD3 -#define KBC_CMDREG_VIA64_AUX_W 0xD4 - -// -// echos of KEYBOARD CONTROLLER COMMAND - read from 60h -// -#define KBC_CMDECHO_KBCSLFTEST_OK 0x55 -#define KBC_CMDECHO_KBCHECK_OK 0x00 -#define KBC_CMDECHO_ACK 0xFA -#define KBC_CMDECHO_BATTEST_OK 0xAA -#define KBC_CMDECHO_BATTEST_FAILE 0xFC - -// -// OUTPUT PORT COMMANDs - write port by writing KBC_CMDREG_VIA64_OUTP_W via 64H, then write the command to 60H -// drive data and clock of KB to high for at least 500us for BAT needs -// -#define KBC_OUTPORT_DCHIGH_BAT 0xC0 -// -// scan code set type -// -#define KBC_INPBUF_VIA60_SCODESET1 0x01 -#define KBC_INPBUF_VIA60_SCODESET2 0x02 -#define KBC_INPBUF_VIA60_SCODESET3 0x03 - -// -// COMMANDs written to INPUT BUFFER - write to 60h -// -#define KBC_INPBUF_VIA60_KBECHO 0xEE -#define KBC_INPBUF_VIA60_KBSCODE 0xF0 -#define KBC_INPBUF_VIA60_KBTYPE 0xF2 -#define KBC_INPBUF_VIA60_KBDELAY 0xF3 -#define KBC_INPBUF_VIA60_KBEN 0xF4 -#define KBC_INPBUF_VIA60_KBSTDDIS 0xF5 -#define KBC_INPBUF_VIA60_KBSTDEN 0xF6 -#define KBC_INPBUF_VIA60_KBRESEND 0xFE -#define KBC_INPBUF_VIA60_KBRESET 0xFF - -// -// 0040h:0017h - KEYBOARD - STATUS FLAGS 1 -// 7 INSert active -// 6 Caps Lock active -// 5 Num Lock active -// 4 Scroll Lock active -// 3 either Alt pressed -// 2 either Ctrl pressed -// 1 Left Shift pressed -// 0 Right Shift pressed -// -// 0040h:0018h - KEYBOARD - STATUS FLAGS 2 -// 7: insert key is depressed -// 6: caps-lock key is depressed (does not work well) -// 5: num-lock key is depressed (does not work well) -// 4: scroll lock key is depressed (does not work well) -// 3: suspend key has been toggled (does not work well) -// 2: system key is pressed and held (does not work well) -// 1: left ALT key is pressed -// 0: left CTRL key is pressed -// -#define KB_INSERT_BIT (0x1 << 7) -#define KB_CAPS_LOCK_BIT (0x1 << 6) -#define KB_NUM_LOCK_BIT (0x1 << 5) -#define KB_SCROLL_LOCK_BIT (0x1 << 4) -#define KB_ALT_PRESSED (0x1 << 3) -#define KB_CTRL_PRESSED (0x1 << 2) -#define KB_LEFT_SHIFT_PRESSED (0x1 << 1) -#define KB_RIGHT_SHIFT_PRESSED (0x1 << 0) - -#define KB_SUSPEND_PRESSED (0x1 << 3) -#define KB_SYSREQ_PRESSED (0x1 << 2) -#define KB_LEFT_ALT_PRESSED (0x1 << 1) -#define KB_LEFT_CTRL_PRESSED (0x1 << 0) - -// -// BIOS Keyboard Device Structure -// -#define BIOS_KEYBOARD_DEV_SIGNATURE SIGNATURE_32 ('B', 'K', 'B', 'D') -#define BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('c', 'b', 'k', 'h') - -typedef struct _BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY { - UINTN Signature; - EFI_KEY_DATA KeyData; - EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; - LIST_ENTRY NotifyEntry; -} BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY; - -#define QUEUE_MAX_COUNT 32 -typedef struct { - UINTN Front; - UINTN Rear; - EFI_KEY_DATA Buffer[QUEUE_MAX_COUNT]; -} SIMPLE_QUEUE; - -typedef struct { - UINTN Signature; - EFI_HANDLE Handle; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_ISA_IO_PROTOCOL *IsaIo; - EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn; - EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInputEx; - UINT16 DataRegisterAddress; - UINT16 StatusRegisterAddress; - UINT16 CommandRegisterAddress; - BOOLEAN ExtendedKeyboard; - - // - // Buffer storing EFI_KEY_DATA - // - SIMPLE_QUEUE Queue; - - // - // Notification Function List - // - LIST_ENTRY NotifyList; - EFI_EVENT TimerEvent; - -} BIOS_KEYBOARD_DEV; - -#define BIOS_KEYBOARD_DEV_FROM_THIS(a) CR (a, BIOS_KEYBOARD_DEV, SimpleTextIn, BIOS_KEYBOARD_DEV_SIGNATURE) -#define TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS(a) \ - CR (a, \ - BIOS_KEYBOARD_DEV, \ - SimpleTextInputEx, \ - BIOS_KEYBOARD_DEV_SIGNATURE \ - ) - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding; - -// -// Driver Binding Protocol functions -// - -/** - Check whether the driver supports this device. - - @param This The Udriver binding protocol. - @param Controller The controller handle to check. - @param RemainingDevicePath The remaining device path. - - @retval EFI_SUCCESS The driver supports this controller. - @retval other This device isn't supported. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Starts the device with this driver. - - @param This The driver binding instance. - @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 The controller is controlled by the driver. - @retval Other This controller cannot be started. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Stop the device handled by this driver. - - @param This The driver binding protocol. - @param Controller The controller to release. - @param NumberOfChildren The number of handles in ChildHandleBuffer. - @param ChildHandleBuffer The array of child handle. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - @retval Others Fail to uninstall protocols attached on the device. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -/** - 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 -BiosKeyboardComponentNameGetDriverName ( - 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 -BiosKeyboardComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - - -// -// Simple Text Input Protocol functions -// -/** - Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations. - - @param This Pointer of simple text Protocol. - @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip. - - @retval EFI_SUCCESS The command byte is written successfully. - @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardReset ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Read out the scan code of the key that has just been stroked. - - @param This Pointer of simple text Protocol. - @param Key Pointer for store the key that read out. - - @retval EFI_SUCCESS The key is read out successfully. - @retval other The key reading failed. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardReadKeyStroke ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, - OUT EFI_INPUT_KEY *Key - ); - -// -// Private worker functions -// -/** - Waiting on the keyboard event, if there's any key pressed by the user, signal the event - - @param Event The event that be siganlled when any key has been stroked. - @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL. - -**/ -VOID -EFIAPI -BiosKeyboardWaitForKey ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - Check key buffer to get the key stroke status. - - @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL. - - @retval EFI_SUCCESS A key is being pressed now. - @retval Other No key is now pressed. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardCheckForKey ( - IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This - ); - -/** - Convert unicode combined with scan code of key to the counterpart of EFIScancode of it. - - @param KeyChar Unicode of key. - @param ScanCode Scan code of key. - - @return The value of EFI Scancode for the key. - @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key. - -**/ -UINT16 -ConvertToEFIScanCode ( - IN CHAR16 KeyChar, - IN UINT16 ScanCode - ); - -/** - Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command - If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device - should not be in system. - - @param BiosKeyboardPrivate Keyboard Private Data Struture - - @retval TRUE Keyboard in System. - @retval FALSE Keyboard not in System. - -**/ -BOOLEAN -CheckKeyboardConnect ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate - ); - -/** - Timer event handler: read a series of key stroke from 8042 - and put them into memory key buffer. - It is registered as running under TPL_NOTIFY - - @param Event The timer event - @param Context A BIOS_KEYBOARD_DEV pointer - -**/ -VOID -EFIAPI -BiosKeyboardTimerHandler ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - 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 -BiosKeyboardResetEx ( - 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 -BiosKeyboardReadKeyStrokeEx ( - 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 -BiosKeyboardSetState ( - 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 NotifyHandle is NULL. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardRegisterKeyNotify ( - 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. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardUnregisterKeyNotify ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN VOID *NotificationHandle - ); - -/** - Wait for a specific value to be presented in - Data register of Keyboard Controller by keyboard and then read it, - used in keyboard commands ack - - @param BiosKeyboardPrivate Keyboard instance pointer. - @param Value The value to be waited for - @param WaitForValueTimeOut The limit of microseconds for timeout - - @retval EFI_SUCCESS The command byte is written successfully. - @retval EFI_TIMEOUT Timeout occurred during writing. - -**/ -EFI_STATUS -KeyboardWaitForValue ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - IN UINT8 Value, - IN UINTN WaitForValueTimeOut - ); - -/** - Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state. - - @param BiosKeyboardPrivate Keyboard instance pointer. - @param Data Data byte to write. - - @retval EFI_SUCCESS The data byte is written successfully. - @retval EFI_TIMEOUT Timeout occurred during writing. - -**/ -EFI_STATUS -KeyboardWrite ( - IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate, - IN UINT8 Data - ); - -/** - Free keyboard notify list. - - @param ListHead The list head - - @retval EFI_SUCCESS Free the notify list successfully - @retval EFI_INVALID_PARAMETER ListHead is invalid. - -**/ -EFI_STATUS -BiosKeyboardFreeNotifyList ( - IN OUT LIST_ENTRY *ListHead - ); - -/** - Check if key is registered. - - @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 - ); - -/** - Waiting on the keyboard event, if there's any key pressed by the user, signal the event - - @param Event The event that be siganlled when any key has been stroked. - @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. - -**/ -VOID -EFIAPI -BiosKeyboardWaitForKeyEx ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c deleted file mode 100644 index 45fa7a21f8..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c +++ /dev/null @@ -1,183 +0,0 @@ -/** @file - -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 "BiosKeyboard.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName = { - BiosKeyboardComponentNameGetDriverName, - BiosKeyboardComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosKeyboardComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosKeyboardComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosKeyboardDriverNameTable[] = { - { - "eng;en", - L"BIOS[INT16] Keyboard Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mBiosKeyboardDriverNameTable, - DriverName, - (BOOLEAN)(This == &gBiosKeyboardComponentName) - ); -} - -/** - 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 -BiosKeyboardComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h deleted file mode 100644 index 0218ef865c..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h +++ /dev/null @@ -1,153 +0,0 @@ -/** @file - -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 _BIOS_KEYBOARD_COMPONENT_NAME_H_ -#define _BIOS_KEYBOARD_COMPONENT_NAME_H_ - - -extern EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2; - -// -// EFI Component Name Functions -// -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -BiosKeyboardComponentNameGetDriverName ( - 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 -BiosKeyboardComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - - -#endif diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf deleted file mode 100644 index a453480aa9..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf +++ /dev/null @@ -1,77 +0,0 @@ -## @file -# Ps2 Keyboard driver. -# -# Ps2 Keyboard driver by using Legacy Bios protocol service and IsaIo protocol -# service. This dirver uses legacy INT16 to get the key stroke status. -# -# 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 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 = KeyboardDxe - MODULE_UNI_FILE = KeyboardDxe.uni - FILE_GUID = 5479662B-6AE4-49e8-A6BD-6DE4B625811F - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - - ENTRY_POINT = InitializeBiosKeyboard - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# -# DRIVER_BINDING = gBiosKeyboardDriverBinding -# COMPONENT_NAME = gBiosKeyboardComponentName -# - -[Sources] - ComponentName.c - ComponentName.h - BiosKeyboard.c - BiosKeyboard.h - - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - - -[LibraryClasses] - MemoryAllocationLib - UefiBootServicesTableLib - UefiDriverEntryPoint - ReportStatusCodeLib - BaseMemoryLib - UefiLib - DebugLib - BaseLib - PcdLib - -[Protocols] - gEfiIsaIoProtocolGuid ## TO_START - gEfiSimpleTextInProtocolGuid ## BY_START - gEfiSimpleTextInputExProtocolGuid ## BY_START - gEfiLegacyBiosProtocolGuid ## CONSUMES - gEfiPs2PolicyProtocolGuid ## SOMETIMES_CONSUMES - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|FALSE ## CONSUMES - -[Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection ## SOMETIMES_CONSUMES - -[UserExtensions.TianoCore."ExtraFiles"] - KeyboardDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni deleted file mode 100644 index f86542d37f..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni deleted file mode 100644 index 38f08d5138..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c deleted file mode 100644 index 7af2dedd5d..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c +++ /dev/null @@ -1,3522 +0,0 @@ -/** @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 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 "BiosSnp16.h" - - -/// -/// EFI Driver Binding Protocol Instance -/// -EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = { - BiosSnp16DriverBindingSupported, - BiosSnp16DriverBindingStart, - BiosSnp16DriverBindingStop, - 0x3, - NULL, - NULL -}; - -/// -/// This boolean is used to determine if we should release the cached vector during an error condition. -/// -BOOLEAN mCachedInt1A = FALSE; - -// -// Private worker functions; -// - -/** - Start the UNDI interface. - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - @param Ax PCI address of Undi device. - - @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. - @retval Others Status of start 16 bit UNDI ROM. -**/ -EFI_STATUS -Undi16SimpleNetworkStartUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - UINT16 Ax - ); - -/** - Start the UNDI interface - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - - @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. - @retval Others Status of start 16 bit UNDI ROM. -**/ -EFI_STATUS -Undi16SimpleNetworkStopUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice - ); - -/** - Stop the UNDI interface - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - - @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM. - @retval Others Status of stop 16 bit UNDI ROM. -**/ -EFI_STATUS -Undi16SimpleNetworkCleanupUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice - ); - -/** - Get runtime information for Undi network interface - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_SUCCESS Sucess operation. - @retval Others Fail to get runtime information for Undi network interface. -**/ -EFI_STATUS -Undi16SimpleNetworkGetInformation ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ); - -/** - Get NIC type - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_SUCCESS Sucess operation. - @retval Others Fail to get NIC type. -**/ -EFI_STATUS -Undi16SimpleNetworkGetNicType ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ); - -/** - Get NDIS information - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_SUCCESS Sucess operation. - @retval Others Fail to get NDIS information. -**/ -EFI_STATUS -Undi16SimpleNetworkGetNdisInfo ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ); - -/** - Signal handlers for ExitBootServices event. - - Clean up any Real-mode UNDI residue from the system - - @param Event ExitBootServices event - @param Context -**/ -VOID -EFIAPI -Undi16SimpleNetworkEvent ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - Loads the undi driver. - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - - @retval EFI_SUCCESS - Successfully loads undi driver. - @retval EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure. -**/ -EFI_STATUS -Undi16SimpleNetworkLoadUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice - ); - -/** - Unload 16 bit UNDI Option ROM from memory - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - - @return EFI_STATUS -**/ -EFI_STATUS -Undi16SimpleNetworkUnloadUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice - ); - -/** - Entry point for EFI drivers. - - @param ImageHandle Handle that identifies the loaded image. - @param SystemTable System Table for this image. - - @return EFI_STATUS Return status from EfiLibInstallAllDriverProtocols. -**/ -EFI_STATUS -EFIAPI -BiosSnp16DriverEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gBiosSnp16DriverBinding, - ImageHandle, - &gBiosSnp16ComponentName, - &gBiosSnp16ComponentName2 - ); -} - -// -// EFI Driver Binding Protocol Functions -// -/** - Tests to see if this driver supports a given controller. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS The driver supports given controller. - @retval EFI_UNSUPPORT The driver doesn't support given controller. - @retval Other Other errors prevent driver finishing to test - if the driver supports given controller. -**/ -EFI_STATUS -EFIAPI -BiosSnp16DriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; - - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // See if this is a PCI Network Controller by looking at the Command register and - // Class Code Register - // - Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci); - if (EFI_ERROR (Status)) { - Status = EFI_UNSUPPORTED; - goto Done; - } - - Status = EFI_UNSUPPORTED; - if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) { - Status = EFI_SUCCESS; - } - -Done: - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Starts the Snp device controller - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS - The device was started. - @retval EFI_DEVICE_ERROR - The device could not be started due to a device error. - @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -BiosSnp16DriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - EFI_DEV_PATH Node; - UINTN Index; - UINTN Index2; - UINTN Segment; - UINTN Bus; - UINTN Device; - UINTN Function; - UINTN Flags; - UINT64 Supports; - - SimpleNetworkDevice = NULL; - PciIo = NULL; - - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Open the IO Abstraction(s) needed - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - } - - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Check to see if there is a legacy option ROM image associated with this PCI device - // - Status = LegacyBios->CheckPciRom ( - LegacyBios, - Controller, - NULL, - NULL, - &Flags - ); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Post the legacy option ROM if it is available. - // - Status = LegacyBios->InstallPciRom ( - LegacyBios, - Controller, - NULL, - &Flags, - NULL, - NULL, - NULL, - NULL - ); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Allocate memory for this SimpleNetwork device instance - // - Status = gBS->AllocatePool ( - EfiBootServicesData, - sizeof (EFI_SIMPLE_NETWORK_DEV), - (VOID **) &SimpleNetworkDevice - ); - if (EFI_ERROR (Status)) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV)); - - // - // Initialize the SimpleNetwork device instance - // - SimpleNetworkDevice->Signature = EFI_SIMPLE_NETWORK_DEV_SIGNATURE; - SimpleNetworkDevice->LegacyBios = LegacyBios; - SimpleNetworkDevice->BaseDevicePath = DevicePath; - SimpleNetworkDevice->PciIo = PciIo; - - // - // Initialize the Nii Protocol - // - SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; - SimpleNetworkDevice->Nii.Type = EfiNetworkInterfaceUndi; - - CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4); - - // - // Load 16 bit UNDI Option ROM into Memory - // - Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI. Status = %r\n", Status)); - goto Done; - } - - SimpleNetworkDevice->UndiLoaded = TRUE; - - // - // Call PXENV_START_UNDI - Initilizes the UNID interface for use. - // - PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); - Status = Undi16SimpleNetworkStartUndi ( - SimpleNetworkDevice, - (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function)) - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi. Status = %r\n", Status)); - goto Done; - } - // - // Initialize the Simple Network Protocol - // - DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n")); - - SimpleNetworkDevice->SimpleNetwork.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; - SimpleNetworkDevice->SimpleNetwork.Start = Undi16SimpleNetworkStart; - SimpleNetworkDevice->SimpleNetwork.Stop = Undi16SimpleNetworkStop; - SimpleNetworkDevice->SimpleNetwork.Initialize = Undi16SimpleNetworkInitialize; - SimpleNetworkDevice->SimpleNetwork.Reset = Undi16SimpleNetworkReset; - SimpleNetworkDevice->SimpleNetwork.Shutdown = Undi16SimpleNetworkShutdown; - SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters; - SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress; - SimpleNetworkDevice->SimpleNetwork.Statistics = Undi16SimpleNetworkStatistics; - SimpleNetworkDevice->SimpleNetwork.MCastIpToMac = Undi16SimpleNetworkMCastIpToMac; - SimpleNetworkDevice->SimpleNetwork.NvData = Undi16SimpleNetworkNvData; - SimpleNetworkDevice->SimpleNetwork.GetStatus = Undi16SimpleNetworkGetStatus; - SimpleNetworkDevice->SimpleNetwork.Transmit = Undi16SimpleNetworkTransmit; - SimpleNetworkDevice->SimpleNetwork.Receive = Undi16SimpleNetworkReceive; - SimpleNetworkDevice->SimpleNetwork.Mode = &(SimpleNetworkDevice->SimpleNetworkMode); - - Status = gBS->CreateEvent ( - EVT_NOTIFY_WAIT, - TPL_NOTIFY, - Undi16SimpleNetworkWaitForPacket, - &SimpleNetworkDevice->SimpleNetwork, - &SimpleNetworkDevice->SimpleNetwork.WaitForPacket - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "ERROR : Could not create event. Status = %r\n", Status)); - goto Done; - } - // - // Create an event to be signalled when ExitBootServices occurs in order - // to clean up nicely - // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - Undi16SimpleNetworkEvent, - NULL, - &gEfiEventExitBootServicesGuid, - &SimpleNetworkDevice->EfiBootEvent - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "ERROR : Could not create event. Status = %r\n", Status)); - goto Done; - } - - // - // Create an event to be signalled when Legacy Boot occurs to clean up the IVT - // - Status = EfiCreateEventLegacyBootEx( - TPL_NOTIFY, - Undi16SimpleNetworkEvent, - NULL, - &SimpleNetworkDevice->LegacyBootEvent - ); - - if (EFI_ERROR(Status)) { - DEBUG ((DEBUG_ERROR,"ERROR : Could not create event. Status = %r\n",Status)); - goto Done; - } - - // - // Initialize the SimpleNetwork Mode Information - // - DEBUG ((DEBUG_NET, "Initialize Mode Information\n")); - - SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped; - SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize = 14; - SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE; - SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported = TRUE; - SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | - EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | - EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | - EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS | - EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; - SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR; - - // - // Initialize the SimpleNetwork Private Information - // - DEBUG ((DEBUG_NET, "Initialize Private Information\n")); - - Status = BiosSnp16AllocatePagesBelowOneMb ( - sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1, - (VOID **) &SimpleNetworkDevice->Xmit - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = BiosSnp16AllocatePagesBelowOneMb ( - 1, - &SimpleNetworkDevice->TxRealModeMediaHeader - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = BiosSnp16AllocatePagesBelowOneMb ( - 1, - &SimpleNetworkDevice->TxRealModeDataBuffer - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = BiosSnp16AllocatePagesBelowOneMb ( - 1, - &SimpleNetworkDevice->TxDestAddr - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - SimpleNetworkDevice->Xmit->XmitOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f); - - SimpleNetworkDevice->Xmit->XmitSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4); - - SimpleNetworkDevice->Xmit->DataBlkCount = 1; - - SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType = 1; - SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte = 0; - - SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f); - - SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4); - - SimpleNetworkDevice->TxBufferFifo.First = 0; - SimpleNetworkDevice->TxBufferFifo.Last = 0; - - // - // Start() the SimpleNetwork device - // - DEBUG ((DEBUG_NET, "Start()\n")); - - Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // GetInformation() the SimpleNetwork device - // - DEBUG ((DEBUG_NET, "GetInformation()\n")); - - Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Build the device path for the child device - // - ZeroMem (&Node, sizeof (Node)); - Node.DevPath.Type = MESSAGING_DEVICE_PATH; - Node.DevPath.SubType = MSG_MAC_ADDR_DP; - SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH)); - CopyMem ( - &Node.MacAddr.MacAddress, - &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, - sizeof (EFI_MAC_ADDRESS) - ); - SimpleNetworkDevice->DevicePath = AppendDevicePathNode ( - SimpleNetworkDevice->BaseDevicePath, - &Node.DevPath - ); - - // - // GetNicType() the SimpleNetwork device - // - DEBUG ((DEBUG_NET, "GetNicType()\n")); - - Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // GetNdisInfo() the SimpleNetwork device - // - DEBUG ((DEBUG_NET, "GetNdisInfo()\n")); - - Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Stop() the SimpleNetwork device - // - DEBUG ((DEBUG_NET, "Stop()\n")); - - Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Print Mode information - // - DEBUG ((DEBUG_NET, "Mode->State = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State)); - DEBUG ((DEBUG_NET, "Mode->HwAddressSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize)); - DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable)); - DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported)); - DEBUG ((DEBUG_NET, "Mode->NvRamSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize)); - DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize)); - DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting)); - DEBUG ((DEBUG_NET, "Mode->IfType = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType)); - DEBUG ((DEBUG_NET, "Mode->MCastFilterCount = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount)); - for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) { - DEBUG ((DEBUG_NET, " Filter[%02d] = ", Index)); - for (Index2 = 0; Index2 < 16; Index2++) { - DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2])); - } - - DEBUG ((DEBUG_NET, "\n")); - } - - DEBUG ((DEBUG_NET, "CurrentAddress = ")); - for (Index2 = 0; Index2 < 16; Index2++) { - DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2])); - } - - DEBUG ((DEBUG_NET, "\n")); - - DEBUG ((DEBUG_NET, "BroadcastAddress = ")); - for (Index2 = 0; Index2 < 16; Index2++) { - DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2])); - } - - DEBUG ((DEBUG_NET, "\n")); - - DEBUG ((DEBUG_NET, "PermanentAddress = ")); - for (Index2 = 0; Index2 < 16; Index2++) { - DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2])); - } - - DEBUG ((DEBUG_NET, "\n")); - - // - // The network device was started, information collected, and stopped. - // Install protocol interfaces for the SimpleNetwork device. - // - DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n")); - - Status = gBS->InstallMultipleProtocolInterfaces ( - &SimpleNetworkDevice->Handle, - &gEfiSimpleNetworkProtocolGuid, - &SimpleNetworkDevice->SimpleNetwork, - &gEfiNetworkInterfaceIdentifierProtocolGuid, - &SimpleNetworkDevice->Nii, - &gEfiDevicePathProtocolGuid, - SimpleNetworkDevice->DevicePath, - NULL - ); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Open PCI I/O from the newly created child handle - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - SimpleNetworkDevice->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - - DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n")); - -Done: - if (EFI_ERROR (Status)) { - if (SimpleNetworkDevice != NULL) { - - Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork); - // - // CLOSE + SHUTDOWN - // - Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice); - // - // CLEANUP - // - Undi16SimpleNetworkStopUndi (SimpleNetworkDevice); - // - // STOP - // - if (SimpleNetworkDevice->UndiLoaded) { - Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice); - } - - if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) { - gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket); - } - - if (SimpleNetworkDevice->LegacyBootEvent != NULL) { - gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent); - } - - if (SimpleNetworkDevice->EfiBootEvent != NULL) { - gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent); - } - - if (SimpleNetworkDevice->Xmit != NULL) { - gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit, - sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1 - ); - } - - if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) { - gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1); - } - - if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) { - gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1); - } - - if (SimpleNetworkDevice->TxDestAddr != NULL) { - gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1); - } - - gBS->FreePool (SimpleNetworkDevice); - - // - // Only restore the vector if it was cached. - // - if (mCachedInt1A) { - RestoreCachedVectorAddress (0x1A); - mCachedInt1A = FALSE; - } - } - - if (PciIo != NULL) { - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationDisable, - Supports, - NULL - ); - } - } - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - if (Status != EFI_OUT_OF_RESOURCES) { - Status = EFI_DEVICE_ERROR; - } - } - return Status; -} - -/** - Stops the device by given device controller. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param ChildHandleBuffer An array of child handles to be freed. May be NULL if - NumberOfChildren is 0. - - @retval EFI_SUCCESS - The device was stopped. - @retval EFI_DEVICE_ERROR - The device could not be stopped due to a device error. -**/ -EFI_STATUS -EFIAPI -BiosSnp16DriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - UINTN Index; - BOOLEAN AllChildrenStopped; - EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT64 Supports; - - // - // Complete all outstanding transactions to Controller. - // Don't allow any new transaction to Controller to be started. - // - if (NumberOfChildren == 0) { - // - // Close the bus driver - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationDisable, - Supports, - NULL - ); - } - } - - Status = gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - Status = gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - } - return Status; - } - - AllChildrenStopped = TRUE; - - for (Index = 0; Index < NumberOfChildren; Index++) { - - Status = gBS->OpenProtocol ( - ChildHandleBuffer[Index], - &gEfiSimpleNetworkProtocolGuid, - (VOID **) &SimpleNetwork, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork); - - Status = gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - ChildHandleBuffer[Index] - ); - - Status = gBS->UninstallMultipleProtocolInterfaces ( - SimpleNetworkDevice->Handle, - &gEfiSimpleNetworkProtocolGuid, - &SimpleNetworkDevice->SimpleNetwork, - &gEfiNetworkInterfaceIdentifierProtocolGuid, - &SimpleNetworkDevice->Nii, - &gEfiDevicePathProtocolGuid, - SimpleNetworkDevice->DevicePath, - NULL - ); - if (EFI_ERROR (Status)) { - gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - ChildHandleBuffer[Index], - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - } else { - - Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork); - // - // CLOSE + SHUTDOWN - // - Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice); - // - // CLEANUP - // - Undi16SimpleNetworkStopUndi (SimpleNetworkDevice); - // - // STOP - // - if (SimpleNetworkDevice->UndiLoaded) { - Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice); - } - - if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) { - gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket); - } - - if (SimpleNetworkDevice->LegacyBootEvent != NULL) { - gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent); - } - - if (SimpleNetworkDevice->EfiBootEvent != NULL) { - gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent); - } - - if (SimpleNetworkDevice->Xmit != NULL) { - gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit, - sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1 - ); - } - - if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) { - gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1); - } - - if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) { - gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1); - } - - if (SimpleNetworkDevice->TxDestAddr != NULL) { - gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1); - } - - gBS->FreePool (SimpleNetworkDevice); - } - - } - - if (EFI_ERROR (Status)) { - AllChildrenStopped = FALSE; - } - } - - if (!AllChildrenStopped) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -// -// FIFO Support Functions -// -/** - Judge whether transmit FIFO is full. - - @param Fifo Point to trasmit FIFO structure. - - @return BOOLEAN whether transmit FIFO is full. -**/ -BOOLEAN -SimpleNetworkTransmitFifoFull ( - EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo - ) -{ - if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) { - return TRUE; - } - - return FALSE; -} - -/** - Judge whether transmit FIFO is empty. - - @param Fifo Point to trasmit FIFO structure. - - @return BOOLEAN whether transmit FIFO is empty. -**/ -BOOLEAN -SimpleNetworkTransmitFifoEmpty ( - EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo - ) -{ - if (Fifo->Last == Fifo->First) { - return TRUE; - } - - return FALSE; -} - - -/** - Add data into transmit buffer. - - @param Fifo Point to trasmit FIFO structure. - @param Data The data point want to be added. - - @retval EFI_OUT_OF_RESOURCES FIFO is full - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -SimpleNetworkTransmitFifoAdd ( - EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo, - VOID *Data - ) -{ - if (SimpleNetworkTransmitFifoFull (Fifo)) { - return EFI_OUT_OF_RESOURCES; - } - - Fifo->Data[Fifo->Last] = Data; - Fifo->Last = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE; - return EFI_SUCCESS; -} - -/** - Get a data and remove it from network transmit FIFO. - - @param Fifo Point to trasmit FIFO structure. - @param Data On return, point to the data point want to be got and removed. - - @retval EFI_OUT_OF_RESOURCES network transmit buffer is empty. - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -SimpleNetworkTransmitFifoRemove ( - EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo, - VOID **Data - ) -{ - if (SimpleNetworkTransmitFifoEmpty (Fifo)) { - return EFI_OUT_OF_RESOURCES; - } - - *Data = Fifo->Data[Fifo->First]; - Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE; - return EFI_SUCCESS; -} - -/** - Get recive filter setting according to EFI mask value. - - @param ReceiveFilterSetting filter setting EFI mask value. - - @return UINT16 Undi filter setting value. -**/ -UINT16 -Undi16GetPacketFilterSetting ( - UINTN ReceiveFilterSetting - ) -{ - UINT16 PktFilter; - - PktFilter = 0; - if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) { - PktFilter |= FLTR_DIRECTED; - } - - if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { - PktFilter |= FLTR_DIRECTED; - } - - if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) { - PktFilter |= FLTR_BRDCST; - } - - if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) { - PktFilter |= FLTR_PRMSCS; - } - - if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) { - PktFilter |= FLTR_PRMSCS; - // - // @bug : Do not know if this is right???? - // - } - // - // @bug : What is FLTR_SRC_RTG? - // - return PktFilter; -} - -/** - Get filter setting from multi cast buffer . - - @param Mode Point to mode structure. - @param McastBuffer The multi cast buffer - @param HwAddressSize Size of filter value. - -**/ -VOID -Undi16GetMCastFilters ( - IN EFI_SIMPLE_NETWORK_MODE *Mode, - IN OUT PXENV_UNDI_MCAST_ADDR_T *McastBuffer, - IN UINTN HwAddressSize - ) -{ - UINTN Index; - - // - // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR? - // - McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount; - for (Index = 0; Index < MAXNUM_MCADDR; Index++) { - if (Index < McastBuffer->MCastAddrCount) { - CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize); - } else { - ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize); - } - } -} -// -// Load 16 bit UNDI Option ROM into memory -// -/** - Loads the undi driver. - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - - @retval EFI_SUCCESS - Successfully loads undi driver. - @retval EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure. -**/ -EFI_STATUS -Undi16SimpleNetworkLoadUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - UINTN RomAddress; - PCI_EXPANSION_ROM_HEADER *PciExpansionRomHeader; - PCI_DATA_STRUCTURE *PciDataStructure; - PCI_TYPE00 Pci; - - if (!mCachedInt1A) { - Status = CacheVectorAddress (0x1A); - if (!EFI_ERROR (Status)) { - mCachedInt1A = TRUE; - } - } - - PciIo = SimpleNetworkDevice->PciIo; - - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (Pci) / sizeof (UINT32), - &Pci - ); - - for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) { - - PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress; - - if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { - continue; - } - - DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress)); - - // - // If the pointer to the PCI Data Structure is invalid, no further images can be located. - // The PCI Data Structure must be DWORD aligned. - // - if (PciExpansionRomHeader->PcirOffset == 0 || - (PciExpansionRomHeader->PcirOffset & 3) != 0 || - RomAddress + PciExpansionRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > 0x100000) { - break; - } - - PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset); - - if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { - continue; - } - - DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure)); - - if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) { - continue; - } - - DEBUG ( - (DEBUG_INIT, - "PCI device with matchinng VendorId and DeviceId (%d,%d)\n", - (UINTN) PciDataStructure->VendorId, - (UINTN) PciDataStructure->DeviceId) - ); - - Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress); - - if (!EFI_ERROR (Status)) { - return EFI_SUCCESS; - } - - // - // Free resources allocated in LaunchBaseCode - // - Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice); - } - - return EFI_NOT_FOUND; -} - -/** - Unload 16 bit UNDI Option ROM from memory - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - - @return EFI_STATUS -**/ -EFI_STATUS -Undi16SimpleNetworkUnloadUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice - ) -{ - if (SimpleNetworkDevice->UndiLoaderTable != NULL) { - ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT); - gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable, - SimpleNetworkDevice->UndiLoaderTablePages - ); - } - - if (SimpleNetworkDevice->DestinationDataSegment != NULL) { - ZeroMem ( - SimpleNetworkDevice->DestinationDataSegment, - SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT - ); - gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment, - SimpleNetworkDevice->DestinationDataSegmentPages - ); - } - - if (SimpleNetworkDevice->DestinationStackSegment != NULL) { - ZeroMem ( - SimpleNetworkDevice->DestinationStackSegment, - SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT - ); - gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment, - SimpleNetworkDevice->DestinationStackSegmentPages - ); - } - - if (SimpleNetworkDevice->DestinationCodeSegment != NULL) { - ZeroMem ( - SimpleNetworkDevice->DestinationCodeSegment, - SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT - ); - gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment, - SimpleNetworkDevice->DestinationCodeSegmentPages - ); - } - - return EFI_SUCCESS; -} - -/** - Start the UNDI interface. - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - @param Ax PCI address of Undi device. - - @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. - @retval Others Status of start 16 bit UNDI ROM. -**/ -EFI_STATUS -Undi16SimpleNetworkStartUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - UINT16 Ax - ) -{ - EFI_STATUS Status; - PXENV_START_UNDI_T Start; - - // - // Call 16 bit UNDI ROM to start the network interface - // - // - // @bug : What is this state supposed to be??? - // - Start.Status = INIT_PXE_STATUS; - Start.Ax = Ax; - Start.Bx = 0x0000; - Start.Dx = 0x0000; - Start.Di = 0x0000; - Start.Es = 0x0000; - - Status = PxeStartUndi (SimpleNetworkDevice, &Start); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Start.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - return Status; -} - - -/** - Stop the UNDI interface - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - - @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM. - @retval Others Status of stop 16 bit UNDI ROM. -**/ -EFI_STATUS -Undi16SimpleNetworkStopUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice - ) -{ - EFI_STATUS Status; - PXENV_STOP_UNDI_T Stop; - - // - // Call 16 bit UNDI ROM to start the network interface - // - Stop.Status = INIT_PXE_STATUS; - - Status = PxeUndiStop (SimpleNetworkDevice, &Stop); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Stop.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - return Status; -} - -/** - Cleanup Unid network interface - - @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure. - - @retval EFI_DEVICE_ERROR Fail to cleanup 16 bit UNDI ROM. - @retval Others Status of cleanup 16 bit UNDI ROM. -**/ -EFI_STATUS -Undi16SimpleNetworkCleanupUndi ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice - ) -{ - EFI_STATUS Status; - PXENV_UNDI_CLEANUP_T Cleanup; - - // - // Call 16 bit UNDI ROM to cleanup the network interface - // - Cleanup.Status = INIT_PXE_STATUS; - - Status = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Cleanup.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - return Status; -} - -/** - Get runtime information for Undi network interface - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_SUCCESS Sucess operation. - @retval Others Fail to get runtime information for Undi network interface. -**/ -EFI_STATUS -Undi16SimpleNetworkGetInformation ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - UINTN Index; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkStarted: - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - default: - return EFI_DEVICE_ERROR; - } - // - // Call 16 bit UNDI ROM to start the network interface - // - ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T)); - - SimpleNetworkDevice->GetInformation.Status = INIT_PXE_STATUS; - - Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation); - if (EFI_ERROR (Status)) { - return Status; - } - - DEBUG ((DEBUG_NET, " GetInformation.Status = %d\n", SimpleNetworkDevice->GetInformation.Status)); - DEBUG ((DEBUG_NET, " GetInformation.BaseIo = %d\n", SimpleNetworkDevice->GetInformation.BaseIo)); - DEBUG ((DEBUG_NET, " GetInformation.IntNumber = %d\n", SimpleNetworkDevice->GetInformation.IntNumber)); - DEBUG ((DEBUG_NET, " GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit)); - DEBUG ((DEBUG_NET, " GetInformation.HwType = %d\n", SimpleNetworkDevice->GetInformation.HwType)); - DEBUG ((DEBUG_NET, " GetInformation.HwAddrLen = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen)); - DEBUG ((DEBUG_NET, " GetInformation.ROMAddress = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress)); - DEBUG ((DEBUG_NET, " GetInformation.RxBufCt = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt)); - DEBUG ((DEBUG_NET, " GetInformation.TxBufCt = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt)); - - DEBUG ((DEBUG_NET, " GetInformation.CurNodeAddr =")); - for (Index = 0; Index < 16; Index++) { - DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index])); - } - - DEBUG ((DEBUG_NET, "\n")); - - DEBUG ((DEBUG_NET, " GetInformation.PermNodeAddr =")); - for (Index = 0; Index < 16; Index++) { - DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index])); - } - - DEBUG ((DEBUG_NET, "\n")); - - // - // Check the status code from the 16 bit UNDI ROM - // - if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // The information has been retrieved. Fill in Mode data. - // - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize = SimpleNetworkDevice->GetInformation.HwAddrLen; - - SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize = SimpleNetworkDevice->GetInformation.MaxTranUnit; - - SimpleNetworkDevice->SimpleNetworkMode.IfType = (UINT8) SimpleNetworkDevice->GetInformation.HwType; - - ZeroMem ( - &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, - sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress - ); - - CopyMem ( - &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, - &SimpleNetworkDevice->GetInformation.CurrentNodeAddress, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - ZeroMem ( - &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress, - sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress - ); - - CopyMem ( - &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress, - &SimpleNetworkDevice->GetInformation.PermNodeAddress, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - // - // hard code broadcast address - not avail in PXE2.1 - // - ZeroMem ( - &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress, - sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress - ); - - SetMem ( - &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize, - 0xff - ); - - return Status; -} - -/** - Get NIC type - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_SUCCESS Sucess operation. - @retval Others Fail to get NIC type. -**/ -EFI_STATUS -Undi16SimpleNetworkGetNicType ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - - ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T)); - - SimpleNetworkDevice->GetNicType.Status = INIT_PXE_STATUS; - - Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType); - - if (EFI_ERROR (Status)) { - return Status; - } - - DEBUG ((DEBUG_NET, " GetNicType.Status = %d\n", SimpleNetworkDevice->GetNicType.Status)); - DEBUG ((DEBUG_NET, " GetNicType.NicType = %d\n", SimpleNetworkDevice->GetNicType.NicType)); - // - // Check the status code from the 16 bit UNDI ROM - // - if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // The information has been retrieved. Fill in Mode data. - // - return Status; -} - -/** - Get NDIS information - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_SUCCESS Sucess operation. - @retval Others Fail to get NDIS information. -**/ -EFI_STATUS -Undi16SimpleNetworkGetNdisInfo ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - - ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T)); - - SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS; - - Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo); - - if (EFI_ERROR (Status)) { - return Status; - } - - DEBUG ((DEBUG_NET, " GetNdisInfo.Status = %d\n", SimpleNetworkDevice->GetNdisInfo.Status)); - DEBUG ((DEBUG_NET, " GetNdisInfo.IfaceType = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType)); - DEBUG ((DEBUG_NET, " GetNdisInfo.LinkSpeed = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed)); - DEBUG ((DEBUG_NET, " GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags)); - - // - // Check the status code from the 16 bit UNDI ROM - // - if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // The information has been retrieved. Fill in Mode data. - // - return Status; -} - -/** - Call Undi ROM 16bit ISR() to check interrupt cause. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param FrameLength The length of frame buffer. - @param FrameHeaderLength The length of frame buffer's header if has. - @param Frame The frame buffer to process network interrupt. - @param ProtType The type network transmit protocol - @param PktType The type of package. - - @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM's ISR, or status is invalid. - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -Undi16SimpleNetworkIsr ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - IN UINTN *FrameLength, - IN UINTN *FrameHeaderLength, OPTIONAL - IN UINT8 *Frame, OPTIONAL - IN UINT8 *ProtType, OPTIONAL - IN UINT8 *PktType OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - BOOLEAN FrameReceived; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - - FrameReceived = FALSE; - - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - - DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid)); - - if (!SimpleNetworkDevice->IsrValid) { - // - // Call 16 bit UNDI ROM to open the network interface - // - ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T)); - SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS; - SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START; - - DEBUG ((DEBUG_NET, "Isr() START\n")); - - Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // There have been no events on this UNDI interface, so return EFI_NOT_READY - // - if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) { - return EFI_SUCCESS; - } - // - // There is data to process, so call until all events processed. - // - ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T)); - SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS; - SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS; - - DEBUG ((DEBUG_NET, "Isr() PROCESS\n")); - - Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr); - if (EFI_ERROR (Status)) { - return Status; - } - - SimpleNetworkDevice->IsrValid = TRUE; - } - // - // Call UNDI GET_NEXT until DONE - // - while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) { - // - // Check the status code from the 16 bit UNDI ROM - // - if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // UNDI is busy. Caller will have to call again. - // This should never happen with a polled mode driver. - // - if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) { - DEBUG ((DEBUG_NET, " BUSY\n")); - return EFI_SUCCESS; - } - // - // Check for invalud UNDI FuncFlag - // - if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE && - SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT - ) { - DEBUG ((DEBUG_NET, " Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag)); - return EFI_DEVICE_ERROR; - } - // - // Check for Transmit Event - // - if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) { - DEBUG ((DEBUG_NET, " TRANSMIT\n")); - SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; - } - // - // Check for Receive Event - // - else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) { - // - // note - this code will hang on a receive interrupt in a GetStatus loop - // - DEBUG ((DEBUG_NET, " RECEIVE\n")); - SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; - - DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength = %d\n", SimpleNetworkDevice->Isr.BufferLength)); - DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength = %d\n", SimpleNetworkDevice->Isr.FrameLength)); - DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength)); - DEBUG ( - ( - DEBUG_NET, "SimpleNetworkDevice->Isr.Frame = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel, - SimpleNetworkDevice->Isr.FrameOffset - ) - ); - DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength)); - DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength)); - - if (FrameReceived) { - return EFI_SUCCESS; - } - - if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) { - DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL *FrameLength = %08x\n", *FrameLength)); - *FrameLength = SimpleNetworkDevice->Isr.FrameLength; - return EFI_BUFFER_TOO_SMALL; - } - - *FrameLength = SimpleNetworkDevice->Isr.FrameLength; - if (FrameHeaderLength != NULL) { - *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength; - } - - if (ProtType != NULL) { - *ProtType = SimpleNetworkDevice->Isr.ProtType; - } - - if (PktType != NULL) { - *PktType = SimpleNetworkDevice->Isr.PktType; - } - - CopyMem ( - Frame, - (VOID *)(UINTN) ((SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset), - SimpleNetworkDevice->Isr.BufferLength - ); - Frame = Frame + SimpleNetworkDevice->Isr.BufferLength; - if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) { - FrameReceived = TRUE; - } - } - // - // There is data to process, so call until all events processed. - // - ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T)); - SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS; - SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; - - DEBUG ((DEBUG_NET, "Isr() GET NEXT\n")); - - Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - // if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) { - // return EFI_DEVICE_ERROR; - // } - // - } - - SimpleNetworkDevice->IsrValid = FALSE; - return EFI_SUCCESS; -} -// -// /////////////////////////////////////////////////////////////////////////////////////// -// Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs -///////////////////////////////////////////////////////////////////////////////////////// -// -// Start() -// -/** - Call 16 bit UNDI ROM to start the network interface - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_DEVICE_ERROR Network interface has not be initialized. - @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. - @retval EFI_SUCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkStart ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_STARTUP_T Startup; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkStopped: - break; - - case EfiSimpleNetworkStarted: - case EfiSimpleNetworkInitialized: - return EFI_ALREADY_STARTED; - - default: - return EFI_DEVICE_ERROR; - } - // - // Call 16 bit UNDI ROM to start the network interface - // - Startup.Status = INIT_PXE_STATUS; - - Status = PxeUndiStartup (SimpleNetworkDevice, &Startup); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Startup.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // The UNDI interface has been started, so update the State. - // - SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted; - - // - // - // - SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0; - SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = 0; - - return Status; -} -// -// Stop() -// -/** - Call 16 bit UNDI ROM to stop the network interface - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_DEVICE_ERROR Network interface has not be initialized. - @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. - @retval EFI_SUCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkStop ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkStarted: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkInitialized: - default: - return EFI_DEVICE_ERROR; - } - - SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped; - - return Status; -} - -// -// Initialize() -// -/** - Initialize network interface - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param ExtraRxBufferSize The size of extra request receive buffer. - @param ExtraTxBufferSize The size of extra request transmit buffer. - - @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. - @retval EFI_SUCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkInitialize ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN UINTN ExtraRxBufferSize OPTIONAL, - IN UINTN ExtraTxBufferSize OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_INITIALIZE_T Initialize; - PXENV_UNDI_OPEN_T Open; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkStarted: - break; - - case EfiSimpleNetworkInitialized: - default: - return EFI_DEVICE_ERROR; - } - // - // Call 16 bit UNDI ROM to start the network interface - // - Initialize.Status = INIT_PXE_STATUS; - Initialize.ProtocolIni = 0; - - Status = PxeUndiInitialize (SimpleNetworkDevice, &Initialize); - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status)); - DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status)); - - if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) { - Status = EFI_NO_MEDIA; - } - - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Initialize.Status != PXENV_STATUS_SUCCESS) { - DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status)); - return EFI_DEVICE_ERROR; - } - // - // Call 16 bit UNDI ROM to open the network interface - // - Open.Status = INIT_PXE_STATUS; - Open.OpenFlag = 0; - Open.PktFilter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting); - Undi16GetMCastFilters ( - &SimpleNetworkDevice->SimpleNetworkMode, - &Open.McastBuffer, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - Status = PxeUndiOpen (SimpleNetworkDevice, &Open); - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status)); - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Open.Status != PXENV_STATUS_SUCCESS) { - DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status)); - return EFI_DEVICE_ERROR; - } - // - // The UNDI interface has been initialized, so update the State. - // - SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized; - - // - // If initialize succeeds, then assume that media is present. - // - SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE; - - // - // Reset the recycled transmit buffer FIFO - // - SimpleNetworkDevice->TxBufferFifo.First = 0; - SimpleNetworkDevice->TxBufferFifo.Last = 0; - SimpleNetworkDevice->IsrValid = FALSE; - - return Status; -} -// -// Reset() -// -/** - Reset network interface. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param ExtendedVerification Need extended verfication. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkReset ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_RESET_T Reset; - UINT16 Rx_filter; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - - Reset.Status = INIT_PXE_STATUS; - - Rx_filter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting); - - Undi16GetMCastFilters ( - &SimpleNetworkDevice->SimpleNetworkMode, - &Reset.R_Mcast_Buf, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Reset.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // Reset the recycled transmit buffer FIFO - // - SimpleNetworkDevice->TxBufferFifo.First = 0; - SimpleNetworkDevice->TxBufferFifo.Last = 0; - SimpleNetworkDevice->IsrValid = FALSE; - - return Status; -} -// -// Shutdown() -// -/** - Shutdown network interface. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkShutdown ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_CLOSE_T Close; - PXENV_UNDI_SHUTDOWN_T Shutdown; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - - SimpleNetworkDevice->IsrValid = FALSE; - - // - // Call 16 bit UNDI ROM to start the network interface - // - Close.Status = INIT_PXE_STATUS; - - Status = PxeUndiClose (SimpleNetworkDevice, &Close); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Close.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // Call 16 bit UNDI ROM to open the network interface - // - Shutdown.Status = INIT_PXE_STATUS; - - Status = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Shutdown.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // The UNDI interface has been initialized, so update the State. - // - SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted; - - // - // If shutdown succeeds, then assume that media is not present. - // - SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE; - - // - // Reset the recycled transmit buffer FIFO - // - SimpleNetworkDevice->TxBufferFifo.First = 0; - SimpleNetworkDevice->TxBufferFifo.Last = 0; - - // - // A short delay. Without this an initialize immediately following - // a shutdown will cause some versions of UNDI-16 to stop operating. - // - gBS->Stall (250000); - - return Status; -} -// -// ReceiveFilters() -// -/** - Reset network interface. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param Enable Enable mask value - @param Disable Disable mask value - @param ResetMCastFilter Whether reset multi cast filter or not - @param MCastFilterCnt Count of mutli cast filter for different MAC address - @param MCastFilter Buffer for mustli cast filter for different MAC address. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkReceiveFilters ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - IN UINT32 Enable, - IN UINT32 Disable, - IN BOOLEAN ResetMCastFilter, - IN UINTN MCastFilterCnt OPTIONAL, - IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL - ) -{ - EFI_STATUS Status; - UINTN Index; - UINT32 NewFilter; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_CLOSE_T Close; - PXENV_UNDI_OPEN_T Open; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - // - // First deal with possible filter setting changes - // - if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) { - return EFI_SUCCESS; - } - - NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable; - - if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { - if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) { - return EFI_INVALID_PARAMETER; - } - } - // - // Call 16 bit UNDI ROM to close the network interface - // - Close.Status = INIT_PXE_STATUS; - - Status = PxeUndiClose (SimpleNetworkDevice, &Close); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Close.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // Call 16 bit UNDI ROM to open the network interface - // - // - // Reset the recycled transmit buffer FIFO - // - SimpleNetworkDevice->TxBufferFifo.First = 0; - SimpleNetworkDevice->TxBufferFifo.Last = 0; - - // - // Call 16 bit UNDI ROM to open the network interface - // - ZeroMem (&Open, sizeof Open); - - Open.Status = INIT_PXE_STATUS; - Open.PktFilter = Undi16GetPacketFilterSetting (NewFilter); - - if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { - // - // Copy the MAC addresses into the UNDI open parameter structure - // - Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt; - for (Index = 0; Index < MCastFilterCnt; ++Index) { - CopyMem ( - Open.McastBuffer.MCastAddr[Index], - &MCastFilter[Index], - sizeof Open.McastBuffer.MCastAddr[Index] - ); - } - } else if (!ResetMCastFilter) { - for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) { - CopyMem ( - Open.McastBuffer.MCastAddr[Index], - &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index], - sizeof Open.McastBuffer.MCastAddr[Index] - ); - } - } - - Status = PxeUndiOpen (SimpleNetworkDevice, &Open); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (Open.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - SimpleNetworkDevice->IsrValid = FALSE; - SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter; - - if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { - SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt; - for (Index = 0; Index < MCastFilterCnt; ++Index) { - CopyMem ( - &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index], - &MCastFilter[Index], - sizeof (EFI_MAC_ADDRESS) - ); - } - } - // - // Read back multicast addresses. - // - return EFI_SUCCESS; -} -// -// StationAddress() -// -/** - Set new MAC address. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param Reset Whether reset station MAC address to permenent address - @param New A pointer to New address - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkStationAddress ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - IN BOOLEAN Reset, - IN EFI_MAC_ADDRESS * New OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr; - // - // EFI_DEVICE_PATH_PROTOCOL *OldDevicePath; - // - PXENV_UNDI_CLOSE_T Close; - PXENV_UNDI_OPEN_T Open; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - // - // Call 16 bit UNDI ROM to open the network interface - // - SetStationAddr.Status = INIT_PXE_STATUS; - - if (Reset) { - // - // If we are reseting the Station Address to the permanent address, and the - // Station Address is not programmable, then just return EFI_SUCCESS. - // - if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) { - return EFI_SUCCESS; - } - // - // If the address is already the permanent address, then just return success. - // - if (CompareMem ( - &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, - &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ) == 0) { - return EFI_SUCCESS; - } - // - // Copy the adapters permanent address to the new station address - // - CopyMem ( - &SetStationAddr.StationAddress, - &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - } else { - // - // If we are setting the Station Address, and the - // Station Address is not programmable, return invalid parameter. - // - if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) { - return EFI_INVALID_PARAMETER; - } - // - // If the address is already the new address, then just return success. - // - if (CompareMem ( - &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, - New, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ) == 0) { - return EFI_SUCCESS; - } - // - // Copy New to the new station address - // - CopyMem ( - &SetStationAddr.StationAddress, - New, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - } - // - // Call 16 bit UNDI ROM to stop the network interface - // - Close.Status = INIT_PXE_STATUS; - - PxeUndiClose (SimpleNetworkDevice, &Close); - - // - // Call 16-bit UNDI ROM to set the station address - // - SetStationAddr.Status = PXENV_STATUS_SUCCESS; - - Status = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr); - - // - // Call 16-bit UNDI ROM to start the network interface - // - Open.Status = PXENV_STATUS_SUCCESS; - Open.OpenFlag = 0; - Open.PktFilter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting); - Undi16GetMCastFilters ( - &SimpleNetworkDevice->SimpleNetworkMode, - &Open.McastBuffer, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - PxeUndiOpen (SimpleNetworkDevice, &Open); - - // - // Check status from station address change - // - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - CopyMem ( - &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress, - &SetStationAddr.StationAddress, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - -#if 0 /* The device path is based on the permanent address not the current address. */ - // - // The station address was changed, so update the device path with the new MAC address. - // - OldDevicePath = SimpleNetworkDevice->DevicePath; - SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath); - SimpleNetworkAppendMacAddressDevicePath ( - &SimpleNetworkDevice->DevicePath, - &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress - ); - - Status = LibReinstallProtocolInterfaces ( - SimpleNetworkDevice->Handle, - &DevicePathProtocol, - OldDevicePath, - SimpleNetworkDevice->DevicePath, - NULL - ); - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n")); - DEBUG ((DEBUG_ERROR, " Status = %r\n", Status)); - } - - FreePool (OldDevicePath); -#endif /* 0 */ - - return Status; -} -// -// Statistics() -// -/** - Resets or collects the statistics on a network interface. - - @param This Protocol instance pointer. - @param Reset Set to TRUE to reset the statistics for the network interface. - @param StatisticsSize On input the size, in bytes, of StatisticsTable. On - output the size, in bytes, of the resulting table of - statistics. - @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that - contains the statistics. - - @retval EFI_SUCCESS The statistics were collected from the network interface. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer - size needed to hold the statistics is returned in - StatisticsSize. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkStatistics ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - IN BOOLEAN Reset, - IN OUT UINTN *StatisticsSize OPTIONAL, - OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics; - PXENV_UNDI_GET_STATISTICS_T GetStatistics; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - - if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) { - return EFI_INVALID_PARAMETER; - } - - // - // If Reset is TRUE, then clear all the statistics. - // - if (Reset) { - - DEBUG ((DEBUG_NET, " RESET Statistics\n")); - - // - // Call 16 bit UNDI ROM to open the network interface - // - ClearStatistics.Status = INIT_PXE_STATUS; - - Status = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - - DEBUG ((DEBUG_NET, " RESET Statistics Complete")); - } - - if (StatisticsSize != NULL) { - EFI_NETWORK_STATISTICS LocalStatisticsTable; - - DEBUG ((DEBUG_NET, " GET Statistics\n")); - - // - // If the size if valid, then see if the table is valid - // - if (StatisticsTable == NULL) { - DEBUG ((DEBUG_NET, " StatisticsTable is NULL\n")); - return EFI_INVALID_PARAMETER; - } - // - // Call 16 bit UNDI ROM to open the network interface - // - GetStatistics.Status = INIT_PXE_STATUS; - GetStatistics.XmtGoodFrames = 0; - GetStatistics.RcvGoodFrames = 0; - GetStatistics.RcvCRCErrors = 0; - GetStatistics.RcvResourceErrors = 0; - - Status = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (GetStatistics.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // Fill in the Statistics Table with the collected values. - // - SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff); - - LocalStatisticsTable.TxGoodFrames = GetStatistics.XmtGoodFrames; - LocalStatisticsTable.RxGoodFrames = GetStatistics.RcvGoodFrames; - LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors; - LocalStatisticsTable.RxDroppedFrames = GetStatistics.RcvResourceErrors; - - CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize); - - DEBUG ( - (DEBUG_NET, - " Statistics Collected : Size=%d Buf=%08x\n", - *StatisticsSize, - StatisticsTable) - ); - - DEBUG ((DEBUG_NET, " GET Statistics Complete")); - - if (*StatisticsSize < sizeof LocalStatisticsTable) { - DEBUG ((DEBUG_NET, " BUFFER TOO SMALL\n")); - Status = EFI_BUFFER_TOO_SMALL; - } - - *StatisticsSize = sizeof LocalStatisticsTable; - - return Status; - - } - - return EFI_SUCCESS; -} -// -// MCastIpToMac() -// -/** - Translate IP address to MAC address. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param IPv6 IPv6 or IPv4 - @param IP A pointer to given Ip address. - @param MAC On return, translated MAC address. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_INVALID_PARAMETER Invalid IP address. - @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address. - @retval EFI_UNSUPPORTED Do not support IPv6 - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkMCastIpToMac ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN BOOLEAN IPv6, - IN EFI_IP_ADDRESS *IP, - OUT EFI_MAC_ADDRESS *MAC - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr; - - if (This == NULL || IP == NULL || MAC == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - // - // 16 bit UNDI Option ROMS do not support IPv6. Check for IPv6 usage. - // - if (IPv6) { - return EFI_UNSUPPORTED; - } - // - // Call 16 bit UNDI ROM to open the network interface - // - GetMcastAddr.Status = INIT_PXE_STATUS; - CopyMem (&GetMcastAddr.InetAddr, IP, 4); - - Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) { - return EFI_DEVICE_ERROR; - } - // - // Copy the MAC address from the returned data structure. - // - CopyMem ( - MAC, - &GetMcastAddr.MediaAddr, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - return Status; -} -// -// NvData() -// -/** - Performs read and write operations on the NVRAM device attached to a - network interface. - - @param This The protocol instance pointer. - @param ReadWrite TRUE for read operations, FALSE for write operations. - @param Offset Byte offset in the NVRAM device at which to start the read or - write operation. This must be a multiple of NvRamAccessSize and - less than NvRamSize. - @param BufferSize The number of bytes to read or write from the NVRAM device. - This must also be a multiple of NvramAccessSize. - @param Buffer A pointer to the data buffer. - - @retval EFI_SUCCESS The NVRAM access was performed. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkNvData ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN BOOLEAN ReadWrite, - IN UINTN Offset, - IN UINTN BufferSize, - IN OUT VOID *Buffer - ) -{ - return EFI_UNSUPPORTED; -} -// -// GetStatus() -// -/** - Reads the current interrupt status and recycled transmit buffer status from - a network interface. - - @param This The protocol instance pointer. - @param InterruptStatus A pointer to the bit mask of the currently active interrupts - If this is NULL, the interrupt status will not be read from - the device. If this is not NULL, the interrupt status will - be read from the device. When the interrupt status is read, - it will also be cleared. Clearing the transmit interrupt - does not empty the recycled transmit buffer array. - @param TxBuf Recycled transmit buffer address. The network interface will - not transmit if its internal recycled transmit buffer array - is full. Reading the transmit buffer does not clear the - transmit interrupt. If this is NULL, then the transmit buffer - status will not be read. If there are no transmit buffers to - recycle and TxBuf is not NULL, * TxBuf will be set to NULL. - - @retval EFI_SUCCESS The status of the network interface was retrieved. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkGetStatus ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - OUT UINT32 *InterruptStatus OPTIONAL, - OUT VOID **TxBuf OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - UINTN FrameLength; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - - if (InterruptStatus == NULL && TxBuf == NULL) { - return EFI_INVALID_PARAMETER; - } - - FrameLength = 0; - Status = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL); - - if (Status != EFI_BUFFER_TOO_SMALL) { - if (EFI_ERROR (Status)) { - return Status; - } - } - // - // See if the caller wants interrupt info. - // - if (InterruptStatus != NULL) { - *InterruptStatus = SimpleNetworkDevice->InterruptStatus; - SimpleNetworkDevice->InterruptStatus = 0; - } - // - // See if the caller wants transmit buffer status info. - // - if (TxBuf != NULL) { - *TxBuf = 0; - SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf); - } - - return EFI_SUCCESS; -} - -/** - Places a packet in the transmit queue of a network interface. - - @param This The protocol instance pointer. - @param HeaderSize The size, in bytes, of the media header to be filled in by - the Transmit() function. If HeaderSize is non-zero, then it - must be equal to This->Mode->MediaHeaderSize and the DestAddr - and Protocol parameters must not be NULL. - @param BufferSize The size, in bytes, of the entire packet (media header and - data) to be transmitted through the network interface. - @param Buffer A pointer to the packet (media header followed by data) to be - transmitted. This parameter cannot be NULL. If HeaderSize is zero, - then the media header in Buffer must already be filled in by the - caller. If HeaderSize is non-zero, then the media header will be - filled in by the Transmit() function. - @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter - is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then - This->Mode->CurrentAddress is used for the source HW MAC address. - @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this - parameter is ignored. - @param Protocol The type of header to build. If HeaderSize is zero, then this - parameter is ignored. See RFC 1700, section "Ether Types", for - examples. - - @retval EFI_SUCCESS The packet was placed on the transmit queue. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. - @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkTransmit ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN UINTN HeaderSize, - IN UINTN BufferSize, - IN VOID *Buffer, - IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, - IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, - IN UINT16 *Protocol OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - PXENV_UNDI_TRANSMIT_T XmitInfo; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) { - return EFI_BUFFER_TOO_SMALL; - } - - if (HeaderSize != 0) { - if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) { - return EFI_INVALID_PARAMETER; - } - - if (DestAddr == NULL || Protocol == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (DestAddr != NULL) { - CopyMem ( - Buffer, - DestAddr, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - } - - if (SrcAddr == NULL) { - SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress; - } - - CopyMem ( - (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize, - SrcAddr, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - if (Protocol != NULL) { - *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF)); - } - } - // - // See if the recycled transmit buffer FIFO is full. - // If it is full, then we can not transmit until the caller calls GetStatus() to pull - // off recycled transmit buffers. - // - if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) { - return EFI_NOT_READY; - } - // - // Output debug trace message. - // - DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r ")); - - // - // Initialize UNDI WRITE parameter structure. - // - XmitInfo.Status = INIT_PXE_STATUS; - XmitInfo.Protocol = P_UNKNOWN; - XmitInfo.XmitFlag = XMT_DESTADDR; - XmitInfo.DestAddrOffset = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f); - XmitInfo.DestAddrSegment = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4); - XmitInfo.TBDOffset = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f); - XmitInfo.TBDSegment = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4); - XmitInfo.Reserved[0] = 0; - XmitInfo.Reserved[1] = 0; - - CopyMem ( - SimpleNetworkDevice->TxDestAddr, - Buffer, - SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize - ); - - CopyMem ( - SimpleNetworkDevice->TxRealModeMediaHeader, - Buffer, - SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize - ); - - SimpleNetworkDevice->Xmit->ImmedLength = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize; - - SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength); - - CopyMem ( - SimpleNetworkDevice->TxRealModeDataBuffer, - (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize, - SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen - ); - - // - // Make API call to UNDI TRANSMIT - // - XmitInfo.Status = 0; - - Status = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check the status code from the 16 bit UNDI ROM - // - switch (XmitInfo.Status) { - case PXENV_STATUS_OUT_OF_RESOURCES: - return EFI_NOT_READY; - - case PXENV_STATUS_SUCCESS: - break; - - default: - return EFI_DEVICE_ERROR; - } - // - // Add address of Buffer to the recycled transmit buffer FIFO - // - SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer); - - return EFI_SUCCESS; -} - -/** - Receives a packet from a network interface. - - @param This The protocol instance pointer. - @param HeaderSize The size, in bytes, of the media header received on the network - interface. If this parameter is NULL, then the media header size - will not be returned. - @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in - bytes, of the packet that was received on the network interface. - @param Buffer A pointer to the data buffer to receive both the media header and - the data. - @param SrcAddr The source HW MAC address. If this parameter is NULL, the - HW MAC source address will not be extracted from the media - header. - @param DestAddr The destination HW MAC address. If this parameter is NULL, - the HW MAC destination address will not be extracted from the - media header. - @param Protocol The media header type. If this parameter is NULL, then the - protocol will not be extracted from the media header. See - RFC 1700 section "Ether Types" for examples. - - @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has - been updated to the number of bytes received. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_NOT_READY The network interface is too busy to accept this transmit - request. - @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkReceive ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - OUT UINTN *HeaderSize OPTIONAL, - IN OUT UINTN *BufferSize, - OUT VOID *Buffer, - OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, - OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, - OUT UINT16 *Protocol OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - UINTN MediaAddrSize; - UINT8 ProtType; - - if (This == NULL || BufferSize == NULL || Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - - Status = Undi16SimpleNetworkIsr ( - This, - BufferSize, - HeaderSize, - Buffer, - &ProtType, - NULL - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) { - return EFI_NOT_READY; - - } - - SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; - - MediaAddrSize = This->Mode->HwAddressSize; - - if (SrcAddr != NULL) { - CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize); - } - - if (DestAddr != NULL) { - CopyMem (DestAddr, Buffer, MediaAddrSize); - } - - if (Protocol != NULL) { - *((UINT8 *) Protocol) = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1); - *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize)); - } - - DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d HeaderSize = %d\n", *BufferSize, *HeaderSize)); - - return Status; - -} -// -// WaitForPacket() -// -/** - wait for a packet to be received. - - @param Event Event used with WaitForEvent() to wait for a packet to be received. - @param Context Event Context - -**/ -VOID -EFIAPI -Undi16SimpleNetworkWaitForPacket ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // Someone is waiting on the receive packet event, if there's - // a packet pending, signal the event - // - if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) { - gBS->SignalEvent (Event); - } -} -// -// CheckForPacket() -// -/** - Check whether packet is ready for receive. - - @param This The protocol instance pointer. - - @retval EFI_SUCCESS Receive data is ready. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_NOT_READY The network interface is too busy to accept this transmit - request. - @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. -**/ -EFI_STATUS -Undi16SimpleNetworkCheckForPacket ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice; - UINTN FrameLength; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); - - if (SimpleNetworkDevice == NULL) { - return EFI_DEVICE_ERROR; - } - // - // Verify that the current state of the adapter is valid for this call. - // - switch (SimpleNetworkDevice->SimpleNetworkMode.State) { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return EFI_NOT_STARTED; - - case EfiSimpleNetworkStarted: - default: - return EFI_DEVICE_ERROR; - } - - FrameLength = 0; - Status = Undi16SimpleNetworkIsr ( - This, - &FrameLength, - NULL, - NULL, - NULL, - NULL - ); - - if (Status != EFI_BUFFER_TOO_SMALL) { - if (EFI_ERROR (Status)) { - return Status; - } - } - - return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY; -} - -/** - Signal handlers for ExitBootServices event. - - Clean up any Real-mode UNDI residue from the system - - @param Event ExitBootServices event - @param Context -**/ -VOID -EFIAPI -Undi16SimpleNetworkEvent ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // NOTE: This is not the only way to effect this cleanup. The prescribed mechanism - // would be to perform an UNDI STOP command. This strategam has been attempted - // but results in problems making some of the EFI core services from TPL_CALLBACK. - // This issue needs to be resolved, but the other alternative has been to perform - // the unchain logic explicitly, as done below. - // - RestoreCachedVectorAddress (0x1A); -} - -/** - Allocate buffer below 1M for real mode. - - @param NumPages The number pages want to be allocated. - @param Buffer On return, allocated buffer. - - @return Status of allocating pages. -**/ -EFI_STATUS -BiosSnp16AllocatePagesBelowOneMb ( - UINTN NumPages, - VOID **Buffer - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - - PhysicalAddress = 0x000fffff; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiRuntimeServicesData, - NumPages, - &PhysicalAddress - ); - if (EFI_ERROR (Status)) { - return Status; - } - - *Buffer = (VOID *) (UINTN) PhysicalAddress; - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h deleted file mode 100644 index b29059f685..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h +++ /dev/null @@ -1,1655 +0,0 @@ -/** @file - -Copyright (c) 1999 - 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 _BIOS_SNP_16_H_ -#define _BIOS_SNP_16_H_ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "Pxe.h" - -// -// BIOS Simple Network Protocol Device Structure -// -#define EFI_SIMPLE_NETWORK_DEV_SIGNATURE SIGNATURE_32 ('s', 'n', '1', '6') - -#define INIT_PXE_STATUS 0xabcd - -#define EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE 64 - -typedef struct { - UINT32 First; - UINT32 Last; - VOID * Data[EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE]; -} EFI_SIMPLE_NETWORK_DEV_FIFO; - -typedef struct { - UINTN Signature; - EFI_HANDLE Handle; - EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; - EFI_SIMPLE_NETWORK_MODE SimpleNetworkMode; - EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL Nii; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - - // - // Local Data for Simple Network Protocol interface goes here - // - BOOLEAN UndiLoaded; - EFI_EVENT EfiBootEvent; - EFI_EVENT LegacyBootEvent; - UINT16 PxeEntrySegment; - UINT16 PxeEntryOffset; - EFI_SIMPLE_NETWORK_DEV_FIFO TxBufferFifo; - EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath; - PXE_T *Pxe; ///< Pointer to !PXE structure - PXENV_UNDI_GET_INFORMATION_T GetInformation; ///< Data from GET INFORMATION - PXENV_UNDI_GET_NIC_TYPE_T GetNicType; ///< Data from GET NIC TYPE - PXENV_UNDI_GET_NDIS_INFO_T GetNdisInfo; ///< Data from GET NDIS INFO - BOOLEAN IsrValid; ///< TRUE if Isr contains valid data - PXENV_UNDI_ISR_T Isr; ///< Data from ISR - PXENV_UNDI_TBD_T *Xmit; // - VOID *TxRealModeMediaHeader; ///< < 1 MB Size = 0x100 - VOID *TxRealModeDataBuffer; ///< < 1 MB Size = GetInformation.MaxTranUnit - VOID *TxDestAddr; ///< < 1 MB Size = 16 - UINT8 InterruptStatus; ///< returned/cleared by GetStatus, set in ISR - UINTN UndiLoaderTablePages; - UINTN DestinationDataSegmentPages; - UINTN DestinationStackSegmentPages; - UINTN DestinationCodeSegmentPages; - VOID *UndiLoaderTable; - VOID *DestinationDataSegment; - VOID *DestinationStackSegment; - VOID *DestinationCodeSegment; -} EFI_SIMPLE_NETWORK_DEV; - -#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) \ - CR (a, \ - EFI_SIMPLE_NETWORK_DEV, \ - SimpleNetwork, \ - EFI_SIMPLE_NETWORK_DEV_SIGNATURE \ - ) - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding; -extern EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2; - - -// -// Driver Binding Protocol functions -// -/** - Tests to see if this driver supports a given controller. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS The driver supports given controller. - @retval EFI_UNSUPPORT The driver doesn't support given controller. - @retval Other Other errors prevent driver finishing to test - if the driver supports given controller. -**/ -EFI_STATUS -EFIAPI -BiosSnp16DriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -; - -/** - Starts the Snp device controller - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS - The device was started. - @retval EFI_DEVICE_ERROR - The device could not be started due to a device error. - @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. -**/ -EFI_STATUS -EFIAPI -BiosSnp16DriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -; - -/** - Stops the device by given device controller. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The handle of the controller to test. - @param NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param ChildHandleBuffer An array of child handles to be freed. May be NULL if - NumberOfChildren is 0. - - @retval EFI_SUCCESS - The device was stopped. - @retval EFI_DEVICE_ERROR - The device could not be stopped due to a device error. -**/ -EFI_STATUS -EFIAPI -BiosSnp16DriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -; - -// -// Simple Network Protocol functions -// -/** - Call 16 bit UNDI ROM to start the network interface - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_DEVICE_ERROR Network interface has not be initialized. - @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. - @retval EFI_SUCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkStart ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -; - -/** - Call 16 bit UNDI ROM to stop the network interface - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_DEVICE_ERROR Network interface has not be initialized. - @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. - @retval EFI_SUCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkStop ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -; - -/** - Initialize network interface - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param ExtraRxBufferSize The size of extra request receive buffer. - @param ExtraTxBufferSize The size of extra request transmit buffer. - - @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call. - @retval EFI_SUCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkInitialize ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN UINTN ExtraRxBufferSize OPTIONAL, - IN UINTN ExtraTxBufferSize OPTIONAL - ) -; - -/** - Reset network interface. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param ExtendedVerification Need extended verfication. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkReset ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -; - -/** - Shutdown network interface. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkShutdown ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -; - -/** - Reset network interface. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param Enable Enable mask value - @param Disable Disable mask value - @param ResetMCastFilter Whether reset multi cast filter or not - @param MCastFilterCnt Count of mutli cast filter for different MAC address - @param MCastFilter Buffer for mustli cast filter for different MAC address. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkReceiveFilters ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - IN UINT32 Enable, - IN UINT32 Disable, - IN BOOLEAN ResetMCastFilter, - IN UINTN MCastFilterCnt OPTIONAL, - IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL - ) -; - -/** - Set new MAC address. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param Reset Whether reset station MAC address to permenent address - @param New A pointer to New address - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkStationAddress ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - IN BOOLEAN Reset, - IN EFI_MAC_ADDRESS * New OPTIONAL - ) -; - -/** - Collect statistics. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param Reset Whether cleanup old statistics data. - @param StatisticsSize The buffer of statistics table. - @param StatisticsTable A pointer to statistics buffer. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkStatistics ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - IN BOOLEAN Reset, - IN OUT UINTN *StatisticsSize OPTIONAL, - OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL - ) -; - -/** - Translate IP address to MAC address. - - @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure. - @param IPv6 IPv6 or IPv4 - @param IP A pointer to given Ip address. - @param MAC On return, translated MAC address. - - @retval EFI_INVALID_PARAMETER Invalid This paramter. - @retval EFI_INVALID_PARAMETER Invalid IP address. - @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address. - @retval EFI_UNSUPPORTED Do not support IPv6 - @retval EFI_DEVICE_ERROR Network device has not been initialized. - @retval EFI_NOT_STARTED Network device has been stopped. - @retval EFI_DEVICE_ERROR Invalid status for network device - @retval EFI_SUCCESS Success operation. -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkMCastIpToMac ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN BOOLEAN IPv6, - IN EFI_IP_ADDRESS *IP, - OUT EFI_MAC_ADDRESS *MAC - ) -; - -/** - Performs read and write operations on the NVRAM device attached to a - network interface. - - @param This The protocol instance pointer. - @param ReadWrite TRUE for read operations, FALSE for write operations. - @param Offset Byte offset in the NVRAM device at which to start the read or - write operation. This must be a multiple of NvRamAccessSize and - less than NvRamSize. - @param BufferSize The number of bytes to read or write from the NVRAM device. - This must also be a multiple of NvramAccessSize. - @param Buffer A pointer to the data buffer. - - @retval EFI_SUCCESS The NVRAM access was performed. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkNvData ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN BOOLEAN Write, - IN UINTN Offset, - IN UINTN BufferSize, - IN OUT VOID *Buffer - ) -; - -/** - Reads the current interrupt status and recycled transmit buffer status from - a network interface. - - @param This The protocol instance pointer. - @param InterruptStatus A pointer to the bit mask of the currently active interrupts - If this is NULL, the interrupt status will not be read from - the device. If this is not NULL, the interrupt status will - be read from the device. When the interrupt status is read, - it will also be cleared. Clearing the transmit interrupt - does not empty the recycled transmit buffer array. - @param TxBuf Recycled transmit buffer address. The network interface will - not transmit if its internal recycled transmit buffer array - is full. Reading the transmit buffer does not clear the - transmit interrupt. If this is NULL, then the transmit buffer - status will not be read. If there are no transmit buffers to - recycle and TxBuf is not NULL, * TxBuf will be set to NULL. - - @retval EFI_SUCCESS The status of the network interface was retrieved. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkGetStatus ( - IN EFI_SIMPLE_NETWORK_PROTOCOL * This, - OUT UINT32 *InterruptStatus OPTIONAL, - OUT VOID **TxBuf OPTIONAL - ) -; - -/** - Places a packet in the transmit queue of a network interface. - - @param This The protocol instance pointer. - @param HeaderSize The size, in bytes, of the media header to be filled in by - the Transmit() function. If HeaderSize is non-zero, then it - must be equal to This->Mode->MediaHeaderSize and the DestAddr - and Protocol parameters must not be NULL. - @param BufferSize The size, in bytes, of the entire packet (media header and - data) to be transmitted through the network interface. - @param Buffer A pointer to the packet (media header followed by data) to be - transmitted. This parameter cannot be NULL. If HeaderSize is zero, - then the media header in Buffer must already be filled in by the - caller. If HeaderSize is non-zero, then the media header will be - filled in by the Transmit() function. - @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter - is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then - This->Mode->CurrentAddress is used for the source HW MAC address. - @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this - parameter is ignored. - @param Protocol The type of header to build. If HeaderSize is zero, then this - parameter is ignored. See RFC 1700, section "Ether Types", for - examples. - - @retval EFI_SUCCESS The packet was placed on the transmit queue. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. - @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkTransmit ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - IN UINTN HeaderSize, - IN UINTN BufferSize, - IN VOID *Buffer, - IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, - IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, - IN UINT16 *Protocol OPTIONAL - ) -; - -/** - Receives a packet from a network interface. - - @param This The protocol instance pointer. - @param HeaderSize The size, in bytes, of the media header received on the network - interface. If this parameter is NULL, then the media header size - will not be returned. - @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in - bytes, of the packet that was received on the network interface. - @param Buffer A pointer to the data buffer to receive both the media header and - the data. - @param SrcAddr The source HW MAC address. If this parameter is NULL, the - HW MAC source address will not be extracted from the media - header. - @param DestAddr The destination HW MAC address. If this parameter is NULL, - the HW MAC destination address will not be extracted from the - media header. - @param Protocol The media header type. If this parameter is NULL, then the - protocol will not be extracted from the media header. See - RFC 1700 section "Ether Types" for examples. - - @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has - been updated to the number of bytes received. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_NOT_READY The network interface is too busy to accept this transmit - request. - @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. - -**/ -EFI_STATUS -EFIAPI -Undi16SimpleNetworkReceive ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This, - OUT UINTN *HeaderSize OPTIONAL, - IN OUT UINTN *BufferSize, - OUT VOID *Buffer, - OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, - OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, - OUT UINT16 *Protocol OPTIONAL - ) -; - -/** - wait for a packet to be received. - - @param Event Event used with WaitForEvent() to wait for a packet to be received. - @param Context Event Context - -**/ -VOID -EFIAPI -Undi16SimpleNetworkWaitForPacket ( - IN EFI_EVENT Event, - IN VOID *Context - ) -; - -/** - Check whether packet is ready for receive. - - @param This The protocol instance pointer. - - @retval EFI_SUCCESS Receive data is ready. - @retval EFI_NOT_STARTED The network interface has not been started. - @retval EFI_NOT_READY The network interface is too busy to accept this transmit - request. - @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. - @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. - @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. - @retval EFI_UNSUPPORTED This function is not supported by the network interface. -**/ -EFI_STATUS -Undi16SimpleNetworkCheckForPacket ( - IN EFI_SIMPLE_NETWORK_PROTOCOL *This - ) -; - -/** - Cache Interrupt verctor address converted from IVT number. - - @param VectorNumber IVT number - - @retval EFI_SUCCESS Success to operation. -**/ -EFI_STATUS -CacheVectorAddress ( - UINT8 VectorNumber - ) -; - -/** - Get interrupt vector address according to IVT number. - - @param VectorNumber Given IVT number - - @return cached interrupt vector address. -**/ -EFI_STATUS -RestoreCachedVectorAddress ( - UINT8 VectorNumber - ) -; - -/** - If available, launch the BaseCode from a NIC option ROM. - This should install the !PXE and PXENV+ structures in memory for - subsequent use. - - - @param SimpleNetworkDevice Simple network device instance - @param RomAddress The ROM base address for NIC rom. - - @retval EFI_NOT_FOUND The check sum does not match - @retval EFI_NOT_FOUND Rom ID offset is wrong - @retval EFI_NOT_FOUND No Rom ID structure is found -**/ -EFI_STATUS -LaunchBaseCode ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - UINTN RomAddress - ) -; - -/** - PXE - START UNDI - Op-Code: PXENV_START_UNDI (0000h) - Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is - responsible for saving the information it needs to communicate with the hardware. - This service is also responsible for hooking the Int 1Ah service routine - Note: This API service must be called only once during UNDI Option ROM boot. - The UNDI driver is responsible for saving this information and using it every time - PXENV_UNDI_STARTUP is called. - Service cannot be used in protected mode. - typedef struct { - PXENV_STATUS Status; - UINT16 AX; - UINT16 BX; - UINT16 DX; - UINT16 DI; - UINT16 ES; - } PXENV_START_UNDI_T; - Set before calling API service - AX, BX, DX, DI, ES: BIOS initialization parameter registers. These - fields should contain the same information passed to the option ROM - initialization routine by the Host System BIOS. Information about the - contents of these registers can be found in the [PnP], [PCI] and - [BBS] specifications. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeStartUndi ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_START_UNDI_T *PxeUndiTable - ) -; - -/** - PXE - UNDI STARTUP - Op-Code: PXENV_UNDI_STARTUP (0001h) - Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the - caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper - operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used - to complete this initialization. The rest of the UNDI APIs will not be available until this call has - been completed. - Note: PXENV_UNDI_STARTUP must not be called again without first calling - PXENV_UNDI_SHUTDOWN. - PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for - chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and - PXENV_STOP_UNDI API calls. - This service cannot be used in protected mode. - typedef struct - { - PXENV_STATUS Status; - } PXENV_UNDI_STARTUP_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiStartup ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable - ) -; - -/** - PXE - UNDI CLEANUP - Op-Code: PXENV_UNDI_CLEANUP (0002h) - Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field - in the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be - made just before unloading the Universal NIC Driver. The rest of the API will not be available - after this call executes. - This service cannot be used in protected mode. - typedef struct { - PXENX_STATUS Status; - } PXENV_UNDI_CLEANUP_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiCleanup ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable - ) -; - -/** - PXE - UNDI INITIALIZE - Op-Code: PXENV_UNDI_INITIALIZE (0003h) - Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the - caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call resets the adapter and programs it with default parameters. The default parameters used - are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the - receive and transmit units of the network adapter to readily receive or transmit packets. The - application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network. - This call must be made by an application to establish an interface to the network adapter driver. - Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for - the Protocol field in the parameter structure. - typedef struct { - PXENV_STATUS Status; - ADDR32 ProtocolIni; - UINT8 reserved[8]; - } PXENV_UNDI_INITIALIZE_T; - Set before calling API service - ProtocolIni: Physical address of a memory copy of the driver - module from the protocol.ini file obtained from the protocol manager - driver (refer to the NDIS 2.0 specification). This parameter is - supported for the universal NDIS driver to pass the information - contained in the protocol.ini file to the NIC driver for any specific - configuration of the NIC. (Note that the module identification in the - protocol.ini file was done by NDIS.) This value can be NULL for any - other application interfacing to the universal NIC driver - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance. - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiInitialize ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable - ) -; - -/** - Wrapper routine for reset adapter. - - PXE - UNDI RESET ADAPTER - Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h) - Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized - by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to - Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the - network. This routine cannot be used to replace Initialize or Shutdown calls. - typedef struct { - PXENV_STATUS Status; - PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; - } PXENV_UNDI_RESET_T; - - #define MAXNUM_MCADDR 8 - - typedef struct { - UINT16 MCastAddrCount; - MAC_ADDR McastAddr[MAXNUM_MCADDR]; - } PXENV_UNDI_MCAST_ADDRESS_t; - - Set before calling API service - R_Mcast_Buf: This is a structure of MCastAddrCount and - McastAddr. - MCastAddrCount: Number of multicast MAC addresses in the - buffer. - McastAddr: List of up to MAXNUM_MCADDR multicast MAC - addresses. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance. - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - @param RxFilter Filter setting mask value for PXE recive . - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiResetNic ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_RESET_T *PxeUndiTable, - IN UINT16 RxFilter - ) -; - -/** - PXE - UNDI SHUTDOWN - Op-Code: PXENV_UNDI_SHUTDOWN (0005h) - Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call resets the network adapter and leaves it in a safe state for another driver to program it. - Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the - Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again. - typedef struct - { - PXENV_STATUS Status; - } PXENV_UNDI_SHUTDOWN_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiShutdown ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable - ) -; - -/** - PXE - UNDI OPEN - Op-Code: PXENV_UNDI_OPEN (0006h) - Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call activates the adapter network connection and sets the adapter ready to accept packets - for transmit and receive. - typedef struct { - PXENV_STATUS Status; - UINT16 OpenFlag; - UINT16 PktFilter; - #define FLTR_DIRECTED 0x0001 - #define FLTR_BRDCST 0x0002 - #define FLTR_PRMSCS 0x0004 - #define FLTR_SRC_RTG 0x0008 - PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; - } PXENV_UNDI_OPEN_T; - Set before calling API service - OpenFlag: This is an adapter specific input parameter. This is - supported for the universal NDIS 2.0 driver to pass in the open flags - provided by the protocol driver. (See the NDIS 2.0 specification.) - This can be zero. - PktFilter: Filter for receiving packets. This can be one, or more, of - the FLTR_xxx constants. Multiple values are arithmetically or-ed - together. - directed packets are packets that may come to your MAC address - or the multicast MAC address. - R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h). - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiOpen ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable - ) -; - -/** - PXE - UNDI CLOSE - Op-Code: PXENV_UNDI_CLOSE (0007h) - Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or - received until the network adapter is open again. - typedef struct { - PXENV_STATUS Status; - } PXENV_UNDI_CLOSE_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiClose ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable - ) -; - -/** - PXE - UNDI TRANSMIT PACKET - Op-Code: PXENV_UNDI_TRANSMIT (0008h) - Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that - has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. - The status code must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call transmits a buffer to the network. The media header - for the packet can be filled by the calling protocol, but it might not be. - The network adapter driver will fill it if required by the values in the - parameter block. The packet is buffered for transmission provided there is - an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no - buffer is available the function returns PXENV_EXIT_FAILURE with a status - code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is - implementation-dependent. An interrupt is generated on completion of the - transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is - permitted in the context of a transmit complete interrupt. - - typedef struct { - PXENV_STATUS Status; - UINT8 Protocol; - #define P_UNKNOWN 0 - #define P_IP 1 - #define P_ARP 2 - #define P_RARP 3 - UINT8 XmitFlag; - #define XMT_DESTADDR 0x0000 - #define XMT_BROADCAST 0x0001 - SEGOFF16 DestAddr; - SEGOFF16 TBD; - UINT32 Reserved[2]; - } t_PXENV_UNDI_TRANSMIT; - - #define MAX_DATA_BLKS 8 - - typedef struct { - UINT16 ImmedLength; - SEGOFF16 Xmit; - UINT16 DataBlkCount; - struct DataBlk { - UINT8 TDPtrType; - UINT8 TDRsvdByte; - UINT16 TDDataLen; - SEGOFF16 TDDataPtr; - } DataBlock[MAX_DATA_BLKS]; - } PXENV_UNDI_TBD_T - - Set before calling API service - Protocol: This is the protocol of the upper layer that is calling UNDI - TRANSMIT call. If the upper layer has filled the media header, this - field must be P_UNKNOWN. - XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a - pointer to the destination media address in the field DestAddr. If - XMT_BROADCAST, the NIC driver fills the broadcast address for the - destination. - TBD: Segment:Offset address of the transmit buffer descriptor. - ImmedLength: Length of the immediate transmit buffer: Xmit. - Xmit: Segment:Offset of the immediate transmit buffer. - DataBlkCount: Number of blocks in this transmit buffer. - TDPtrType: - 0 => 32-bit physical address in TDDataPtr (not supported in this - version of PXE) - 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit - protected mode pointer - TDRsvdByte: Reserved must be zero. - TDDatalen: Data block length in bytes. - TDDataPtr: Segment:Offset of the transmit block. - DataBlock: Array of transmit data blocks. - Returned from API service - Status: See the PXENV_STATUS_xxx constants - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiTransmit ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable - ) -; - -/** - PXE - UNDI SET MULTICAST ADDRESS - Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h) - Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call changes the current list of multicast addresses to the input list and resets the network - adapter to accept it. If the number of multicast addresses is zero, multicast is disabled. - typedef struct { - PXENV_STATUS Status; - PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; - } PXENV_UNDI_SET_MCAST_ADDR_T; - Set before calling API service - R_Mcast_Buf: See description in the UNDI RESET ADAPTER - (0004h) API. - Returned from API service - Status: See the PXENV_STATUS_xxx constants - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiSetMcastAddr ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable - ) -; - -/** - PXE - UNDI SET STATION ADDRESS - Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah) - Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call sets the MAC address to be the input value and is called before opening the network - adapter. Later, the open call uses this variable as a temporary MAC address to program the - adapter individual address registers. - typedef struct { - PXENV_STATUS Status; - MAC_ADDR StationAddress; - } PXENV_UNDI_SET_STATION_ADDR_T; - Set before calling API service - StationAddress: Temporary MAC address to be used for - transmit and receive. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiSetStationAddr ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable - ) -; - -/** - PXE - UNDI SET PACKET FILTER - Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh) - Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with - the open call. - typedef struct { - PXENV_STATUS Status; - UINT8 filter; - } PXENV_UNDI_SET_PACKET_FILTER_T; - Set before calling API service - Filter: See the receive filter values in the UNDI OPEN - (0006h) API description. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiSetPacketFilter ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable - ) -; - -/** - PXE - UNDI GET INFORMATION - Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch) - Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call copies the network adapter variables, including the MAC address, into the input buffer. - Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and - PXENV_UNDI_STARTUP have been issued. All other fields must be valid after - PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been - called. - typedef struct { - PXENV_STATUS Status; - UINT16 BaseIo; - UINT16 IntNumber; - UINT16 MaxTranUnit; - UINT16 HwType; - #define ETHER_TYPE 1 - #define EXP_ETHER_TYPE 2 - #define IEEE_TYPE 6 - #define ARCNET_TYPE 7 - UINT16 HwAddrLen; - MAC_ADDR CurrentNodeAddress; - MAC_ADDR PermNodeAddress; - SEGSEL ROMAddress; - UINT16 RxBufCt; - UINT16 TxBufCt; - } PXENV_UNDI_GET_INFORMATION_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - BaseIO: Adapter base I/O address. - IntNumber: Adapter IRQ number. - MaxTranUnit: Adapter maximum transmit unit. - HWType: Type of protocol at the hardware level. - HWAddrLen: Length of the hardware address. - CurrentNodeAddress: Current hardware address. - PermNodeAddress: Permanent hardware address. - ROMAddress: Real mode ROM segment address. - RxBufCnt: Receive queue length. - TxBufCnt: Transmit queue length. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetInformation ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable - ) -; - -/** - PXE - UNDI GET STATISTICS - Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh) - Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized - by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call reads statistical information from the network adapter, and returns. - typedef struct { - PXENV_STATUS Status; - UINT32 XmtGoodFrames; - UINT32 RcvGoodFrames; - UINT32 RcvCRCErrors; - UINT32 RcvResourceErrors; - } PXENV_UNDI_GET_STATISTICS_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - XmtGoodFrames: Number of successful transmissions. - RcvGoodFrames: Number of good frames received. - RcvCRCErrors: Number of frames received with CRC - error. - RcvResourceErrors: Number of frames discarded - because receive queue was full. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetStatistics ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable - ) -; - -/** - PXE - UNDI CLEAR STATISTICS - Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh) - Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call clears the statistical information from the network adapter. - typedef struct { - PXENV_STATUS Status; - } PXENV_UNDI_CLEAR_STATISTICS_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiClearStatistics ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable - ) -; - -/** - PXE - UNDI INITIATE DIAGS - Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh) - Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run - hardware diagnostics and to update its status information. - typedef struct { - PXENV_STATUS Status; - } PXENV_UNDI_INITIATE_DIAGS_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiInitiateDiags ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable - ) -; - -/** - PXE - UNDI FORCE INTERRUPT - Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h) - Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the - network adapter driver usually queues the packet and calls the application's callback receive - routine with a pointer to the packet received. Then, the callback routine either can copy the packet - to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied, - the network adapter driver does not remove it from the input queue. When the application wants to - copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive - interrupt. - typedef struct { - PXENV_STATUS Status; - } PXENV_UNDI_FORCE_INTERRUPT_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiForceInterrupt ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable - ) -; - -/** - PXE - UNDI GET MULTICAST ADDRESS - Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h) - Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized - by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call converts the given IP multicast address to a hardware multicast address. - typedef struct { - PXENV_STATUS Status; - IP4 InetAddr; - MAC_ADDR MediaAddr; - } PXENV_UNDI_GET_MCAST_ADDR_T; - Set before calling API service - InetAddr: IP multicast address. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - MediaAddr: MAC multicast address. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetMcastAddr ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable - ) -; - -/** - PXE - UNDI GET NIC TYPE - Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h) - Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE_T parameter structure that has been initialized by - the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the - NIC information. - Description: This call, if successful, provides the NIC-specific information necessary to identify the network - adapter that is used to boot the system. - Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if - the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific - information can be obtained from the DHCPDISCOVER packet itself. - PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called - before the information provided is valid. - typedef { - PXENV_STATUS Status; - UINT8 NicType; - #define PCI_NIC 2 - #define PnP_NIC 3 - #define CardBus_NIC 4 - Union { - Struct { - UINT16 Vendor_ID; - UINT16 Dev_ID; - UINT8 Base_Class; - UINT8 Sub_Class; - UINT8 Prog_Intf; - UINT8 Rev; - UINT16 BusDevFunc; - UINT16 SubVendor_ID; - UINT16 SubDevice_ID; - } pci, cardbus; - struct { - UINT32 EISA_Dev_ID; - UINT8 Base_Class; - UINT8 Sub_Class; - UINT8 Prog_Intf; - UINT16 CardSelNum; - } pnp; - } info; - } PXENV_UNDI_GET_NIC_TYPE_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - NICType: Type of NIC information stored in the parameter - structure. - Info: Information about the fields in this union can be found - in the [PnP] and [PCI] specifications - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetNicType ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable - ) -; - -/** - PXE - UNDI GET IFACE INFO - Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h) - Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized - by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the - interface specific information. - Description: This call, if successful, provides the network interface specific information such as the interface - type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the - universal drivers such as NDIS or Miniport to communicate to the upper protocol modules. - Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the - universal driver to translate/convert this information into a format that is required in its specification - or to suit the expectation of the upper level protocol modules. - PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called - before the information provided is valid. - typedef struct { - PXENV_STATUS Status - UINT8 IfaceType[16]; - UINT32 LinkSpeed; - UINT32 ServiceFlags; - UINT32 Reserved[4]; - } PXENV_UNDI_GET_NDIS_INFO_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - IfaceType: Name of MAC type in ASCIIZ format. This is - used by the universal NDIS driver to specify its driver type - to the protocol driver. - LinkSpeed: Defined in the NDIS 2.0 specification. - ServiceFlags: Defined in the NDIS 2.0 specification. - Reserved: Must be zero. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetNdisInfo ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable - ) -; - -/** - PXE - UNDI ISR - Op-Code: PXENV_UNDI_ISR (0014h) - Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in - the parameter block indicates the operation to be performed for the call. This field is filled with the - status of that operation on return. - Note: Interrupt Service Routine Operation: - In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the - application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR - API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing - (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT). - When the Network Interface HW generates an interrupt the protocol driver interrupt service - routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then - calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for - the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface - level and read any status values required to further process the interrupt. UNDI must return as - quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or - PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the - interrupt was generated by this particular Network Interface or not. - If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was - not generated by our NIC, and interrupt processing is complete. - If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start - a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is - now complete. - The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to - PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and - return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the - first buffer pointer of that frame in the parameter block. - The protocol driver calls UNDI repeatedly with the FuncFlag equal to - PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received - frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l - remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous - buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter - block. Otherwise it must return the first buffer in the next frame. - If there is no received frame pending to be processed, UNDI processes the transmit completes and - if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the - NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag. - IMPORTANT: It is possible for the protocol driver to be interrupted again while in the - strategy routine when the UNDI re-enables interrupts. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiIsr ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_ISR_T *PxeUndiTable - ) -; - -/** - PXE - STOP UNDI - Op-Code: PXENV_STOP_UNDI (0015h) - Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This routine is responsible for unhooking the Int 1Ah service routine. - Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid - status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from - base memory. Also, UNDI must not be removed from base memory if BC is not removed from base - memory. - Service cannot be used in protected mode. - typedef struct { - PXENV_STATUS Status; - } PXENV_STOP_UNDI_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiStop ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_STOP_UNDI_T *PxeUndiTable - ) -; - -/** - PXE - UNDI GET STATE - Op-Code: PXENV_UNDI_GET_STATE (0015h) - Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state - constants - Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call - sequences - typedef struct { - #define PXE_UNDI_GET_STATE_STARTED 1 - #define PXE_UNDI_GET_STATE_INITIALIZED 2 - #define PXE_UNDI_GET_STATE_OPENED 3 - PXENV_STATUS Status; - UINT8 UNDIstate; - } PXENV_UNDI_GET_STATE_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - State: See definitions of the state constants. - Note. UNDI implementation is responsible for maintaining - internal state machine. - UNDI ISR - Op-Code: PXENV_UNDI_ISR (0014h) - Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in - the parameter block indicates the operation to be performed for the call. This field is filled with the - status of that operation on return. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetState ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable - ) -; - -/** - Effect the Far Call into the PXE Layer - - Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API - services will not work, unless there are three 16-bit parameters pushed onto the stack. - push DS ;Far pointer to parameter structure - push offset pxe_data_call_struct ;is pushed onto stack. - push Index ;UINT16 is pushed onto stack. - call dword ptr (s_PXE ptr es:[di]).EntryPointSP - add sp, 6 ;Caller cleans up stack. - - @param SimpleNetworkDevice Device instance for simple network - @param Table Point to parameter/retun value table for legacy far call - @param TableSize The size of paramter/return value table - @param CallIndex The index of legacy call. - - @return EFI_STATUS -**/ -EFI_STATUS -MakePxeCall ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT VOID *Table, - IN UINTN TableSize, - IN UINT16 CallIndex - ) -; - -/** - Allocate buffer below 1M for real mode. - - @param NumPages The number pages want to be allocated. - @param Buffer On return, allocated buffer. - - @return Status of allocating pages. -**/ -EFI_STATUS -BiosSnp16AllocatePagesBelowOneMb ( - UINTN NumPages, - VOID **Buffer - ) -; - -#endif diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni deleted file mode 100644 index 7bfc6abbc4..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni deleted file mode 100644 index 273cbec3a0..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16Extra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c deleted file mode 100644 index 488c597517..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c +++ /dev/null @@ -1,309 +0,0 @@ -/** @file - -Copyright (c) 1999 - 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 "BiosSnp16.h" - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -BiosSnp16ComponentNameGetDriverName ( - 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 -BiosSnp16ComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName = { - BiosSnp16ComponentNameGetDriverName, - BiosSnp16ComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosSnp16ComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosSnp16ComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosSnp16DriverNameTable[] = { - { - "eng;en", - L"BIOS[UNDI] Simple Network Protocol Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -BiosSnp16ComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mBiosSnp16DriverNameTable, - DriverName, - (BOOLEAN)(This == &gBiosSnp16ComponentName) - ); -} - -/** - 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 -BiosSnp16ComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c deleted file mode 100644 index 243048c551..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c +++ /dev/null @@ -1,962 +0,0 @@ -/** @file - Helper Routines that use a PXE-enabled NIC option ROM. - -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 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 "BiosSnp16.h" - -#define TO_SEGMENT(x) ((UINT16) (RShiftU64 ((UINT32)(UINTN) (x), 4) & 0xF000)) -#define TO_OFFSET(x) ((UINT16) ((UINT32)(UINTN) (x) & 0xFFFF)) -#define PARAGRAPH_SIZE 0x10 -#define IVT_BASE 0x00000000 - -#pragma pack(1) -typedef struct { - UINT16 Signature; ///< 0xaa55 - UINT8 ROMlength; ///< size of this ROM in 512 byte blocks - UINT8 InitEntryPoint[4]; ///< a jump to the initialization routine - UINT8 Reserved[0xf]; ///< various - UINT16 PxeRomIdOffset; ///< offset of UNDI, $BC$, or BUSD ROM ID structure - UINT16 PcirHeaderOffset; ///< offset of PCI Expansion Header - UINT16 PnpHeaderOffset; ///< offset of Plug and Play Expansion Header -} OPTION_ROM_HEADER; -#pragma pack() - -UINT32 CachedVectorAddress[0x100]; - -/** - Cache Interrupt verctor address converted from IVT number. - - @param VectorNumber IVT number - - @retval EFI_SUCCESS Success to operation. -**/ -EFI_STATUS -CacheVectorAddress ( - UINT8 VectorNumber - ) -{ - UINT32 *Address; - - Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4); - CachedVectorAddress[VectorNumber] = *Address; - return EFI_SUCCESS; -} - -/** - Get interrupt vector address according to IVT number. - - @param VectorNumber Given IVT number - - @return cached interrupt vector address. -**/ -EFI_STATUS -RestoreCachedVectorAddress ( - UINT8 VectorNumber - ) -{ - UINT32 *Address; - - Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4); - *Address = CachedVectorAddress[VectorNumber]; - return EFI_SUCCESS; -} - -/** - Print Undi loader table. - - @param UndiLoaderStructure Point to Undi Loader table structure. - -**/ -VOID -Print_Undi_Loader_Table ( - VOID *UndiLoaderStructure - ) -{ - UNDI_LOADER_T *DisplayPointer; - - DisplayPointer = (UNDI_LOADER_T *) UndiLoaderStructure; - - DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n")); - DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) UndiLoaderStructure)); - - DEBUG ((DEBUG_NET, "\n\rStatus = 0x%X\n\r", DisplayPointer->Status)); - DEBUG ((DEBUG_NET, "\t_AX_= 0x%X\n\r", DisplayPointer->Ax)); - DEBUG ((DEBUG_NET, "\t_BX_= 0x%X\n\r", DisplayPointer->Bx)); - DEBUG ((DEBUG_NET, "\t_DX_= 0x%X\n\r", DisplayPointer->Dx)); - DEBUG ((DEBUG_NET, "\t_DI_= 0x%X\n\r", DisplayPointer->Di)); - DEBUG ((DEBUG_NET, "\t_ES_= 0x%X\n\r", DisplayPointer->Es)); - DEBUG ((DEBUG_NET, "\tUNDI_DS= 0x%X\n\r", DisplayPointer->Undi_Ds)); - DEBUG ((DEBUG_NET, "\tUNDI_CS= 0x%X\n\r", DisplayPointer->Undi_Cs)); - DEBUG ((DEBUG_NET, "\tPXEptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Segment)); - DEBUG ((DEBUG_NET, "\tPXEptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Offset)); - DEBUG ((DEBUG_NET, "\tPXENVptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Segment)); - DEBUG ((DEBUG_NET, "\tPXENVptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Offset)); -} - -/** - Simple table dumper. The ROMID table is necessary in order to effect - the "Early UNDI" trick. Herein, the UNDI layer can be loaded in the - pre-boot phase without having to download a Network Boot Program - across the wire. It is required in the implementation in that we - are not using PXE. - - @param RomIDStructure Point to RomID structure. - -**/ -VOID -Print_ROMID_Table ( - IN VOID *RomIDStructure - ) -{ - UNDI_ROMID_T *DisplayPointer; - - DisplayPointer = (UNDI_ROMID_T *) RomIDStructure; - - DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n")); - DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) RomIDStructure)); - - DEBUG ( - (DEBUG_NET, - "\n\rROMID %c%c%c%c\n\r", - DisplayPointer->Signature[0], - DisplayPointer->Signature[1], - DisplayPointer->Signature[2], - DisplayPointer->Signature[3]) - ); - - DEBUG ( - (DEBUG_NET, - "Length of this structure in bytes = 0x%X\n\r", - DisplayPointer->StructLength) - ); - DEBUG ( - (DEBUG_NET, - "Use to make byte checksum of this structure == zero is = 0x%X\n\r", - DisplayPointer->StructCksum) - ); - DEBUG ( - (DEBUG_NET, - "Structure format revision number= 0x%X\n\r", - DisplayPointer->StructRev) - ); - DEBUG ( - (DEBUG_NET, - "API Revision number = 0x%X 0x%X 0x%X\n\r", - DisplayPointer->UNDI_Rev[0], - DisplayPointer->UNDI_Rev[1], - DisplayPointer->UNDI_Rev[2]) - ); - DEBUG ( - (DEBUG_NET, - "Offset of UNDI loader routine in the option ROM image= 0x%X\n\r", - DisplayPointer->UNDI_Loader) - ); - DEBUG ((DEBUG_NET, "From the data above, the absolute entry point of the UNDI loader is\n\r")); - DEBUG ( - (DEBUG_NET, - "\tat address 0x%X\n\r", - (UINT32) (DisplayPointer->UNDI_Loader + ((UINT32) (UINTN)(DisplayPointer - 0x20) & 0xFFFF0))) - ); - DEBUG ((DEBUG_NET, "Minimum stack segment size, in bytes,\n\r")); - DEBUG ( - (DEBUG_NET, - "needed to load and run the UNDI= 0x%X \n\r", - DisplayPointer->StackSize) - ); - DEBUG ( - (DEBUG_NET, - "UNDI runtime code and data = 0x%X\n\r", - DisplayPointer->DataSize) - ); - DEBUG ( - (DEBUG_NET, - "Segment size = 0x%X\n\r", - DisplayPointer->CodeSize) - ); - DEBUG ( - (DEBUG_NET, - "\n\rBus Type = %c%c%c%c\n\r", - DisplayPointer->BusType[0], - DisplayPointer->BusType[1], - DisplayPointer->BusType[2], - DisplayPointer->BusType[3]) - ); -} - -/** - Print PXE table. - - @param PxeTable Point to PXE table structure - -**/ -VOID -Print_PXE_Table ( - IN VOID* PxeTable - ) -{ - PXE_T *DisplayPointer; - UINTN Index; - UINT8 *Dptr; - - DisplayPointer = (PXE_T *) PxeTable; - Dptr = (UINT8 *) PxeTable; - - DEBUG ((DEBUG_NET, "This is the PXE table at address 0x%X\n\r", PxeTable)); - - DEBUG ((DEBUG_NET, "A dump of the 0x%X bytes is:\n\r", sizeof (PXE_T))); - - for (Index = 0; Index < sizeof (PXE_T); Index++) { - if ((Index % 0x10) == 0) { - DEBUG ((DEBUG_NET, "\t\n\r")); - } - - DEBUG ((DEBUG_NET, " 0x%X ", *Dptr++)); - } - - DEBUG ((DEBUG_NET, "\n\r")); - DEBUG ( - (DEBUG_NET, - "\n\rPXE %c%c%c%c%c%c\n\r", - DisplayPointer->Signature[0], - DisplayPointer->Signature[1], - DisplayPointer->Signature[2], - DisplayPointer->Signature[3]) - ); - DEBUG ( - (DEBUG_NET, - "Length of this structure in bytes = 0x%X\n\r", - DisplayPointer->StructLength) - ); - DEBUG ( - (DEBUG_NET, - "Use to make byte checksum of this structure == zero is = 0x%X\n\r", - DisplayPointer->StructCksum) - ); - DEBUG ( - (DEBUG_NET, - "Structure format revision number = 0x%X\n\r", - DisplayPointer->StructRev) - ); - DEBUG ( - (DEBUG_NET, - "Must be zero, is equal to 0x%X\n\r", - DisplayPointer->Reserved1) - ); - DEBUG ( - (DEBUG_NET, - "Far pointer to UNDI ROMID = 0x%X\n\r", - (UINT32) (DisplayPointer->Undi.Segment << 0x4 | DisplayPointer->Undi.Offset)) - ); - DEBUG ( - (DEBUG_NET, - "Far pointer to base-code ROMID = 0x%X\n\r", - (UINT32) ((DisplayPointer->Base.Segment << 0x04) | DisplayPointer->Base.Offset)) - ); - DEBUG ((DEBUG_NET, "16bit stack segment API entry point. This will be seg:off in \n\r")); - DEBUG ( - (DEBUG_NET, - "real mode and sel:off in 16:16 protected mode = 0x%X:0x%X\n\r", - DisplayPointer->EntryPointSP.Segment, - DisplayPointer->EntryPointSP.Offset) - ); - - DEBUG ((DEBUG_NET, "\n\tNOTE to the implementer\n\tThis is the entry to use for call-ins\n\r")); - - DEBUG ((DEBUG_NET, "32bit stack Segment API entry point. This will be sel:off. \n\r")); - DEBUG ( - (DEBUG_NET, - "In real mode, sel == 0 = 0x%X:0x%X\n\r", - DisplayPointer->EntryPointESP.Segment, - DisplayPointer->EntryPointESP.Offset) - ); - DEBUG ( - (DEBUG_NET, - "Reserved2 value, must be zero, is equal to 0x%X\n\r", - DisplayPointer->Reserved2) - ); - DEBUG ( - (DEBUG_NET, - "Number of segment descriptors in this structur = 0x%X\n\r", - (UINT8) DisplayPointer->SegDescCnt) - ); - DEBUG ( - (DEBUG_NET, - "First segment descriptor in GDT assigned to PXE = 0x%X\n\r", - (UINT16) DisplayPointer->FirstSelector) - ); - DEBUG ( - (DEBUG_NET, - "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", - (UINT16) DisplayPointer->Stack.Seg_Addr, - (UINT32) DisplayPointer->Stack.Phy_Addr, - (UINT16) DisplayPointer->Stack.Seg_Size) - ); - DEBUG ( - (DEBUG_NET, - "The UNDIData is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", - (UINT16) DisplayPointer->UNDIData.Seg_Addr, - (UINT32) DisplayPointer->UNDIData.Phy_Addr, - (UINT16) DisplayPointer->UNDIData.Seg_Size) - ); - DEBUG ( - (DEBUG_NET, - "The UNDICodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", - (UINT16) DisplayPointer->UNDICode.Seg_Addr, - (UINT32) DisplayPointer->UNDICode.Phy_Addr, - (UINT16) DisplayPointer->UNDICode.Seg_Size) - ); - DEBUG ( - (DEBUG_NET, - "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", - (UINT16) DisplayPointer->UNDICodeWrite.Seg_Addr, - (UINT32) DisplayPointer->UNDICodeWrite.Phy_Addr, - (UINT16) DisplayPointer->UNDICodeWrite.Seg_Size) - ); - DEBUG ( - (DEBUG_NET, - "The BC_Data is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", - (UINT16) DisplayPointer->BC_Data.Seg_Addr, - (UINT32) DisplayPointer->BC_Data.Phy_Addr, - (UINT16) DisplayPointer->BC_Data.Seg_Size) - ); - DEBUG ( - (DEBUG_NET, - "The BC_Code is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", - (UINT16) DisplayPointer->BC_Code.Seg_Addr, - (UINT32) DisplayPointer->BC_Code.Phy_Addr, - (UINT16) DisplayPointer->BC_Code.Seg_Size) - ); - DEBUG ( - (DEBUG_NET, - "The BC_CodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r", - (UINT16) DisplayPointer->BC_CodeWrite.Seg_Addr, - (UINT32) DisplayPointer->BC_CodeWrite.Phy_Addr, - (UINT16) DisplayPointer->BC_CodeWrite.Seg_Size) - ); -} - -/** - Print PXENV table. - - @param PxenvTable Point to PXENV - -**/ -VOID -Print_PXENV_Table ( - IN VOID *PxenvTable - ) -{ - PXENV_T *DisplayPointer; - - DisplayPointer = (PXENV_T *) PxenvTable; - - DEBUG ( - (DEBUG_NET, - "\n\rPXENV+ %c%c%c%c%c%c\n\r", - DisplayPointer->Signature[0], - DisplayPointer->Signature[1], - DisplayPointer->Signature[2], - DisplayPointer->Signature[3], - DisplayPointer->Signature[4], - DisplayPointer->Signature[5]) - ); - - DEBUG ( - (DEBUG_NET, - "PXE version number. \n\r\tLSB is minor version. \n\r\tMSB is major version = 0x%X\n\r", - DisplayPointer->Version) - ); - DEBUG ( - (DEBUG_NET, - "Length of PXE-2.0 Entry Point structure in bytes = 0x%X\n\r", - DisplayPointer->StructLength) - ); - DEBUG ((DEBUG_NET, "Used to make structure checksum equal zero is now = 0x%X\n\r", DisplayPointer->StructCksum)); - DEBUG ((DEBUG_NET, "Real mode API entry point segment:Offset. = 0x%X\n\r", DisplayPointer->RMEntry)); - DEBUG ((DEBUG_NET, "Protected mode API entry point = 0x%X\n\r", DisplayPointer->PMEntryOff)); - DEBUG ((DEBUG_NET, " segment:Offset. This will always be zero. \n\r")); - DEBUG ((DEBUG_NET, "Protected mode API calls = 0x%X\n\r", DisplayPointer->PMEntrySeg)); - DEBUG ((DEBUG_NET, "Real mode stack segment = 0x%X\n\r", DisplayPointer->StackSeg)); - DEBUG ((DEBUG_NET, "Stack segment size in bytes = 0x%X\n\r", DisplayPointer->StackSize)); - DEBUG ((DEBUG_NET, "Real mode base-code code segment = 0x%X\n\r", DisplayPointer->BaseCodeSeg)); - DEBUG ((DEBUG_NET, "Base-code code segment size = 0x%X\n\r", DisplayPointer->BaseCodeSize)); - DEBUG ((DEBUG_NET, "Real mode base-code data segment = 0x%X\n\r", DisplayPointer->BaseDataSeg)); - DEBUG ((DEBUG_NET, "Base-code data segment size = 0x%X\n\r", DisplayPointer->BaseDataSize)); - - DEBUG ( - (DEBUG_NET, - "UNDI code segment size in bytes = 0x%X\n\r", - DisplayPointer->UNDICodeSize) - ); - DEBUG ( - (DEBUG_NET, - "Real mode segment:Offset pointer \n\r\tto PXE Runtime ID structure, address = 0x%X\n\r", - DisplayPointer->RuntimePtr) - ); - DEBUG ( - ( - DEBUG_NET, - "From above, we have a linear address of 0x%X\n\r", - (UINT32) - ( - ((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF) + - (((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF0000) >> 12) - ) - ) - ); -} - - -#define OPTION_ROM_PTR ((OPTION_ROM_HEADER *) RomAddress) - -/** - If available, launch the BaseCode from a NIC option ROM. - This should install the !PXE and PXENV+ structures in memory for - subsequent use. - - - @param SimpleNetworkDevice Simple network device instance - @param RomAddress The ROM base address for NIC rom. - - @retval EFI_NOT_FOUND The check sum does not match - @retval EFI_NOT_FOUND Rom ID offset is wrong - @retval EFI_NOT_FOUND No Rom ID structure is found -**/ -EFI_STATUS -LaunchBaseCode ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - UINTN RomAddress - ) -{ - EFI_STATUS Status; - EFI_IA32_REGISTER_SET InOutRegs; - UNDI_ROMID_T *RomIdTableAddress; - UNDI_LOADER_T *UndiLoaderTable; - UINT16 Segment; - UINT16 *StackPointer; - VOID *Buffer; - UINTN Size; - PXE_T *Pxe; - UINT32 RomLength; - UINTN PciSegment; - UINTN Bus; - UINTN Device; - UINTN Function; - BOOLEAN ThunkFailed; - - DEBUG ((DEBUG_NET, "\n\r\n\rCheck for the UNDI ROMID Signature\n\r")); - - // - // paranoia - check structures for validity - // - RomLength = OPTION_ROM_PTR->ROMlength << 9; - if (CalculateSum8 ((UINT8 *) RomAddress, RomLength) != 0) { - DEBUG ((DEBUG_ERROR, "ROM Header Checksum Error\n\r")); - return EFI_NOT_FOUND; - } - - RomIdTableAddress = (UNDI_ROMID_T *) (RomAddress + OPTION_ROM_PTR->PxeRomIdOffset); - - if ((UINTN) (OPTION_ROM_PTR->PxeRomIdOffset + RomIdTableAddress->StructLength) > RomLength) { - DEBUG ((DEBUG_ERROR, "ROM ID Offset Error\n\r")); - return EFI_NOT_FOUND; - } - // - // see if this is a header for an UNDI ROM ID structure (vs. a $BC$ or BUSD type) - // - if (CompareMem (RomIdTableAddress->Signature, UNDI_ROMID_SIG, sizeof RomIdTableAddress->Signature) != 0) { - DEBUG ((DEBUG_ERROR, "No ROM ID Structure found....\n\r")); - return EFI_NOT_FOUND; - // - // its not - keep looking - // - } - - if (CalculateSum8 ((UINT8 *) RomIdTableAddress, RomIdTableAddress->StructLength) != 0) { - DEBUG ((DEBUG_ERROR, "ROM ID Checksum Error\n\r")); - return EFI_NOT_FOUND; - } - - Print_ROMID_Table (RomIdTableAddress); - - DEBUG ( - (DEBUG_NET, - "The ROM ID is located at 0x%X\n\r", - RomIdTableAddress) - ); - - DEBUG ( - (DEBUG_NET, - "With an UNDI Loader located at 0x%X\n\r", - RomAddress + RomIdTableAddress->UNDI_Loader) - ); - - // - // found an UNDI ROM ID structure - // - SimpleNetworkDevice->Nii.ImageAddr = RomAddress; - SimpleNetworkDevice->Nii.ImageSize = RomLength; - SimpleNetworkDevice->Nii.MajorVer = RomIdTableAddress->UNDI_Rev[2]; - SimpleNetworkDevice->Nii.MinorVer = RomIdTableAddress->UNDI_Rev[1]; - - DEBUG ((DEBUG_NET, "Allocate area for the UNDI_LOADER_T structure\n\r")); - // - // Allocate 1 page below 1MB to put real mode thunk code in - // - // Undi Loader Table is a PXE Specification prescribed data structure - // that is used to transfer information into and out of the Undi layer. - // Note how it must be located below 1 MB. - // - SimpleNetworkDevice->UndiLoaderTablePages = EFI_SIZE_TO_PAGES (PARAGRAPH_SIZE + sizeof (UNDI_LOADER_T)); - Status = BiosSnp16AllocatePagesBelowOneMb ( - SimpleNetworkDevice->UndiLoaderTablePages, - &SimpleNetworkDevice->UndiLoaderTable - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); - return EFI_OUT_OF_RESOURCES; - } - - UndiLoaderTable = SimpleNetworkDevice->UndiLoaderTable; - - DEBUG ((DEBUG_NET, "Allocate area for the real-mode stack whose sole purpose\n\r")); - DEBUG ((DEBUG_NET, "in life right now is to store a SEG:OFFSET combo pair that\n\r")); - DEBUG ((DEBUG_NET, "points to an Undi_Loader_t table structure\n\r")); - - Size = 0x100; - Status = gBS->AllocatePool (EfiLoaderData, Size, &Buffer); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Now we want to put a pointer to the Under Loader Table in our MemPage - // Buffer. This will be the argument stack for the call into the Undi Loader - // - StackPointer = (UINT16 *) Buffer; - *StackPointer++ = TO_OFFSET (UndiLoaderTable); - // - // push the OFFSET - // - *StackPointer++ = TO_SEGMENT (UndiLoaderTable); - // - // push the SEGMENT - // - StackPointer = (UINT16 *) Buffer; - // - // reset the stack pointer - // - DEBUG ( - (DEBUG_NET, - "After the fixups, the stack pointer is 0x%X\n\r", - (UINT64)(UINTN) StackPointer) - ); - - // - // Allocate memory for the Deployed UNDI. - // The UNDI is essentially telling us how much space it needs, and - // it is up to the EFI driver to allocate sufficient, boot-time - // persistent resources for the call - // - SimpleNetworkDevice->DestinationDataSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->DataSize); - Status = BiosSnp16AllocatePagesBelowOneMb ( - SimpleNetworkDevice->DestinationDataSegmentPages, - &SimpleNetworkDevice->DestinationDataSegment - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); - return Status; - } - - UndiLoaderTable->Undi_Ds = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationDataSegment >> 4); - - // - // Allocate memory for the Deployed UNDI stack - // The UNDI is essentially telling us how much space it needs, and - // it is up to the EFI driver to allocate sufficient, boot-time - // persistent resources for the call - // - SimpleNetworkDevice->DestinationStackSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->StackSize); - Status = BiosSnp16AllocatePagesBelowOneMb ( - SimpleNetworkDevice->DestinationStackSegmentPages, - &SimpleNetworkDevice->DestinationStackSegment - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); - return Status; - } - // - // Allocate memory for the Deployed UNDI. - // The UNDI is essentially telling us how much space it needs, and - // it is up to the EFI driver to allocate sufficient, boot-time - // persistent resources for the call - // - SimpleNetworkDevice->DestinationCodeSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->CodeSize); - Status = BiosSnp16AllocatePagesBelowOneMb ( - SimpleNetworkDevice->DestinationCodeSegmentPages, - &SimpleNetworkDevice->DestinationCodeSegment - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); - return Status; - } - - UndiLoaderTable->Undi_Cs = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationCodeSegment >> 4); - - // - // these are in the Input and Output Parameter to be sent to the UNDI Loader code - // - UndiLoaderTable->Status = 0xAA55; - // - // -------------------- Changed by Michael_Huang@3Com.com ----------------- - // UndiLoaderTable->_AX is AX value when UNDI ROM is initialized by BIOS, it is the PCI bus device - // function of the NIC. Please refer to PXE Spec for detail info. - // old code is: - // UndiLoaderTable->Ax = 0x0; - // ----------------------------------------------------------------------- - // - SimpleNetworkDevice->PciIo->GetLocation ( - SimpleNetworkDevice->PciIo, - &PciSegment, - &Bus, - &Device, - &Function - ); - UndiLoaderTable->Ax = (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function)); - UndiLoaderTable->Bx = 0x0; - UndiLoaderTable->Dx = 0x0; - UndiLoaderTable->Di = 0x0; - UndiLoaderTable->Es = 0x0; - - // - // set these OUT values to zero in order to ensure that - // uninitialized memory is not mistaken for display data - // - UndiLoaderTable->PXEptr.Offset = 0; - UndiLoaderTable->PXEptr.Segment = 0; - UndiLoaderTable->PXENVptr.Segment = 0; - UndiLoaderTable->PXENVptr.Offset = 0; - - DEBUG ( - (DEBUG_INIT, - "The NIC is located at Bus 0x%X, Device 0x%X, Function 0x%X\n\r", - Bus, - Device, - Function) - ); - - // - // These are the values that set up the ACTUAL IA32 machine state, whether in - // Real16 in EFI32 or the IVE for IA64 - // register values are unused except for CS:IP and SS:SP - // - InOutRegs.X.AX = 0; - InOutRegs.X.BX = 0; - InOutRegs.X.CX = 0; - InOutRegs.X.DX = 0; - InOutRegs.X.SI = 0; - InOutRegs.X.DI = 0; - InOutRegs.X.BP = 0; - InOutRegs.X.DS = 0; - InOutRegs.X.ES = 0; - // - // just to be clean - // - DEBUG ((DEBUG_NET, "The way this game works is that the SS:SP +4 should point\n\r")); - DEBUG ((DEBUG_NET, "to the contents of the UndiLoaderTable\n\r")); - DEBUG ( - (DEBUG_NET, - "The Undi Loader Table is at address = 0x%X\n\r", - (UINT32)(UINTN) UndiLoaderTable) - ); - DEBUG ( - (DEBUG_NET, - "The segment and offsets are 0x%X and 0x%X, resp\n", - TO_SEGMENT (UndiLoaderTable), - TO_OFFSET (UndiLoaderTable)) - ); - - DEBUG ( - (DEBUG_NET, - "The Linear Address of the UNDI Loader entry is 0x%X\n", - RomAddress + RomIdTableAddress->UNDI_Loader) - ); - - DEBUG ( - (DEBUG_NET, - "The Address offset of the UNDI Loader entry is 0x%X\n", - RomIdTableAddress->UNDI_Loader) - ); - - DEBUG ((DEBUG_NET, "Before the call, we have...\n\r")); - Print_Undi_Loader_Table (UndiLoaderTable); - - Segment = ((UINT16) (RShiftU64 (RomAddress, 4) & 0xFFFF)); - DEBUG ((DEBUG_NET, "The Segment of the call is 0x%X\n\r", Segment)); - - // - // make the call into the UNDI Code - // - DEBUG ((DEBUG_INIT, "Make the call into the UNDI code now\n\r")); - - DEBUG ((DEBUG_NET, "\nThe 20-BIt address of the Call, and the location \n\r")); - DEBUG ((DEBUG_NET, "\twhere we should be able to set a breakpoint is \n\r")); - DEBUG ( - (DEBUG_NET, - "\t\t0x%X, from SEG:OFF 0x%X:0x%X\n\r\n\r", - Segment * 0x10 + RomIdTableAddress->UNDI_Loader, - Segment, - RomIdTableAddress->UNDI_Loader) - ); - - ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 ( - SimpleNetworkDevice->LegacyBios, - Segment, // Input segment - (UINT16) RomIdTableAddress->UNDI_Loader, // Offset - &InOutRegs, // Ptr to Regs - Buffer, // Reference to Stack - Size // Size of the Stack - ); - if (ThunkFailed) { - return EFI_ABORTED; - } - - DEBUG ( - (DEBUG_NET, - "The return code UndiLoaderTable->Status is = 0x%X\n\r", - UndiLoaderTable->Status) - ); - DEBUG ( - (DEBUG_NET, - "This error code should match eax, which is = 0x%X\n\r", - InOutRegs.X.AX) - ); - - if ((UndiLoaderTable->Status != 0) || (InOutRegs.X.AX != PXENV_EXIT_SUCCESS)) { - DEBUG ((DEBUG_NET, "LaunchBaseCode exits with error, RomAddress = 0x%X\n\r", RomAddress)); - return EFI_ABORTED; - } - - DEBUG ((DEBUG_NET, "Now returned from the UNDI code\n\r")); - - DEBUG ((DEBUG_NET, "After the call, we have...\n\r")); - Print_Undi_Loader_Table (UndiLoaderTable); - - DEBUG ((DEBUG_NET, "Display the PXENV+ and !PXE tables exported by NIC\n\r")); - Print_PXENV_Table ((VOID *)(UINTN)((UndiLoaderTable->PXENVptr.Segment << 4) | UndiLoaderTable->PXENVptr.Offset)); - Print_PXE_Table ((VOID *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset)); - - Pxe = (PXE_T *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset); - SimpleNetworkDevice->Nii.Id = (UINT64)(UINTN) Pxe; - - gBS->FreePool (Buffer); - - // - // paranoia - make sure a valid !PXE structure - // - if (CompareMem (Pxe->Signature, PXE_SIG, sizeof Pxe->Signature) != 0) { - DEBUG ((DEBUG_ERROR, "!PXE Structure not found....\n\r")); - return EFI_NOT_FOUND; - // - // its not - keep looking - // - } - - if (CalculateSum8 ((UINT8 *) Pxe, Pxe->StructLength) != 0) { - DEBUG ((DEBUG_ERROR, "!PXE Checksum Error\n\r")); - return EFI_NOT_FOUND; - } - - if (Pxe->StructLength < (UINT8 *) &Pxe->FirstSelector - (UINT8 *) Pxe->Signature) { - DEBUG ((DEBUG_ERROR, "!PXE Length Error\n\r")); - return EFI_NOT_FOUND; - } - - if ((((UINTN) Pxe->Undi.Segment) << 4) + Pxe->Undi.Offset != (UINTN) RomIdTableAddress) { - DEBUG ((DEBUG_ERROR, "!PXE RomId Address Error\n\r")); - return EFI_NOT_FOUND; - } - // - // This is the magic to bind the global PXE interface - // This dirtiness is for non-protocol shrouded access - // - SimpleNetworkDevice->PxeEntrySegment = Pxe->EntryPointSP.Segment; - - if (SimpleNetworkDevice->PxeEntrySegment == 0) { - DEBUG ((DEBUG_ERROR, "!PXE EntryPointSP segment Error\n\r")); - return EFI_NOT_FOUND; - } - - SimpleNetworkDevice->PxeEntryOffset = Pxe->EntryPointSP.Offset; - - DEBUG ( - ( - DEBUG_NET, "The entry point is 0x%X:0x%X\n\r", SimpleNetworkDevice->PxeEntrySegment, SimpleNetworkDevice-> - PxeEntryOffset - ) - ); - - return EFI_SUCCESS; -} - -/** - Effect the Far Call into the PXE Layer - - Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API - services will not work, unless there are three 16-bit parameters pushed onto the stack. - push DS ;Far pointer to parameter structure - push offset pxe_data_call_struct ;is pushed onto stack. - push Index ;UINT16 is pushed onto stack. - call dword ptr (s_PXE ptr es:[di]).EntryPointSP - add sp, 6 ;Caller cleans up stack. - - @param SimpleNetworkDevice Device instance for simple network - @param Table Point to parameter/retun value table for legacy far call - @param TableSize The size of paramter/return value table - @param CallIndex The index of legacy call. - - @return EFI_STATUS -**/ -EFI_STATUS -MakePxeCall ( - EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT VOID *Table, - IN UINTN TableSize, - IN UINT16 CallIndex - ) -{ - EFI_STATUS Status; - EFI_IA32_REGISTER_SET InOutRegs; - UINT16 *BPtr; - VOID *Buffer; - UINTN Size; - VOID *MemPageAddress; - UINTN Index; - BOOLEAN ThunkFailed; - - DEBUG ((DEBUG_NET, "MakePxeCall(CallIndex = %02x, Table = %X, TableSize = %d)\n", CallIndex, Table, TableSize)); - - if (SimpleNetworkDevice->PxeEntrySegment == 0 && SimpleNetworkDevice->PxeEntryOffset == 0) { - return EFI_DEVICE_ERROR; - } - - Status = EFI_SUCCESS; - - // - // Allocate a transient data structure for the argument table - // This table needs to have the input XXX_t structure copied into here. - // The PXE UNDI can only grab this table when it's below one-MB, and - // this implementation will not try to push this table on the stack - // (although this is a possible optimization path since EFI always allocates - // 4K as a minimum page size...............) - // - Status = BiosSnp16AllocatePagesBelowOneMb ( - TableSize / EFI_PAGE_SIZE + 1, - &MemPageAddress - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status)); - return Status; - } - // - // Copy the > 1MB pool table to a sub-1MB buffer - // - CopyMem (MemPageAddress, Table, TableSize); - - // - // Allocate space for IA-32 register context - // - ZeroMem (&InOutRegs, sizeof (InOutRegs)); - InOutRegs.X.ES = SimpleNetworkDevice->PxeEntrySegment; - InOutRegs.X.DI = SimpleNetworkDevice->PxeEntryOffset; - - // - // The game here is to build the stack which will subsequently - // get copied down below 1 MB by the FarCall primitive. - // This is now our working stack - // - Size = 6; - Status = gBS->AllocatePool ( - EfiRuntimeServicesData, - Size, - &Buffer - ); - if (EFI_ERROR (Status)) { - return Status; - } - - BPtr = (UINT16 *) Buffer; - *BPtr++ = CallIndex; - // - // SP + 2 - // - *BPtr++ = TO_OFFSET (MemPageAddress); - *BPtr++ = TO_SEGMENT (MemPageAddress); - - DEBUG ((DEBUG_NET, "State before FarCall86\n")); - DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer)); - BPtr = (UINT16 *) Buffer; - DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2))); - DEBUG ((DEBUG_NET, " MemPage = ")); - for (Index = 0; Index < TableSize; Index++) { - DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index))); - } - - DEBUG ((DEBUG_NET, "\n")); - - ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 ( - SimpleNetworkDevice->LegacyBios, - SimpleNetworkDevice->PxeEntrySegment, // Input segment - SimpleNetworkDevice->PxeEntryOffset, - &InOutRegs, // Ptr to Regs - Buffer, // Reference to Stack - 6 // Size of the Stack - ); - if (ThunkFailed) { - return EFI_ABORTED; - } - - DEBUG ((DEBUG_NET, "State after FarCall86\n")); - DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer)); - BPtr = (UINT16 *) Buffer; - DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2))); - DEBUG ((DEBUG_NET, " MemPage = ")); - for (Index = 0; Index < TableSize; Index++) { - DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index))); - } - - DEBUG ((DEBUG_NET, "\n")); - - // - // Copy the sub 1MB table to > 1MB table - // - CopyMem (Table, MemPageAddress, TableSize); - - // - // For PXE UNDI call, AX contains the return status. - // Convert the PXE UNDI Status to EFI_STATUS type - // - if (InOutRegs.X.AX == PXENV_EXIT_SUCCESS) { - Status = EFI_SUCCESS; - } else { - Status = EFI_DEVICE_ERROR; - } - // - // Clean up house - // - gBS->FreePool (Buffer); - gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) MemPageAddress, TableSize / EFI_PAGE_SIZE + 1); - - return Status; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h deleted file mode 100644 index 54503a840f..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h +++ /dev/null @@ -1,613 +0,0 @@ -/** @file - These are PXE Specification 2.1-compliant data structures and defines. - - This file relies upon the existence of a PXE-compliant ROM - in memory, as defined by the Preboot Execution Environment - Specification (PXE), Version 2.1, located at - - http://developer.intel.com/ial/wfm/wfmspecs.htm - -Copyright (c) 1999 - 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 _PXEDEF_H_ -#define _PXEDEF_H_ - -#pragma pack(1) - -// -// PXE structure signatures -// -#define BC_ROMID_SIG "$BC$" -#define UNDI_ROMID_SIG "UNDI" -#define BUSD_ROMID_SIG "BUSD" - -#define PXE_SIG "!PXE" -#define PXENV_SIG "PXENV+" - -#define BC_ROMID_REV 0x00 -#define UNDI_ROMID_REV 0x00 -#define BUSD_ROMID_REV 0x00 - -#define PXE_REV 0x00 -#define PXENV_REV 0x0201 - -#define PXENV_PTR SIGNATURE_32 ('P', 'X', 'E', 'N') -#define PXE_PTR SIGNATURE_32 ('!', 'P', 'X', 'E') -#define UNDI_ROMID_SIG_PTR SIGNATURE_32 ('U', 'N', 'D', 'I') - -typedef UINT16 SEGSEL; // Real mode segment or protected mode selector. -typedef UINT16 OFF16; // Unsigned 16bit offset. -typedef UINT32 ADDR32; - -// -// Bus types -// -#define PXENV_BUS_ISA 0 -#define PXENV_BUS_EISA 1 -#define PXENV_BUS_MCA 2 -#define PXENV_BUS_PCI 3 -#define PXENV_BUS_VESA 4 -#define PXENV_BUS_PCMCIA 5 - -// -// -// Result codes returned in AX by a PXENV API service. -// -#define PXENV_EXIT_SUCCESS 0x0000 -#define PXENV_EXIT_FAILURE 0x0001 - -// -// Status codes returned in the status word of PXENV API parameter structures. -// -// Generic API errors - these do not match up with the M0x or E0x messages -// that are reported by the loader. -// -#define PXENV_STATUS_SUCCESS 0x00 -#define PXENV_STATUS_FAILURE 0x01 -#define PXENV_STATUS_BAD_FUNC 0x02 -#define PXENV_STATUS_UNSUPPORTED 0x03 -#define PXENV_STATUS_KEEP_UNDI 0x04 -#define PXENV_STATUS_KEEP_ALL 0x05 -#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 - -typedef enum { - PxeEnvStatus_Success, - PxeEnvStatus_Failure, - PxeEnvStatus_BadFunc, - PxeEnvStatus_Unsupported, - PxeEnvStatus_KeepUndi, - PxeEnvStatus_KeepAll -} EFI_PXE_STATUS; - -/* Driver errors (0x60 to 0x6F) */ - -// These errors are for UNDI compatible NIC drivers. -#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 -#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 -#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 -#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 -#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 -#define PXENV_STATUS_UNDI_BAD_MAC_ADDR 0x67 -#define PXENV_STATUS_UNDI_BAD_EEPROM_CKSUM 0x68 -#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 -#define PXENV_STATUS_UNDI_INVALID_STATE 0x6A -#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B -#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C - -typedef struct { - UINT16 Seg_Addr; - UINT32 Phy_Addr; - UINT16 Seg_Size; -} NEWSEGDESC_T; - -typedef struct { - OFF16 Offset; - SEGSEL Segment; -} SEGOFF16; - -typedef struct { - UINT8 Signature[4]; ///< Structure signature is not NULL terminated. - UINT8 StructLength; ///< Length of this structure in bytes. - UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero. - UINT8 StructRev; ///< Structure format revision number. - UINT8 UNDI_Rev[3]; ///< API revision number stored in Intel order. - // - // Revision 2.1.0 == 0x00, 0x01, 0x02 - // - UINT16 UNDI_Loader; ///< Offset of UNDI loader routine in the option ROM image. - UINT16 StackSize; ///< Minimum stack segment size, in bytes, needed to load and run the UNDI. - UINT16 DataSize; ///< UNDI runtime code and data - UINT16 CodeSize; ///< segment sizes. - UINT8 BusType[4]; ///< 'ISAR', 'EISA', 'PCIR', 'PCCR' -} UNDI_ROMID_T; - -typedef struct { - UINT8 Signature[4]; ///< Structure signature is not NULL terminated. - UINT8 StructLength; ///< Length of this structure in bytes. - UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero. - UINT8 StructRev; ///< Structure format revision number. - UINT8 BC_Rev[3]; ///< API revision number stored in Intel order. - // - // Revision 2.1.0 == 0x00, 0x01, 0x02 - // - UINT16 BC_Loader; ///< Offset of base-code loader routine in the option ROM image. - UINT16 StackSize; ///< Minimum stack segment size (bytes) needed to load/run base-code. - UINT16 DataSize; ///< Base-code runtime code and data - UINT16 CodeSize; ///< segment sizes. -} BC_ROMID_T; - -typedef struct { - UINT8 Signature[4]; ///< Structure signature is not NULL terminated. - UINT8 StructLength; ///< Length of this structure in bytes. - UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero. - UINT8 StructRev; ///< Structure format revision number. - UINT8 Reserved1; ///< must be zero - /// - /// UNDI_ROMID_T __FAR *UNDI;// Far pointer to UNDI ROMID - /// - SEGOFF16 Undi; - - /// - /// BC_ROMID_T __FAR *Base; // Far pointer to base-code ROMID - /// - SEGOFF16 Base; - - /// - /// UINT16 (__FAR __CDECL *EntryPointSP)(UINT16 func, VOID __FAR *param); - /// 16bit stack segment API entry point. This will be seg:off in - /// real mode and sel:off in 16:16 protected mode. - /// - SEGOFF16 EntryPointSP; - - /// - /// UINT16 (__FAR __CDECL *EntryPointESP)(UINT16 func, VOID __FAR *param); - /// 32bit stack segment API entry point. This will be sel:off. - /// In real mode, sel == 0 - /// - SEGOFF16 EntryPointESP; - /// - /// UINT16 (__FAR __CDECL *StatusCallout)(UINT16 param); - /// Address of DHCP/TFTP status callout routine. - /// - SEGOFF16 StatusCallout; - UINT8 Reserved2; ///< must be zero - UINT8 SegDescCnt; ///< Number of segment descriptors in this structure. - UINT16 FirstSelector; ///< First segment descriptor in GDT assigned to PXE. - NEWSEGDESC_T Stack; - NEWSEGDESC_T UNDIData; - NEWSEGDESC_T UNDICode; - NEWSEGDESC_T UNDICodeWrite; - NEWSEGDESC_T BC_Data; - NEWSEGDESC_T BC_Code; - NEWSEGDESC_T BC_CodeWrite; -} PXE_T; - -typedef struct { - CHAR8 Signature[6]; ///< "PXENV+" - UINT16 Version; ///< PXE version number. LSB is minor version. MSB is major version. - UINT8 StructLength; ///< Length of PXE-2.0 Entry Point structure in bytes. - UINT8 StructCksum; ///< Used to make structure checksum equal zero. - UINT32 RMEntry; ///< Real mode API entry point segment:offset. - UINT32 PMEntryOff; ///< Protected mode API entry point - UINT16 PMEntrySeg; ///< segment:offset. This will always be zero. Protected mode API calls - ///< must be made through the API entry points in the PXE Runtime ID structure. - - UINT16 StackSeg; ///< Real mode stack segment. - UINT16 StackSize; ///< Stack segment size in bytes. - UINT16 BaseCodeSeg; ///< Real mode base-code code segment. - UINT16 BaseCodeSize; ///< Base-code code segment size - UINT16 BaseDataSeg; ///< Real mode base-code data segment. - UINT16 BaseDataSize; ///< Base-code data segment size - UINT16 UNDIDataSeg; ///< Real mode UNDI data segment. - UINT16 UNDIDataSize; ///< UNDI data segment size in bytes. - UINT16 UNDICodeSeg; ///< Real mode UNDI code segment. - UINT16 UNDICodeSize; ///< UNDI code segment size in bytes. - PXE_T *RuntimePtr; ///< Real mode segment:offset pointer to PXE Runtime ID structure. -} PXENV_T; - -typedef struct { - OUT UINT16 Status; - IN OUT UINT16 Ax; - IN OUT UINT16 Bx; - IN OUT UINT16 Dx; - IN OUT UINT16 Di; - IN OUT UINT16 Es; - IN OUT UINT16 Undi_Ds; - IN OUT UINT16 Undi_Cs; - OUT SEGOFF16 PXEptr; - OUT SEGOFF16 PXENVptr; -} UNDI_LOADER_T; - -// -// Put in some UNDI-specific arguments -// -#define PXENV_START_UNDI 0x0000 -#define PXENV_UNDI_STARTUP 0x0001 -#define PXENV_UNDI_CLEANUP 0x0002 -#define PXENV_UNDI_INITIALIZE 0x0003 -#define PXENV_UNDI_RESET_NIC 0x0004 -#define PXENV_UNDI_SHUTDOWN 0x0005 -#define PXENV_UNDI_OPEN 0x0006 -#define PXENV_UNDI_CLOSE 0x0007 -#define PXENV_UNDI_TRANSMIT 0x0008 -#define PXENV_UNDI_SET_MCAST_ADDR 0x0009 -#define PXENV_UNDI_SET_STATION_ADDR 0x000A -#define PXENV_UNDI_SET_PACKET_FILTER 0x000B -#define PXENV_UNDI_GET_INFORMATION 0x000C -#define PXENV_UNDI_GET_STATISTICS 0x000D -#define PXENV_UNDI_CLEAR_STATISTICS 0x000E -#define PXENV_UNDI_INITIATE_DIAGS 0x000F -#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 -#define PXENV_UNDI_GET_MCAST_ADDR 0x0011 -#define PXENV_UNDI_GET_NIC_TYPE 0x0012 -#define PXENV_UNDI_GET_NDIS_INFO 0x0013 -#define PXENV_UNDI_ISR 0x0014 -#define PXENV_STOP_UNDI 0x0015 -#define PXENV_UNDI_GET_STATE 0x0016 - -#define ADDR_LEN 16 -#define MAXNUM_MCADDR 8 -#define IPLEN 4 ///< length of an IP address -#define XMT_DESTADDR 0x0000 ///< destination address given -#define XMT_BROADCAST 0x0001 ///< use broadcast address - -typedef struct { - UINT16 MCastAddrCount; ///< In: Number of multi-cast - - /* addresses. */ - UINT8 MCastAddr[MAXNUM_MCADDR][ADDR_LEN]; /* In: */ - - /* list of multi-cast addresses. */ - - /* Each address can take up to */ - - /* ADDR_LEN bytes and a maximum */ - - /* of MAXNUM_MCADDR address can */ - - /* be provided*/ -} PXENV_UNDI_MCAST_ADDR_T; - -/* Definitions of TFTP API parameter structures. - */ -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - IN UINT16 Ax; ///< In: These register fields must be - IN UINT16 Bx; ///< filled in with the same data - IN UINT16 Dx; ///< that was passed to the MLID - IN UINT16 Di; ///< option ROM boot code by the - IN UINT16 Es; ///< system BIOS. -} PXENV_START_UNDI_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx -} PXENV_UNDI_STARTUP_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx -} PXENV_UNDI_CLEANUP_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - - /// - /// This is an input parameter and is a 32-bit physical address of - /// a memory copy of the driver module in the protocol.ini file - /// obtained from the Protocol Manager driver(refer to NDIS 2.0 - /// specifications). This parameter is basically supported for - /// the universal NDIS driver to pass the information contained in - /// protocol.ini file to the NIC driver for any specific - /// configuration of the NIC. (Note that the module - /// identification in the protocol.ini file was done by NDIS - /// itself.) This value can be NULL for for any other application - /// interfacing to the Universal NIC Driver. - /// - IN UINT32 ProtocolIni; - UINT8 Reserved[8]; -} PXENV_UNDI_INITIALIZE_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - IN PXENV_UNDI_MCAST_ADDR_T R_Mcast_Buf; ///< multicast address list - /* see note below */ -} PXENV_UNDI_RESET_T; - -/*++ - Note: The NIC driver does not remember the multicast - addresses provided in any call. So the application must - provide the multicast address list with all the calls that - reset the receive unit of the adapter. - --*/ -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx -} PXENV_UNDI_SHUTDOWN_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - - /// - /// This is an input parameter and is adapter specific. This is - /// supported for Universal NDIS 2.0 driver to pass down the Open - /// flags provided by the protocol driver (See NDIS 2.0 - /// specifications). This can be zero. - /// - IN UINT16 OpenFlag; ///< In: See description below - IN UINT16 PktFilter; ///< In: Filter for receiving - - /* packet. It takes the following */ - - /* values, multiple values can be */ - - /* ORed together. */ -#define FLTR_DIRECTED 0x0001 ///< directed/multicast -#define FLTR_BRDCST 0x0002 ///< broadcast packets -#define FLTR_PRMSCS 0x0004 ///< any packet on LAN -#define FLTR_SRC_RTG 0x0008 ///< source routing packet - IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; /* In: */ - /* See t_PXENV_UNDI_MCAST_ADDR. */ -} PXENV_UNDI_OPEN_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx -} PXENV_UNDI_CLOSE_T; - -#define MAX_DATA_BLKS 8 - -typedef struct { - IN UINT16 ImmedLength; ///< In: Data buffer length in - - /* bytes. */ - UINT16 XmitOffset; ///< 16-bit segment & offset of the - UINT16 XmitSegment; ///< immediate data buffer. - UINT16 DataBlkCount; ///< In: Number of data blocks. - struct DataBlk { - UINT8 TDPtrType; ///< 0 => 32 bit Phys pointer in TDDataPtr, not supported in this version of LSA - ///< 1 => seg:offser in TDDataPtr which can be a real mode or 16-bit protected mode pointer - UINT8 TDRsvdByte; ///< Reserved, must be zero. - UINT16 TDDataLen; ///< Data block length in bytes. - UINT16 TDDataPtrOffset; ///< Far pointer to data buffer. - UINT16 TDDataPtrSegment; ///< Far pointer to data buffer. - } DataBlock[MAX_DATA_BLKS]; -} -PXENV_UNDI_TBD_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - - /// - /// This is the protocol of the upper layer that is calling - /// NICTransmit call. If the upper layer has filled the media - /// header this field must be 0. - /// - IN UINT8 Protocol; -#define P_UNKNOWN 0 -#define P_IP 1 -#define P_ARP 2 -#define P_RARP 3 - - /// - /// If this flag is 0, the NIC driver expects a pointer to the - /// destination media address in the field DestMediaAddr. If 1, - /// the NIC driver fills the broadcast address for the - /// destination. - /// - IN UINT8 XmitFlag; -#define XMT_DESTADDR 0x0000 ///< destination address given -#define XMT_BROADCAST 0x0001 ///< use broadcast address - - /// - /// This is a pointer to the hardware address of the destination - /// media. It can be null if the destination is not known in - /// which case the XmitFlag contains 1 for broadcast. Destination - /// media address must be obtained by the upper level protocol - /// (with Address Resolution Protocol) and NIC driver does not do - /// any address resolution. - /// - IN UINT16 DestAddrOffset; ///< 16-bit segment & offset of the - IN UINT16 DestAddrSegment; ///< destination media address - - - IN UINT16 TBDOffset; ///< 16-bit segment & offset of the - IN UINT16 TBDSegment; ///< transmit buffer descriptor of type - - /// XmitBufferDesc - IN UINT32 Reserved[2]; -} PXENV_UNDI_TRANSMIT_T; - - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; ///< In: -} PXENV_UNDI_SET_MCAST_ADDR_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - IN UINT8 StationAddress[ADDR_LEN]; ///< new address to be set -} PXENV_UNDI_SET_STATION_ADDR_T; - -typedef struct s_PXENV_UNDI_SET_PACKET_FILTER { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - IN UINT8 Filter; ///< In: Receive filter value. -} PXENV_UNDI_SET_PACKET_FILTER_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - OUT UINT16 BaseIo; ///< Out: Adapter's Base IO - OUT UINT16 IntNumber; ///< Out: IRQ number - OUT UINT16 MaxTranUnit; ///< Out: MTU - OUT UINT16 HwType; ///< Out: type of protocol at hardware level - -#define ETHER_TYPE 1 -#define EXP_ETHER_TYPE 2 -#define IEEE_TYPE 6 -#define ARCNET_TYPE 7 - /*++ - other numbers can be obtained from rfc1010 for "Assigned - Numbers". This number may not be validated by the application - and hence adding new numbers to the list should be fine at any - time. - --*/ - OUT UINT16 HwAddrLen; ///< Out: actual length of hardware address - OUT UINT8 CurrentNodeAddress[ADDR_LEN]; ///< Out: Current hardware address - OUT UINT8 PermNodeAddress[ADDR_LEN]; ///< Out: Permanent hardware address - OUT UINT16 ROMAddress; ///< Out: ROM address - OUT UINT16 RxBufCt; ///< Out: receive Queue length - OUT UINT16 TxBufCt; ///< Out: Transmit Queue length -} PXENV_UNDI_GET_INFORMATION_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - OUT UINT32 XmtGoodFrames; ///< Out: No. of good transmissions - OUT UINT32 RcvGoodFrames; ///< Out: No. of good frames received - OUT UINT32 RcvCRCErrors; ///< Out: No. of frames with CRC error - OUT UINT32 RcvResourceErrors; ///< Out: no. of frames discarded - /* Out: receive Queue full */ -} PXENV_UNDI_GET_STATISTICS_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx -} PXENV_UNDI_CLEAR_STATISTICS_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx -} PXENV_UNDI_INITIATE_DIAGS_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx -} PXENV_UNDI_FORCE_INTERRUPT_T; - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - IN UINT32 InetAddr; ///< In: IP Multicast Address - OUT UINT8 MediaAddr[ADDR_LEN]; ///< Out: corresponding hardware - /* multicast address */ -} PXENV_UNDI_GET_MCAST_ADDR_T; - -typedef struct { - OUT UINT16 Vendor_ID; ///< OUT: - OUT UINT16 Dev_ID; ///< OUT: - OUT UINT8 Base_Class; ///< OUT: - OUT UINT8 Sub_Class; ///< OUT: - OUT UINT8 Prog_Intf; ///< OUT: program interface - OUT UINT8 Rev; ///< OUT: Revision number - OUT UINT16 BusDevFunc; ///< OUT: Bus, Device & Function numbers - OUT UINT16 SubVendor_ID; ///< OUT: - OUT UINT16 SubDevice_ID; ///< OUT: -} PCI_INFO_T; - -typedef struct { - OUT UINT32 EISA_Dev_ID; ///< Out: - OUT UINT8 Base_Class; ///< OUT: - OUT UINT8 Sub_Class; ///< OUT: - OUT UINT8 Prog_Intf; ///< OUT: program interface - OUT UINT16 CardSelNum; ///< OUT: Card Selector Number - OUT UINT8 Reserved; ///< to make it 10 bytes -} PNP_INFO_T; - - -typedef union { - PCI_INFO_T Pci; - PNP_INFO_T Pnp; -} PCI_PNP_INFO_T; - -typedef struct { - OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx - OUT UINT8 NicType; ///< OUT: 2=PCI, 3=PnP - PCI_PNP_INFO_T PciPnpInfo; -} PXENV_UNDI_GET_NIC_TYPE_T; - -typedef struct { - OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx - OUT UINT8 IfaceType[16]; ///< OUT: Type name of MAC, AsciiZ - - /* format. This is used by the */ - - /* Universal NDIS Driver to fill */ - - /* the driver type in it's MAC */ - - /* Service specific */ - - /* characteristic table */ - OUT UINT32 LinkSpeed; ///< OUT: - OUT UINT32 ServiceFlags; ///< OUT: as defined in NDIS Spec 2.0X - OUT UINT32 Reserved[4]; ///< OUT: will be filled with 0s till defined -} PXENV_UNDI_GET_NDIS_INFO_T; - -typedef struct { - OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx - IN OUT UINT16 FuncFlag; ///< In: PXENV_UNDI_ISR_IN_xxx - - /* Out: PXENV_UNDI_ISR_OUT_xxx */ - OUT UINT16 BufferLength; - OUT UINT16 FrameLength; - OUT UINT16 FrameHeaderLength; - OUT UINT16 FrameOffset; - OUT UINT16 FrameSegSel; - OUT UINT8 ProtType; - OUT UINT8 PktType; -} PXENV_UNDI_ISR_T; - -#define PXENV_UNDI_ISR_IN_START 1 /* This function must be first */ - -/* when an interrupt is received. */ - -/* It will tell us if the intr */ - -/* was generated by our device. */ -#define PXENV_UNDI_ISR_IN_PROCESS 2 /* Call to start processing one of */ - -/* our interrupts. */ -#define PXENV_UNDI_ISR_IN_GET_NEXT 3 /* Call to start/continue receiving */ - -/* data from receive buffer(s). */ - -/*++ - - Possible responses from PXENV_UNDI_ISR_IN_START - - --*/ -#define PXENV_UNDI_ISR_OUT_OURS 0 ///< This is our interrupt. Deal with it. -#define PXENV_UNDI_ISR_OUT_NOT_OURS 1 ///< This is not our interrupt. - -/*++ - - Possible responses from PXENV_UNDI_ISR_IN_PROCESS and - PXENV_UNDI_ISR_IN_PROCESS - ---*/ -#define PXENV_UNDI_ISR_OUT_DONE 0 ///< We are done processing this interrupt. -#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 ///< We completed a transmit interrupt. -#define PXENV_UNDI_ISR_OUT_RECEIVE 3 ///< Get data from receive buffer. - -#define PXENV_UNDI_ISR_OUT_BUSY 4 /* ? */ - -typedef struct { - UINT16 Status; ///< Out: PXENV_STATUS_xxx -} PXENV_STOP_UNDI_T; - -#define PXENV_UNDI_STARTED 1 ///< not even initialized -#define PXENV_UNDI_INITIALIZED 2 ///< initialized and closed (not opened) -#define PXENV_UNDI_OPENED 3 ///< initialized & opened - -typedef struct { - OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx - UINT16 UNDI_State; -} PXENV_UNDI_GET_STATE_T; - -#pragma pack() - -#endif diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c deleted file mode 100644 index d35fc3f430..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c +++ /dev/null @@ -1,1254 +0,0 @@ -/** @file - Wrapper routines that use a PXE-enabled NIC option ROM to - supply internal routines for an EFI SNI (Simple Network - Interface) Protocol. - - This file relies upon the existence of a PXE-compliant ROM - in memory, as defined by the Preboot Execution Environment - Specification (PXE), Version 2.1, located at - - http://developer.intel.com/ial/wfm/wfmspecs.htm - -Copyright (c) 1999 - 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 "BiosSnp16.h" - -/** - PXE - START UNDI - Op-Code: PXENV_START_UNDI (0000h) - Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is - responsible for saving the information it needs to communicate with the hardware. - This service is also responsible for hooking the Int 1Ah service routine - Note: This API service must be called only once during UNDI Option ROM boot. - The UNDI driver is responsible for saving this information and using it every time - PXENV_UNDI_STARTUP is called. - Service cannot be used in protected mode. - typedef struct { - PXENV_STATUS Status; - UINT16 AX; - UINT16 BX; - UINT16 DX; - UINT16 DI; - UINT16 ES; - } PXENV_START_UNDI_T; - Set before calling API service - AX, BX, DX, DI, ES: BIOS initialization parameter registers. These - fields should contain the same information passed to the option ROM - initialization routine by the Host System BIOS. Information about the - contents of these registers can be found in the [PnP], [PCI] and - [BBS] specifications. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeStartUndi ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_START_UNDI_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_START_UNDI_T), - PXENV_START_UNDI - ); -} - -/** - PXE - UNDI STARTUP - Op-Code: PXENV_UNDI_STARTUP (0001h) - Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the - caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper - operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used - to complete this initialization. The rest of the UNDI APIs will not be available until this call has - been completed. - Note: PXENV_UNDI_STARTUP must not be called again without first calling - PXENV_UNDI_SHUTDOWN. - PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for - chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and - PXENV_STOP_UNDI API calls. - This service cannot be used in protected mode. - typedef struct - { - PXENV_STATUS Status; - } PXENV_UNDI_STARTUP_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiStartup ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_STARTUP_T), - PXENV_UNDI_STARTUP - ); -} - -/** - PXE - UNDI CLEANUP - Op-Code: PXENV_UNDI_CLEANUP (0002h) - Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field - in the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be - made just before unloading the Universal NIC Driver. The rest of the API will not be available - after this call executes. - This service cannot be used in protected mode. - typedef struct { - PXENX_STATUS Status; - } PXENV_UNDI_CLEANUP_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiCleanup ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_CLEANUP_T), - PXENV_UNDI_CLEANUP - ); -} - -/** - PXE - UNDI INITIALIZE - Op-Code: PXENV_UNDI_INITIALIZE (0003h) - Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the - caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call resets the adapter and programs it with default parameters. The default parameters used - are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the - receive and transmit units of the network adapter to readily receive or transmit packets. The - application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network. - This call must be made by an application to establish an interface to the network adapter driver. - Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for - the Protocol field in the parameter structure. - typedef struct { - PXENV_STATUS Status; - ADDR32 ProtocolIni; - UINT8 reserved[8]; - } PXENV_UNDI_INITIALIZE_T; - Set before calling API service - ProtocolIni: Physical address of a memory copy of the driver - module from the protocol.ini file obtained from the protocol manager - driver (refer to the NDIS 2.0 specification). This parameter is - supported for the universal NDIS driver to pass the information - contained in the protocol.ini file to the NIC driver for any specific - configuration of the NIC. (Note that the module identification in the - protocol.ini file was done by NDIS.) This value can be NULL for any - other application interfacing to the universal NIC driver - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiInitialize ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_INITIALIZE_T), - PXENV_UNDI_INITIALIZE - ); -} - -/** - Wrapper routine for reset adapter. - - PXE - UNDI RESET ADAPTER - Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h) - Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized - by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to - Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the - network. This routine cannot be used to replace Initialize or Shutdown calls. - typedef struct { - PXENV_STATUS Status; - PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; - } PXENV_UNDI_RESET_T; - - #define MAXNUM_MCADDR 8 - - typedef struct { - UINT16 MCastAddrCount; - MAC_ADDR McastAddr[MAXNUM_MCADDR]; - } PXENV_UNDI_MCAST_ADDRESS_t; - - Set before calling API service - R_Mcast_Buf: This is a structure of MCastAddrCount and - McastAddr. - MCastAddrCount: Number of multicast MAC addresses in the - buffer. - McastAddr: List of up to MAXNUM_MCADDR multicast MAC - addresses. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance. - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - @param RxFilter Filter setting mask value for PXE recive . - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiResetNic ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_RESET_T *PxeUndiTable, - IN UINT16 RxFilter - ) -{ - PXENV_UNDI_OPEN_T Open; - PXENV_UNDI_CLOSE_T Close; - UINTN Status; - - Status = MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_RESET_T), - PXENV_UNDI_RESET_NIC - ); - if (!EFI_ERROR(Status)) { - return Status; - } - - Close.Status = PXENV_STATUS_SUCCESS; - - Status = MakePxeCall ( - SimpleNetworkDevice, - &Close, - sizeof (Close), - PXENV_UNDI_CLOSE - ); - if (EFI_ERROR(Status)) { - return EFI_DEVICE_ERROR; - } - - Status = MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_RESET_T), - PXENV_UNDI_RESET_NIC - ); - if (EFI_ERROR(Status)) { - return EFI_DEVICE_ERROR; - } - - Open.Status = PXENV_STATUS_SUCCESS; - Open.OpenFlag = 0; - Open.PktFilter = RxFilter; - CopyMem ( - &Open.McastBuffer, - &PxeUndiTable->R_Mcast_Buf, - sizeof (PXENV_UNDI_MCAST_ADDR_T) - ); - - - Status = MakePxeCall ( - SimpleNetworkDevice, - &Open, - sizeof (Open), - PXENV_UNDI_OPEN - ); - if (EFI_ERROR(Status)) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - PXE - UNDI SHUTDOWN - Op-Code: PXENV_UNDI_SHUTDOWN (0005h) - Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call resets the network adapter and leaves it in a safe state for another driver to program it. - Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the - Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again. - typedef struct - { - PXENV_STATUS Status; - } PXENV_UNDI_SHUTDOWN_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiShutdown ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_SHUTDOWN_T), - PXENV_UNDI_SHUTDOWN - ); -} - -/** - PXE - UNDI OPEN - Op-Code: PXENV_UNDI_OPEN (0006h) - Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call activates the adapter network connection and sets the adapter ready to accept packets - for transmit and receive. - typedef struct { - PXENV_STATUS Status; - UINT16 OpenFlag; - UINT16 PktFilter; - #define FLTR_DIRECTED 0x0001 - #define FLTR_BRDCST 0x0002 - #define FLTR_PRMSCS 0x0004 - #define FLTR_SRC_RTG 0x0008 - PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; - } PXENV_UNDI_OPEN_T; - Set before calling API service - OpenFlag: This is an adapter specific input parameter. This is - supported for the universal NDIS 2.0 driver to pass in the open flags - provided by the protocol driver. (See the NDIS 2.0 specification.) - This can be zero. - PktFilter: Filter for receiving packets. This can be one, or more, of - the FLTR_xxx constants. Multiple values are arithmetically or-ed - together. - directed packets are packets that may come to your MAC address - or the multicast MAC address. - R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h). - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiOpen ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_OPEN_T), - PXENV_UNDI_OPEN - ); -} - -/** - PXE - UNDI CLOSE - Op-Code: PXENV_UNDI_CLOSE (0007h) - Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or - received until the network adapter is open again. - typedef struct { - PXENV_STATUS Status; - } PXENV_UNDI_CLOSE_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiClose ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_CLOSE_T), - PXENV_UNDI_CLOSE - ); -} - -/** - PXE - UNDI TRANSMIT PACKET - Op-Code: PXENV_UNDI_TRANSMIT (0008h) - Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that - has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. - The status code must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call transmits a buffer to the network. The media header - for the packet can be filled by the calling protocol, but it might not be. - The network adapter driver will fill it if required by the values in the - parameter block. The packet is buffered for transmission provided there is - an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no - buffer is available the function returns PXENV_EXIT_FAILURE with a status - code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is - implementation-dependent. An interrupt is generated on completion of the - transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is - permitted in the context of a transmit complete interrupt. - - typedef struct { - PXENV_STATUS Status; - UINT8 Protocol; - #define P_UNKNOWN 0 - #define P_IP 1 - #define P_ARP 2 - #define P_RARP 3 - UINT8 XmitFlag; - #define XMT_DESTADDR 0x0000 - #define XMT_BROADCAST 0x0001 - SEGOFF16 DestAddr; - SEGOFF16 TBD; - UINT32 Reserved[2]; - } t_PXENV_UNDI_TRANSMIT; - - #define MAX_DATA_BLKS 8 - - typedef struct { - UINT16 ImmedLength; - SEGOFF16 Xmit; - UINT16 DataBlkCount; - struct DataBlk { - UINT8 TDPtrType; - UINT8 TDRsvdByte; - UINT16 TDDataLen; - SEGOFF16 TDDataPtr; - } DataBlock[MAX_DATA_BLKS]; - } PXENV_UNDI_TBD_T - - Set before calling API service - Protocol: This is the protocol of the upper layer that is calling UNDI - TRANSMIT call. If the upper layer has filled the media header, this - field must be P_UNKNOWN. - XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a - pointer to the destination media address in the field DestAddr. If - XMT_BROADCAST, the NIC driver fills the broadcast address for the - destination. - TBD: Segment:Offset address of the transmit buffer descriptor. - ImmedLength: Length of the immediate transmit buffer: Xmit. - Xmit: Segment:Offset of the immediate transmit buffer. - DataBlkCount: Number of blocks in this transmit buffer. - TDPtrType: - 0 => 32-bit physical address in TDDataPtr (not supported in this - version of PXE) - 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit - protected mode pointer - TDRsvdByte: Reserved must be zero. - TDDatalen: Data block length in bytes. - TDDataPtr: Segment:Offset of the transmit block. - DataBlock: Array of transmit data blocks. - Returned from API service - Status: See the PXENV_STATUS_xxx constants - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiTransmit ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable - ) -{ - EFI_STATUS Status; - - Status = MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_TRANSMIT_T), - PXENV_UNDI_TRANSMIT - ); - if (Status == EFI_SUCCESS) { - return EFI_SUCCESS; - } - - switch (PxeUndiTable->Status) { - case PXENV_STATUS_OUT_OF_RESOURCES: - return EFI_NOT_READY; - - default: - return EFI_DEVICE_ERROR; - } -} - -/** - PXE - UNDI SET MULTICAST ADDRESS - Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h) - Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call changes the current list of multicast addresses to the input list and resets the network - adapter to accept it. If the number of multicast addresses is zero, multicast is disabled. - typedef struct { - PXENV_STATUS Status; - PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf; - } PXENV_UNDI_SET_MCAST_ADDR_T; - Set before calling API service - R_Mcast_Buf: See description in the UNDI RESET ADAPTER - (0004h) API. - Returned from API service - Status: See the PXENV_STATUS_xxx constants - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiSetMcastAddr ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_SET_MCAST_ADDR_T), - PXENV_UNDI_SET_MCAST_ADDR - ); -} - -/** - PXE - UNDI SET STATION ADDRESS - Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah) - Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call sets the MAC address to be the input value and is called before opening the network - adapter. Later, the open call uses this variable as a temporary MAC address to program the - adapter individual address registers. - typedef struct { - PXENV_STATUS Status; - MAC_ADDR StationAddress; - } PXENV_UNDI_SET_STATION_ADDR_T; - Set before calling API service - StationAddress: Temporary MAC address to be used for - transmit and receive. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiSetStationAddr ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_SET_STATION_ADDR_T), - PXENV_UNDI_SET_STATION_ADDR - ); -} - -/** - PXE - UNDI SET PACKET FILTER - Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh) - Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with - the open call. - typedef struct { - PXENV_STATUS Status; - UINT8 filter; - } PXENV_UNDI_SET_PACKET_FILTER_T; - Set before calling API service - Filter: See the receive filter values in the UNDI OPEN - (0006h) API description. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiSetPacketFilter ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_SET_PACKET_FILTER_T), - PXENV_UNDI_SET_PACKET_FILTER - ); -} - -/** - PXE - UNDI GET INFORMATION - Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch) - Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call copies the network adapter variables, including the MAC address, into the input buffer. - Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and - PXENV_UNDI_STARTUP have been issued. All other fields must be valid after - PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been - called. - typedef struct { - PXENV_STATUS Status; - UINT16 BaseIo; - UINT16 IntNumber; - UINT16 MaxTranUnit; - UINT16 HwType; - #define ETHER_TYPE 1 - #define EXP_ETHER_TYPE 2 - #define IEEE_TYPE 6 - #define ARCNET_TYPE 7 - UINT16 HwAddrLen; - MAC_ADDR CurrentNodeAddress; - MAC_ADDR PermNodeAddress; - SEGSEL ROMAddress; - UINT16 RxBufCt; - UINT16 TxBufCt; - } PXENV_UNDI_GET_INFORMATION_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - BaseIO: Adapter base I/O address. - IntNumber: Adapter IRQ number. - MaxTranUnit: Adapter maximum transmit unit. - HWType: Type of protocol at the hardware level. - HWAddrLen: Length of the hardware address. - CurrentNodeAddress: Current hardware address. - PermNodeAddress: Permanent hardware address. - ROMAddress: Real mode ROM segment address. - RxBufCnt: Receive queue length. - TxBufCnt: Transmit queue length. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetInformation ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_GET_INFORMATION_T), - PXENV_UNDI_GET_INFORMATION - ); -} - -/** - PXE - UNDI GET STATISTICS - Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh) - Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized - by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call reads statistical information from the network adapter, and returns. - typedef struct { - PXENV_STATUS Status; - UINT32 XmtGoodFrames; - UINT32 RcvGoodFrames; - UINT32 RcvCRCErrors; - UINT32 RcvResourceErrors; - } PXENV_UNDI_GET_STATISTICS_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - XmtGoodFrames: Number of successful transmissions. - RcvGoodFrames: Number of good frames received. - RcvCRCErrors: Number of frames received with CRC - error. - RcvResourceErrors: Number of frames discarded - because receive queue was full. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetStatistics ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_GET_STATISTICS_T), - PXENV_UNDI_GET_STATISTICS - ); -} - -/** - PXE - UNDI CLEAR STATISTICS - Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh) - Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call clears the statistical information from the network adapter. - typedef struct { - PXENV_STATUS Status; - } PXENV_UNDI_CLEAR_STATISTICS_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiClearStatistics ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_CLEAR_STATISTICS_T), - PXENV_UNDI_CLEAR_STATISTICS - ); -} - -/** - PXE - UNDI INITIATE DIAGS - Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh) - Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the - PXENV_STATUS_xxx constants. - Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run - hardware diagnostics and to update its status information. - typedef struct { - PXENV_STATUS Status; - } PXENV_UNDI_INITIATE_DIAGS_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiInitiateDiags ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_INITIATE_DIAGS_T), - PXENV_UNDI_INITIATE_DIAGS - ); -} - -/** - PXE - UNDI FORCE INTERRUPT - Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h) - Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been - initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the - network adapter driver usually queues the packet and calls the application's callback receive - routine with a pointer to the packet received. Then, the callback routine either can copy the packet - to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied, - the network adapter driver does not remove it from the input queue. When the application wants to - copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive - interrupt. - typedef struct { - PXENV_STATUS Status; - } PXENV_UNDI_FORCE_INTERRUPT_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiForceInterrupt ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_FORCE_INTERRUPT_T), - PXENV_UNDI_FORCE_INTERRUPT - ); -} - -/** - PXE - UNDI GET MULTICAST ADDRESS - Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h) - Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized - by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This call converts the given IP multicast address to a hardware multicast address. - typedef struct { - PXENV_STATUS Status; - IP4 InetAddr; - MAC_ADDR MediaAddr; - } PXENV_UNDI_GET_MCAST_ADDR_T; - Set before calling API service - InetAddr: IP multicast address. - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - MediaAddr: MAC multicast address. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetMcastAddr ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_GET_MCAST_ADDR_T), - PXENV_UNDI_GET_MCAST_ADDR - ); -} - -/** - PXE - UNDI GET NIC TYPE - Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h) - Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE parameter structure that has been initialized by - the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the - NIC information. - Description: This call, if successful, provides the NIC-specific information necessary to identify the network - adapter that is used to boot the system. - Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if - the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific - information can be obtained from the DHCPDISCOVER packet itself. - PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called - before the information provided is valid. - typedef { - PXENV_STATUS Status; - UINT8 NicType; - #define PCI_NIC 2 - #define PnP_NIC 3 - #define CardBus_NIC 4 - Union { - Struct { - UINT16 Vendor_ID; - UINT16 Dev_ID; - UINT8 Base_Class; - UINT8 Sub_Class; - UINT8 Prog_Intf; - UINT8 Rev; - UINT16 BusDevFunc; - UINT16 SubVendor_ID; - UINT16 SubDevice_ID; - } pci, cardbus; - struct { - UINT32 EISA_Dev_ID; - UINT8 Base_Class; - UINT8 Sub_Class; - UINT8 Prog_Intf; - UINT16 CardSelNum; - } pnp; - } info; - } PXENV_UNDI_GET_NIC_TYPE_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - NICType: Type of NIC information stored in the parameter - structure. - Info: Information about the fields in this union can be found - in the [PnP] and [PCI] specifications - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetNicType ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_GET_NIC_TYPE_T), - PXENV_UNDI_GET_NIC_TYPE - ); -} - -/** - PXE - UNDI GET IFACE INFO - Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h) - Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized - by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the - interface specific information. - Description: This call, if successful, provides the network interface specific information such as the interface - type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the - universal drivers such as NDIS or Miniport to communicate to the upper protocol modules. - Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the - universal driver to translate/convert this information into a format that is required in its specification - or to suit the expectation of the upper level protocol modules. - PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called - before the information provided is valid. - typedef struct { - PXENV_STATUS Status - UINT8 IfaceType[16]; - UINT32 LinkSpeed; - UINT32 ServiceFlags; - UINT32 Reserved[4]; - } PXENV_UNDI_GET_NDIS_INFO_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - IfaceType: Name of MAC type in ASCIIZ format. This is - used by the universal NDIS driver to specify its driver type - to the protocol driver. - LinkSpeed: Defined in the NDIS 2.0 specification. - ServiceFlags: Defined in the NDIS 2.0 specification. - Reserved: Must be zero. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetNdisInfo ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_GET_NDIS_INFO_T), - PXENV_UNDI_GET_NDIS_INFO - ); -} - -/** - PXE - UNDI ISR - Op-Code: PXENV_UNDI_ISR (0014h) - Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in - the parameter block indicates the operation to be performed for the call. This field is filled with the - status of that operation on return. - Note: Interrupt Service Routine Operation: - In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the - application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR - API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing - (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT). - When the Network Interface HW generates an interrupt the protocol driver interrupt service - routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then - calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for - the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface - level and read any status values required to further process the interrupt. UNDI must return as - quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or - PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the - interrupt was generated by this particular Network Interface or not. - If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was - not generated by our NIC, and interrupt processing is complete. - If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start - a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is - now complete. - The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to - PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and - return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the - first buffer pointer of that frame in the parameter block. - The protocol driver calls UNDI repeatedly with the FuncFlag equal to - PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received - frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l - remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous - buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter - block. Otherwise it must return the first buffer in the next frame. - If there is no received frame pending to be processed, UNDI processes the transmit completes and - if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the - NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag. - IMPORTANT: It is possible for the protocol driver to be interrupted again while in the - strategy routine when the UNDI re-enables interrupts. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiIsr ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_ISR_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_ISR_T), - PXENV_UNDI_ISR - ); -} - -/** - PXE - STOP UNDI - Op-Code: PXENV_STOP_UNDI (0015h) - Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This routine is responsible for unhooking the Int 1Ah service routine. - Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid - status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from - base memory. Also, UNDI must not be removed from base memory if BC is not removed from base - memory. - Service cannot be used in protected mode. - typedef struct { - PXENV_STATUS Status; - } PXENV_STOP_UNDI_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiStop ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_STOP_UNDI_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_STOP_UNDI_T), - PXENV_STOP_UNDI - ); -} - -/** - PXE - UNDI GET STATE - Op-Code: PXENV_UNDI_GET_STATE (0015h) - Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state - constants - Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call - sequences - typedef struct { - #define PXE_UNDI_GET_STATE_STARTED 1 - #define PXE_UNDI_GET_STATE_INITIALIZED 2 - #define PXE_UNDI_GET_STATE_OPENED 3 - PXENV_STATUS Status; - UINT8 UNDIstate; - } PXENV_UNDI_GET_STATE_T; - Set before calling API service - N/A - Returned from API service - Status: See the PXENV_STATUS_xxx constants. - State: See definitions of the state constants. - Note. UNDI implementation is responsible for maintaining - internal state machine. - UNDI ISR - Op-Code: PXENV_UNDI_ISR (0014h) - Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller. - Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in - the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx - constants. - Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in - the parameter block indicates the operation to be performed for the call. This field is filled with the - status of that operation on return. - - @param SimpleNetworkDevice Device instance - @param PxeUndiTable Point to structure which hold paramter and return value - for option ROM call. - - @return Return value of PXE option ROM far call. -**/ -EFI_STATUS -PxeUndiGetState ( - IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice, - IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable - ) -{ - return MakePxeCall ( - SimpleNetworkDevice, - PxeUndiTable, - sizeof (PXENV_UNDI_GET_STATE_T), - PXENV_UNDI_GET_STATE - ); -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf deleted file mode 100644 index 2e6b0c532d..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf +++ /dev/null @@ -1,73 +0,0 @@ -## @file -# SNP driver On Legacy NIC ROM. -# -# Thunk wrapper UEFI driver to produce EFI SNP protocol based on legacy 16 NIC ROM. -# -# 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 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] - BASE_NAME = BiosSnp16 - MODULE_UNI_FILE = BiosSnp16.uni - FILE_GUID = D0CAA91E-2DE4-4b0d-B3DC-09C67E854E34 - MODULE_TYPE = UEFI_DRIVER - INF_VERSION = 0x00010005 - VERSION_STRING = 1.0 - - ENTRY_POINT = BiosSnp16DriverEntryPoint - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# -# DRIVER_BINDING = gBiosSnp16DriverBinding -# COMPONENT_NAME = gBiosSnp16ComponentName -# - -[Sources] - BiosSnp16.h - BiosSnp16.c - Misc.c - Pxe.h - PxeUndi.c - ComponentName.c - - -[Libraryclasses] - UefiDriverEntryPoint - DebugLib - BaseMemoryLib - UefiBootServicesTableLib - UefiLib - BaseLib - DevicePathLib - MemoryAllocationLib - -[Guids] - gEfiEventExitBootServicesGuid ##CONSUMES ##Event - -[Protocols] - gEfiNetworkInterfaceIdentifierProtocolGuid ##BY_START - gEfiDevicePathProtocolGuid ##BY_START - gEfiDevicePathProtocolGuid ##TO_START - gEfiSimpleNetworkProtocolGuid ##BY_START - gEfiPciIoProtocolGuid ##TO_START - gEfiLegacyBiosProtocolGuid ##CONSUMES - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - -[UserExtensions.TianoCore."ExtraFiles"] - BiosSnp16Extra.uni diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c deleted file mode 100644 index f1c8b29508..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c +++ /dev/null @@ -1,3296 +0,0 @@ -/** @file - ConsoleOut Routines that speak VGA. - -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 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 "BiosVideo.h" - -// -// EFI Driver Binding Protocol Instance -// -EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = { - BiosVideoDriverBindingSupported, - BiosVideoDriverBindingStart, - BiosVideoDriverBindingStop, - 0x3, - NULL, - NULL -}; - -// -// Global lookup tables for VGA graphics modes -// -UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; - -UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; - -UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - -// -// Save controller attributes during first start -// -UINT64 mOriginalPciAttributes; -BOOLEAN mPciAttributesSaved = FALSE; - -EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = { - { 0x00, 0x00, 0x00, 0x00 }, - { 0x98, 0x00, 0x00, 0x00 }, - { 0x00, 0x98, 0x00, 0x00 }, - { 0x98, 0x98, 0x00, 0x00 }, - { 0x00, 0x00, 0x98, 0x00 }, - { 0x98, 0x00, 0x98, 0x00 }, - { 0x00, 0x98, 0x98, 0x00 }, - { 0x98, 0x98, 0x98, 0x00 }, - { 0x10, 0x10, 0x10, 0x00 }, - { 0xff, 0x10, 0x10, 0x00 }, - { 0x10, 0xff, 0x10, 0x00 }, - { 0xff, 0xff, 0x10, 0x00 }, - { 0x10, 0x10, 0xff, 0x00 }, - { 0xf0, 0x10, 0xff, 0x00 }, - { 0x10, 0xff, 0xff, 0x00 }, - { 0xff, 0xff, 0xff, 0x00 } -}; - -// -// Standard timing defined by VESA EDID -// -VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = { - // - // Established Timing I - // - {800, 600, 60}, - {800, 600, 56}, - {640, 480, 75}, - {640, 480, 72}, - {640, 480, 67}, - {640, 480, 60}, - {720, 400, 88}, - {720, 400, 70}, - // - // Established Timing II - // - {1280, 1024, 75}, - {1024, 768, 75}, - {1024, 768, 70}, - {1024, 768, 60}, - {1024, 768, 87}, - {832, 624, 75}, - {800, 600, 75}, - {800, 600, 72}, - // - // Established Timing III - // - {1152, 870, 75} -}; - -/** - Supported. - - @param This Pointer to driver binding protocol - @param Controller Controller handle to connect - @param RemainingDevicePath A pointer to the remaining portion of a device - path - - @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this - driver, Otherwise, this controller cannot be - managed by this driver - -**/ -EFI_STATUS -EFIAPI -BiosVideoDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; - EFI_DEV_PATH *Node; - - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - 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; - } - - if (Status == EFI_ALREADY_STARTED) { - // - // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure, - // because VgaMiniPort protocol is installed on controller handle directly. - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiVgaMiniPortProtocolGuid, - NULL, - NULL, - NULL, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - return EFI_ALREADY_STARTED; - } - } - // - // See if this is a PCI Graphics Controller by looking at the Command register and - // Class Code Register - // - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (Pci) / sizeof (UINT32), - &Pci - ); - if (EFI_ERROR (Status)) { - Status = EFI_UNSUPPORTED; - goto Done; - } - - Status = EFI_UNSUPPORTED; - if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) { - - Status = EFI_SUCCESS; - // - // If this is a graphics controller, - // go further check RemainingDevicePath validation - // - if (RemainingDevicePath != NULL) { - Node = (EFI_DEV_PATH *) RemainingDevicePath; - // - // Check if RemainingDevicePath is the End of Device Path Node, - // if yes, return EFI_SUCCESS - // - if (!IsDevicePathEnd (Node)) { - // - // If RemainingDevicePath isn't the End of Device Path Node, - // check its validation - // - if (Node->DevPath.Type != ACPI_DEVICE_PATH || - Node->DevPath.SubType != ACPI_ADR_DP || - DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) { - Status = EFI_UNSUPPORTED; - } - } - } - } - -Done: - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - - -/** - Install Graphics Output Protocol onto VGA device handles. - - @param This Pointer to driver binding protocol - @param Controller Controller handle to connect - @param RemainingDevicePath A pointer to the remaining portion of a device - path - - @return EFI_STATUS - -**/ -EFI_STATUS -EFIAPI -BiosVideoDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - UINTN Flags; - UINT64 Supports; - - // - // Initialize local variables - // - PciIo = NULL; - ParentDevicePath = NULL; - - // - // - // See if the Legacy BIOS Protocol is available - // - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Prepare for status code - // - Status = gBS->HandleProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Open the IO Abstraction(s) needed - // - 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; - } - - // - // Save original PCI attributes - // - if (!mPciAttributesSaved) { - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationGet, - 0, - &mOriginalPciAttributes - ); - - if (EFI_ERROR (Status)) { - goto Done; - } - mPciAttributesSaved = TRUE; - } - - // - // Get supported PCI attributes - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16); - if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) { - Status = EFI_UNSUPPORTED; - goto Done; - } - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE, - ParentDevicePath - ); - // - // Enable the device and make sure VGA cycles are being forwarded to this VGA device - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Supports, - NULL - ); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT, - ParentDevicePath - ); - goto Done; - } - // - // Check to see if there is a legacy option ROM image associated with this PCI device - // - Status = LegacyBios->CheckPciRom ( - LegacyBios, - Controller, - NULL, - NULL, - &Flags - ); - if (EFI_ERROR (Status)) { - goto Done; - } - // - // Post the legacy option ROM if it is available. - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_P_PC_RESET, - ParentDevicePath - ); - Status = LegacyBios->InstallPciRom ( - LegacyBios, - Controller, - NULL, - &Flags, - NULL, - NULL, - NULL, - NULL - ); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, - ParentDevicePath - ); - goto Done; - } - - if (RemainingDevicePath != NULL) { - if (IsDevicePathEnd (RemainingDevicePath) && - (FeaturePcdGet (PcdBiosVideoCheckVbeEnable) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable))) { - // - // If RemainingDevicePath is the End of Device Path Node, - // don't create any child device and return EFI_SUCESS - Status = EFI_SUCCESS; - goto Done; - } - } - - // - // Create child handle and install GraphicsOutputProtocol on it - // - Status = BiosVideoChildHandleInstall ( - This, - Controller, - PciIo, - LegacyBios, - ParentDevicePath, - RemainingDevicePath - ); - -Done: - if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE, - ParentDevicePath - ); - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED, - ParentDevicePath - ); - if (!HasChildHandle (Controller)) { - if (mPciAttributesSaved) { - // - // Restore original PCI attributes - // - PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSet, - mOriginalPciAttributes, - NULL - ); - } - } - // - // Release PCI I/O Protocols on the controller handle. - // - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - } - - return Status; -} - - -/** - Stop. - - @param This Pointer to driver binding protocol - @param Controller Controller handle to connect - @param NumberOfChildren Number of children handle created by this driver - @param ChildHandleBuffer Buffer containing child handle created - - @retval EFI_SUCCESS Driver disconnected successfully from controller - @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure - -**/ -EFI_STATUS -EFIAPI -BiosVideoDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - BOOLEAN AllChildrenStopped; - UINTN Index; - EFI_PCI_IO_PROTOCOL *PciIo; - - AllChildrenStopped = TRUE; - - if (NumberOfChildren == 0) { - // - // Close PCI I/O protocol on the controller handle - // - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return EFI_SUCCESS; - } - - for (Index = 0; Index < NumberOfChildren; Index++) { - Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]); - - if (EFI_ERROR (Status)) { - AllChildrenStopped = FALSE; - } - } - - if (!AllChildrenStopped) { - return EFI_DEVICE_ERROR; - } - - if (!HasChildHandle (Controller)) { - if (mPciAttributesSaved) { - Status = gBS->HandleProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - ASSERT_EFI_ERROR (Status); - - // - // Restore original PCI attributes - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSet, - mOriginalPciAttributes, - NULL - ); - ASSERT_EFI_ERROR (Status); - } - } - - - return EFI_SUCCESS; -} - - -/** - Install child handles if the Handle supports MBR format. - - @param This Calling context. - @param ParentHandle Parent Handle - @param ParentPciIo Parent PciIo interface - @param ParentLegacyBios Parent LegacyBios interface - @param ParentDevicePath Parent Device Path - @param RemainingDevicePath Remaining Device Path - - @retval EFI_SUCCESS If a child handle was added - @retval other A child handle was not added - -**/ -EFI_STATUS -BiosVideoChildHandleInstall ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ParentHandle, - IN EFI_PCI_IO_PROTOCOL *ParentPciIo, - IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios, - IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - BIOS_VIDEO_DEV *BiosVideoPrivate; - PCI_TYPE00 Pci; - ACPI_ADR_DEVICE_PATH AcpiDeviceNode; - BOOLEAN ProtocolInstalled; - - // - // Allocate the private device structure for video device - // - BiosVideoPrivate = (BIOS_VIDEO_DEV *) AllocateZeroPool ( - sizeof (BIOS_VIDEO_DEV) - ); - if (NULL == BiosVideoPrivate) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - // - // See if this is a VGA compatible controller or not - // - Status = ParentPciIo->Pci.Read ( - ParentPciIo, - EfiPciIoWidthUint32, - 0, - sizeof (Pci) / sizeof (UINT32), - &Pci - ); - if (EFI_ERROR (Status)) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, - ParentDevicePath - ); - goto Done; - } - BiosVideoPrivate->VgaCompatible = FALSE; - if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) { - BiosVideoPrivate->VgaCompatible = TRUE; - } - - if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) { - BiosVideoPrivate->VgaCompatible = TRUE; - } - - if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) { - // - // Create EXIT_BOOT_SERIVES Event - // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - BiosVideoNotifyExitBootServices, - BiosVideoPrivate, - &gEfiEventExitBootServicesGuid, - &BiosVideoPrivate->ExitBootServicesEvent - ); - if (EFI_ERROR (Status)) { - goto Done; - } - } - - // - // Initialize the child private structure - // - BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE; - - // - // Fill in Graphics Output specific mode structures - // - BiosVideoPrivate->HardwareNeedsStarting = TRUE; - BiosVideoPrivate->ModeData = NULL; - BiosVideoPrivate->LineBuffer = NULL; - BiosVideoPrivate->VgaFrameBuffer = NULL; - BiosVideoPrivate->VbeFrameBuffer = NULL; - - // - // Fill in the Graphics Output Protocol - // - BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode; - BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode; - - - // - // Allocate buffer for Graphics Output Protocol mode information - // - BiosVideoPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool ( - sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE) - ); - if (NULL == BiosVideoPrivate->GraphicsOutput.Mode) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - BiosVideoPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool ( - sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) - ); - if (NULL == BiosVideoPrivate->GraphicsOutput.Mode->Info) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - // - // Assume that Graphics Output Protocol will be produced until proven otherwise - // - BiosVideoPrivate->ProduceGraphicsOutput = TRUE; - - // - // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node. - // - if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) { - if (RemainingDevicePath == NULL) { - ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH)); - AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; - AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; - AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0); - SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); - - BiosVideoPrivate->GopDevicePath = AppendDevicePathNode ( - ParentDevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode - ); - } else { - BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath); - } - - // - // Creat child handle and device path protocol firstly - // - BiosVideoPrivate->Handle = NULL; - Status = gBS->InstallMultipleProtocolInterfaces ( - &BiosVideoPrivate->Handle, - &gEfiDevicePathProtocolGuid, - BiosVideoPrivate->GopDevicePath, - NULL - ); - if (EFI_ERROR (Status)) { - goto Done; - } - } - - // - // Fill in the VGA Mini Port Protocol fields - // - BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode; - BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000; - BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4; - BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5; - BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR; - BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; - BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; - - // - // Child handle need to consume the Legacy Bios protocol - // - BiosVideoPrivate->LegacyBios = ParentLegacyBios; - - // - // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally - // - BiosVideoPrivate->PciIo = ParentPciIo; - - // - // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output - // - if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable)) { - Status = BiosVideoCheckForVbe (BiosVideoPrivate); - DEBUG ((EFI_D_INFO, "BiosVideoCheckForVbe - %r\n", Status)); - } else { - Status = EFI_UNSUPPORTED; - } - if (EFI_ERROR (Status)) { - // - // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support - // for the standard 640x480 16 color VGA mode - // - DEBUG ((EFI_D_INFO, "VgaCompatible - %x\n", BiosVideoPrivate->VgaCompatible)); - if (BiosVideoPrivate->VgaCompatible) { - if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable)) { - Status = BiosVideoCheckForVga (BiosVideoPrivate); - DEBUG ((EFI_D_INFO, "BiosVideoCheckForVga - %r\n", Status)); - } else { - Status = EFI_UNSUPPORTED; - } - } - - if (EFI_ERROR (Status)) { - // - // Free GOP mode structure if it is not freed before - // VgaMiniPort does not need this structure any more - // - if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { - if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { - FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); - BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; - } - FreePool (BiosVideoPrivate->GraphicsOutput.Mode); - BiosVideoPrivate->GraphicsOutput.Mode = NULL; - } - - // - // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do - // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol. - // - BiosVideoPrivate->ProduceGraphicsOutput = FALSE; - - // - // INT services are available, so on the 80x25 and 80x50 text mode are supported - // - BiosVideoPrivate->VgaMiniPort.MaxMode = 2; - } - } - - ProtocolInstalled = FALSE; - - if (BiosVideoPrivate->ProduceGraphicsOutput) { - // - // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &BiosVideoPrivate->Handle, - &gEfiGraphicsOutputProtocolGuid, - &BiosVideoPrivate->GraphicsOutput, - &gEfiEdidDiscoveredProtocolGuid, - &BiosVideoPrivate->EdidDiscovered, - &gEfiEdidActiveProtocolGuid, - &BiosVideoPrivate->EdidActive, - NULL - ); - - if (!EFI_ERROR (Status)) { - // - // Open the Parent Handle for the child - // - Status = gBS->OpenProtocol ( - ParentHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &BiosVideoPrivate->PciIo, - This->DriverBindingHandle, - BiosVideoPrivate->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - if (EFI_ERROR (Status)) { - goto Done; - } - ProtocolInstalled = TRUE; - } - } - - if (!ProtocolInstalled) { - // - // Install VGA Mini Port Protocol - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &ParentHandle, - &gEfiVgaMiniPortProtocolGuid, - &BiosVideoPrivate->VgaMiniPort, - NULL - ); - } - -Done: - if (EFI_ERROR (Status)) { - if ((BiosVideoPrivate != NULL) && (BiosVideoPrivate->ExitBootServicesEvent != NULL)) { - gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent); - } - // - // Free private data structure - // - BiosVideoDeviceReleaseResource (BiosVideoPrivate); - } - - return Status; -} - - -/** - Deregister an video child handle and free resources. - - @param This Protocol instance pointer. - @param Controller Video controller handle - @param Handle Video child handle - - @return EFI_STATUS - -**/ -EFI_STATUS -BiosVideoChildHandleUninstall ( - EFI_DRIVER_BINDING_PROTOCOL *This, - EFI_HANDLE Controller, - EFI_HANDLE Handle - ) -{ - EFI_STATUS Status; - EFI_IA32_REGISTER_SET Regs; - EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; - EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; - BIOS_VIDEO_DEV *BiosVideoPrivate; - EFI_PCI_IO_PROTOCOL *PciIo; - - BiosVideoPrivate = NULL; - GraphicsOutput = NULL; - PciIo = NULL; - Status = EFI_UNSUPPORTED; - - Status = gBS->OpenProtocol ( - Handle, - &gEfiGraphicsOutputProtocolGuid, - (VOID **) &GraphicsOutput, - This->DriverBindingHandle, - Handle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput); - } - - if (EFI_ERROR (Status)) { - Status = gBS->OpenProtocol ( - Handle, - &gEfiVgaMiniPortProtocolGuid, - (VOID **) &VgaMiniPort, - This->DriverBindingHandle, - Handle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort); - } - } - - if (BiosVideoPrivate == NULL) { - return EFI_UNSUPPORTED; - } - - // - // Set the 80x25 Text VGA Mode - // - Regs.H.AH = 0x00; - Regs.H.AL = 0x03; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - Regs.H.AH = 0x11; - Regs.H.AL = 0x14; - Regs.H.BL = 0; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - // - // Close PCI I/O protocol that opened by child handle - // - Status = gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Handle - ); - - // - // Uninstall protocols on child handle - // - if (BiosVideoPrivate->ProduceGraphicsOutput) { - Status = gBS->UninstallMultipleProtocolInterfaces ( - BiosVideoPrivate->Handle, - &gEfiDevicePathProtocolGuid, - BiosVideoPrivate->GopDevicePath, - &gEfiGraphicsOutputProtocolGuid, - &BiosVideoPrivate->GraphicsOutput, - &gEfiEdidDiscoveredProtocolGuid, - &BiosVideoPrivate->EdidDiscovered, - &gEfiEdidActiveProtocolGuid, - &BiosVideoPrivate->EdidActive, - NULL - ); - } - if (!BiosVideoPrivate->ProduceGraphicsOutput) { - Status = gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiVgaMiniPortProtocolGuid, - &BiosVideoPrivate->VgaMiniPort, - NULL - ); - } - - if (EFI_ERROR (Status)) { - gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - return Status; - } - - if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) { - // - // Close EXIT_BOOT_SERIVES Event - // - gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent); - } - - // - // Release all allocated resources - // - BiosVideoDeviceReleaseResource (BiosVideoPrivate); - - return EFI_SUCCESS; -} - - -/** - Release resource for biso video instance. - - @param BiosVideoPrivate Video child device private data structure - -**/ -VOID -BiosVideoDeviceReleaseResource ( - BIOS_VIDEO_DEV *BiosVideoPrivate - ) -{ - if (BiosVideoPrivate == NULL) { - return ; - } - - // - // Release all the resourses occupied by the BIOS_VIDEO_DEV - // - - // - // Free VGA Frame Buffer - // - if (BiosVideoPrivate->VgaFrameBuffer != NULL) { - FreePool (BiosVideoPrivate->VgaFrameBuffer); - } - // - // Free VBE Frame Buffer - // - if (BiosVideoPrivate->VbeFrameBuffer != NULL) { - FreePool (BiosVideoPrivate->VbeFrameBuffer); - } - // - // Free line buffer - // - if (BiosVideoPrivate->LineBuffer != NULL) { - FreePool (BiosVideoPrivate->LineBuffer); - } - // - // Free mode data - // - if (BiosVideoPrivate->ModeData != NULL) { - FreePool (BiosVideoPrivate->ModeData); - } - // - // Free memory allocated below 1MB - // - if (BiosVideoPrivate->PagesBelow1MB != 0) { - gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB); - } - - if (BiosVideoPrivate->VbeSaveRestorePages != 0) { - gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages); - } - - // - // Free graphics output protocol occupied resource - // - if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { - if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { - FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); - BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; - } - FreePool (BiosVideoPrivate->GraphicsOutput.Mode); - BiosVideoPrivate->GraphicsOutput.Mode = NULL; - } - // - // Free EDID discovered protocol occupied resource - // - if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) { - FreePool (BiosVideoPrivate->EdidDiscovered.Edid); - } - // - // Free EDID active protocol occupied resource - // - if (BiosVideoPrivate->EdidActive.Edid != NULL) { - FreePool (BiosVideoPrivate->EdidActive.Edid); - } - - if (BiosVideoPrivate->GopDevicePath!= NULL) { - FreePool (BiosVideoPrivate->GopDevicePath); - } - - FreePool (BiosVideoPrivate); - - return ; -} - - -/** - Generate a search key for a specified timing data. - - @param EdidTiming Pointer to EDID timing - - @return The 32 bit unique key for search. - -**/ -UINT32 -CalculateEdidKey ( - VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming - ) -{ - UINT32 Key; - - // - // Be sure no conflicts for all standard timing defined by VESA. - // - Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution; - return Key; -} - - -/** - Parse the Established Timing and Standard Timing in EDID data block. - - @param EdidBuffer Pointer to EDID data block - @param ValidEdidTiming Valid EDID timing information - - @retval TRUE The EDID data is valid. - @retval FALSE The EDID data is invalid. - -**/ -BOOLEAN -ParseEdidData ( - UINT8 *EdidBuffer, - VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming - ) -{ - UINT8 CheckSum; - UINT32 Index; - UINT32 ValidNumber; - UINT32 TimingBits; - UINT8 *BufferIndex; - UINT16 HorizontalResolution; - UINT16 VerticalResolution; - UINT8 AspectRatio; - UINT8 RefreshRate; - VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming; - VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock; - - EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer; - - // - // Check the checksum of EDID data - // - CheckSum = 0; - for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) { - CheckSum = (UINT8) (CheckSum + EdidBuffer[Index]); - } - if (CheckSum != 0) { - return FALSE; - } - - ValidNumber = 0; - gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0); - - if ((EdidDataBlock->EstablishedTimings[0] != 0) || - (EdidDataBlock->EstablishedTimings[1] != 0) || - (EdidDataBlock->EstablishedTimings[2] != 0) - ) { - // - // Established timing data - // - TimingBits = EdidDataBlock->EstablishedTimings[0] | - (EdidDataBlock->EstablishedTimings[1] << 8) | - ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ; - for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) { - if ((TimingBits & 0x1) != 0) { - DEBUG ((EFI_D_INFO, "Established Timing: %d x %d\n", - mEstablishedEdidTiming[Index].HorizontalResolution, mEstablishedEdidTiming[Index].VerticalResolution)); - ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]); - ValidNumber ++; - } - TimingBits = TimingBits >> 1; - } - } - - // - // Parse the standard timing data - // - BufferIndex = &EdidDataBlock->StandardTimingIdentification[0]; - for (Index = 0; Index < 8; Index ++) { - // - // Check if this is a valid Standard Timing entry - // VESA documents unused fields should be set to 01h - // - if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){ - // - // A valid Standard Timing - // - HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248); - AspectRatio = (UINT8) (BufferIndex[1] >> 6); - switch (AspectRatio) { - case 0: - VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10); - break; - case 1: - VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3); - break; - case 2: - VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4); - break; - case 3: - VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9); - break; - default: - VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3); - break; - } - RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60); - DEBUG ((EFI_D_INFO, "Standard Timing: %d x %d\n", HorizontalResolution, VerticalResolution)); - TempTiming.HorizontalResolution = HorizontalResolution; - TempTiming.VerticalResolution = VerticalResolution; - TempTiming.RefreshRate = RefreshRate; - ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming); - ValidNumber ++; - } - BufferIndex += 2; - } - - // - // Parse the Detailed Timing data - // - BufferIndex = &EdidDataBlock->DetailedTimingDescriptions[0]; - for (Index = 0; Index < 4; Index ++, BufferIndex += VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE) { - if ((BufferIndex[0] == 0x0) && (BufferIndex[1] == 0x0)) { - // - // Check if this is a valid Detailed Timing Descriptor - // If first 2 bytes are zero, it is monitor descriptor other than detailed timing descriptor - // - continue; - } - // - // Calculate Horizontal and Vertical resolution - // - TempTiming.HorizontalResolution = ((UINT16)(BufferIndex[4] & 0xF0) << 4) | (BufferIndex[2]); - TempTiming.VerticalResolution = ((UINT16)(BufferIndex[7] & 0xF0) << 4) | (BufferIndex[5]); - DEBUG ((EFI_D_INFO, "Detailed Timing %d: %d x %d\n", - Index, TempTiming.HorizontalResolution, TempTiming.VerticalResolution)); - ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming); - ValidNumber ++; - } - - ValidEdidTiming->ValidNumber = ValidNumber; - return TRUE; -} - - -/** - Search a specified Timing in all the valid EDID timings. - - @param ValidEdidTiming All valid EDID timing information. - @param EdidTiming The Timing to search for. - - @retval TRUE Found. - @retval FALSE Not found. - -**/ -BOOLEAN -SearchEdidTiming ( - VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming, - VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming - ) -{ - UINT32 Index; - UINT32 Key; - - Key = CalculateEdidKey (EdidTiming); - - for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) { - if (Key == ValidEdidTiming->Key[Index]) { - return TRUE; - } - } - - return FALSE; -} - -/** - Check if all video child handles have been uninstalled. - - @param Controller Video controller handle - - @return TRUE Child handles exist. - @return FALSE All video child handles have been uninstalled. - -**/ -BOOLEAN -HasChildHandle ( - IN EFI_HANDLE Controller - ) -{ - UINTN Index; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; - UINTN EntryCount; - BOOLEAN HasChild; - - EntryCount = 0; - HasChild = FALSE; - gBS->OpenProtocolInformation ( - Controller, - &gEfiPciIoProtocolGuid, - &OpenInfoBuffer, - &EntryCount - ); - for (Index = 0; Index < EntryCount; Index++) { - if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { - HasChild = TRUE; - } - } - - return HasChild; -} - -/** - Check for VBE device. - - @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure - - @retval EFI_SUCCESS VBE device found - -**/ -EFI_STATUS -BiosVideoCheckForVbe ( - IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate - ) -{ - EFI_STATUS Status; - EFI_IA32_REGISTER_SET Regs; - UINT16 *ModeNumberPtr; - UINT16 VbeModeNumber; - BOOLEAN ModeFound; - BOOLEAN EdidFound; - BIOS_VIDEO_MODE_DATA *ModeBuffer; - BIOS_VIDEO_MODE_DATA *CurrentModeData; - UINTN PreferMode; - UINTN ModeNumber; - VESA_BIOS_EXTENSIONS_EDID_TIMING Timing; - VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming; - EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride; - UINT32 EdidAttributes; - BOOLEAN EdidOverrideFound; - UINTN EdidOverrideDataSize; - UINT8 *EdidOverrideDataBlock; - UINTN EdidActiveDataSize; - UINT8 *EdidActiveDataBlock; - UINT32 HighestHorizontalResolution; - UINT32 HighestVerticalResolution; - UINTN HighestResolutionMode; - - EdidFound = TRUE; - EdidOverrideFound = FALSE; - EdidOverrideDataBlock = NULL; - EdidActiveDataSize = 0; - EdidActiveDataBlock = NULL; - HighestHorizontalResolution = 0; - HighestVerticalResolution = 0; - HighestResolutionMode = 0; - - // - // Allocate buffer under 1MB for VBE data structures - // - BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES ( - sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) + - sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) + - sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) + - sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK) - ); - - BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1; - - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiBootServicesData, - BiosVideoPrivate->NumberOfPagesBelow1MB, - &BiosVideoPrivate->PagesBelow1MB - ); - if (EFI_ERROR (Status)) { - return Status; - } - - ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING)); - - // - // Fill in the VBE related data structures - // - BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB); - BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1); - BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1); - BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1); - BiosVideoPrivate->VbeSaveRestorePages = 0; - BiosVideoPrivate->VbeSaveRestoreBuffer = 0; - - // - // Test to see if the Video Adapter is compliant with VBE 3.0 - // - gBS->SetMem (&Regs, sizeof (Regs), 0); - Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION; - gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0); - BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE; - Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock); - Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock); - - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - Status = EFI_DEVICE_ERROR; - - // - // See if the VESA call succeeded - // - if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { - return Status; - } - // - // Check for 'VESA' signature - // - if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) { - return Status; - } - // - // Check to see if this is VBE 2.0 or higher - // - if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) { - return Status; - } - - EdidFound = FALSE; - EdidAttributes = 0xff; - EdidOverrideDataSize = 0; - - // - // Find EDID Override protocol firstly, this protocol is installed by platform if needed. - // - Status = gBS->LocateProtocol ( - &gEfiEdidOverrideProtocolGuid, - NULL, - (VOID **) &EdidOverride - ); - if (!EFI_ERROR (Status)) { - // - // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow - // - EdidOverrideDataBlock = AllocatePool (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2); - if (NULL == EdidOverrideDataBlock) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - Status = EdidOverride->GetEdid ( - EdidOverride, - BiosVideoPrivate->Handle, - &EdidAttributes, - &EdidOverrideDataSize, - (UINT8 **) &EdidOverrideDataBlock - ); - if (!EFI_ERROR (Status) && - EdidAttributes == 0 && - EdidOverrideDataSize != 0) { - // - // Succeeded to get EDID Override Data - // - EdidOverrideFound = TRUE; - } - } - - if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) { - // - // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned, - // read EDID information through INT10 call - // - - gBS->SetMem (&Regs, sizeof (Regs), 0); - Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID; - Regs.X.BX = 1; - Regs.X.CX = 0; - Regs.X.DX = 0; - Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock); - Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock); - - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - // - // See if the VESA call succeeded - // - if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { - // - // Set EDID Discovered Data - // - BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; - BiosVideoPrivate->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool ( - VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE, - BiosVideoPrivate->VbeEdidDataBlock - ); - - if (NULL == BiosVideoPrivate->EdidDiscovered.Edid) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - EdidFound = TRUE; - } - } - - if (EdidFound) { - EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; - EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid; - } else if (EdidOverrideFound) { - EdidActiveDataSize = EdidOverrideDataSize; - EdidActiveDataBlock = EdidOverrideDataBlock; - EdidFound = TRUE; - } - - if (EdidFound) { - // - // Parse EDID data structure to retrieve modes supported by monitor - // - if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) { - // - // Copy EDID Override Data to EDID Active Data - // - BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize; - BiosVideoPrivate->EdidActive.Edid = (UINT8 *) AllocateCopyPool ( - EdidActiveDataSize, - EdidActiveDataBlock - ); - if (NULL == BiosVideoPrivate->EdidActive.Edid) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - } - } else { - BiosVideoPrivate->EdidActive.SizeOfEdid = 0; - BiosVideoPrivate->EdidActive.Edid = NULL; - EdidFound = FALSE; - } - - // - // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode - // - ModeNumberPtr = (UINT16 *) - ( - (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) | - ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff) - ); - - PreferMode = 0; - ModeNumber = 0; - - // - // ModeNumberPtr may be not 16-byte aligned, so ReadUnaligned16 is used to access the buffer pointed by ModeNumberPtr. - // - for (VbeModeNumber = ReadUnaligned16 (ModeNumberPtr); - VbeModeNumber != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; - VbeModeNumber = ReadUnaligned16 (++ModeNumberPtr)) { - // - // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number. - // - if ((VbeModeNumber & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) { - continue; - } - // - // Get the information about the mode - // - gBS->SetMem (&Regs, sizeof (Regs), 0); - Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION; - Regs.X.CX = VbeModeNumber; - gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0); - Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock); - Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock); - - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - // - // See if the call succeeded. If it didn't, then try the next mode. - // - if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { - continue; - } - // - // See if the mode supports color. If it doesn't then try the next mode. - // - if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) { - continue; - } - // - // See if the mode supports graphics. If it doesn't then try the next mode. - // - if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) { - continue; - } - // - // See if the mode supports a linear frame buffer. If it doesn't then try the next mode. - // - if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) { - continue; - } - // - // See if the mode supports 32 bit color. If it doesn't then try the next mode. - // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the - // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel - // - if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) { - continue; - } - - if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) { - continue; - } - - if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) { - continue; - } - // - // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode. - // - if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) { - continue; - } - - DEBUG ((EFI_D_INFO, "Video Controller Mode 0x%x: %d x %d\n", - VbeModeNumber, BiosVideoPrivate->VbeModeInformationBlock->XResolution, BiosVideoPrivate->VbeModeInformationBlock->YResolution)); - - if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) { - // - // EDID exist, check whether this mode match with any mode in EDID - // - Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; - Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; - if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) { - // - // When EDID comes from INT10 call, EDID does not include 800x600, 640x480 and 1024x768, - // but INT10 can support these modes, we add them into GOP mode. - // - if ((BiosVideoPrivate->EdidDiscovered.SizeOfEdid != 0) && - !((Timing.HorizontalResolution) == 1024 && (Timing.VerticalResolution == 768)) && - !((Timing.HorizontalResolution) == 800 && (Timing.VerticalResolution == 600)) && - !((Timing.HorizontalResolution) == 640 && (Timing.VerticalResolution == 480))) { - continue; - } - } - } - - // - // Select a reasonable mode to be set for current display mode - // - ModeFound = FALSE; - - if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 && - BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768 - ) { - ModeFound = TRUE; - } - if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 && - BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600 - ) { - ModeFound = TRUE; - PreferMode = ModeNumber; - } - if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 && - BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480 - ) { - ModeFound = TRUE; - } - - if ((!EdidFound) && (!ModeFound)) { - // - // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480 - // - continue; - } - - // - // Record the highest resolution mode to set later - // - if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution > HighestHorizontalResolution) || - ((BiosVideoPrivate->VbeModeInformationBlock->XResolution == HighestHorizontalResolution) && - (BiosVideoPrivate->VbeModeInformationBlock->YResolution > HighestVerticalResolution))) { - HighestHorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; - HighestVerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; - HighestResolutionMode = ModeNumber; - } - - // - // Add mode to the list of available modes - // - ModeNumber ++; - ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool ( - ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA) - ); - if (NULL == ModeBuffer) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - if (ModeNumber > 1) { - CopyMem ( - ModeBuffer, - BiosVideoPrivate->ModeData, - (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA) - ); - } - - if (BiosVideoPrivate->ModeData != NULL) { - FreePool (BiosVideoPrivate->ModeData); - } - - CurrentModeData = &ModeBuffer[ModeNumber - 1]; - CurrentModeData->VbeModeNumber = VbeModeNumber; - if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) { - CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine; - CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition; - CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1); - CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition; - CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1); - CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition; - CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1); - CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition; - CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1); - } else { - CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine; - CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition; - CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1); - CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition; - CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1); - CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition; - CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1); - CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition; - CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1); - } - - CurrentModeData->PixelFormat = PixelBitMask; - if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) && - (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) { - if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) { - CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor; - } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) { - CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; - } - } - - CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position; - CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position; - CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position; - CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position; - - CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr; - CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; - CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; - - CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel; - CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution; - // - // Make sure the FrameBufferSize does not exceed the max available frame buffer size reported by VEB. - // - ASSERT (CurrentModeData->FrameBufferSize <= (UINTN)(BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024)); - - BiosVideoPrivate->ModeData = ModeBuffer; - } - // - // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT - // - if (ModeNumber == 0) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - - // - // Assign Gop's Blt function - // - BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt; - - BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = (UINT32) ModeNumber; - // - // Current mode is unknow till now, set it to an invalid mode. - // - BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; - - // - // Find the best mode to initialize - // - if ((PcdGet32 (PcdVideoHorizontalResolution) == 0x0) || (PcdGet32 (PcdVideoVerticalResolution) == 0x0)) { - DEBUG_CODE ( - BIOS_VIDEO_MODE_DATA *ModeData; - ModeData = &BiosVideoPrivate->ModeData[HighestResolutionMode]; - DEBUG ((EFI_D_INFO, "BiosVideo set highest resolution %d x %d\n", - ModeData->HorizontalResolution, ModeData->VerticalResolution)); - ); - PreferMode = HighestResolutionMode; - } - Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode); - if (EFI_ERROR (Status)) { - for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) { - Status = BiosVideoGraphicsOutputSetMode ( - &BiosVideoPrivate->GraphicsOutput, - (UINT32) PreferMode - ); - if (!EFI_ERROR (Status)) { - break; - } - } - if (PreferMode == ModeNumber) { - // - // None mode is set successfully. - // - goto Done; - } - } - -Done: - // - // If there was an error, then free the mode structure - // - if (EFI_ERROR (Status)) { - if (BiosVideoPrivate->ModeData != NULL) { - FreePool (BiosVideoPrivate->ModeData); - BiosVideoPrivate->ModeData = NULL; - BiosVideoPrivate->MaxMode = 0; - } - if (EdidOverrideDataBlock != NULL) { - FreePool (EdidOverrideDataBlock); - } - } - - return Status; -} - - -/** - Check for VGA device. - - @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure - - @retval EFI_SUCCESS Standard VGA device found - -**/ -EFI_STATUS -BiosVideoCheckForVga ( - IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate - ) -{ - EFI_STATUS Status; - BIOS_VIDEO_MODE_DATA *ModeBuffer; - - Status = EFI_UNSUPPORTED; - - // - // Assign Gop's Blt function - // - BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt; - - // - // Add mode to the list of available modes - // caller should guarantee that Mode has been allocated. - // - ASSERT (BiosVideoPrivate->GraphicsOutput.Mode != NULL); - BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1; - - ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool ( - sizeof (BIOS_VIDEO_MODE_DATA) - ); - if (NULL == ModeBuffer) { - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - - ModeBuffer->VbeModeNumber = 0x0012; - ModeBuffer->BytesPerScanLine = 640; - ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000); - ModeBuffer->HorizontalResolution = 640; - ModeBuffer->VerticalResolution = 480; - ModeBuffer->PixelFormat = PixelBltOnly; - ModeBuffer->BitsPerPixel = 8; - ModeBuffer->ColorDepth = 32; - ModeBuffer->RefreshRate = 60; - - BiosVideoPrivate->ModeData = ModeBuffer; - - // - // Test to see if the Video Adapter support the 640x480 16 color mode - // - BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; - Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0); - -Done: - // - // If there was an error, then free the mode structure - // - if (EFI_ERROR (Status)) { - if (BiosVideoPrivate->ModeData != NULL) { - FreePool (BiosVideoPrivate->ModeData); - BiosVideoPrivate->ModeData = NULL; - } - if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { - if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { - FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); - BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL; - } - FreePool (BiosVideoPrivate->GraphicsOutput.Mode); - BiosVideoPrivate->GraphicsOutput.Mode = NULL; - } - } - return Status; -} - -// -// Graphics Output Protocol Member Functions for VESA BIOS Extensions -// - -/** - Graphics Output protocol interface to get video mode. - - @param This Protocol instance pointer. - @param ModeNumber The mode number to return information on. - @param SizeOfInfo A pointer to the size, in bytes, of the Info - buffer. - @param Info Caller allocated buffer that returns information - about ModeNumber. - - @retval EFI_SUCCESS Mode information returned. - @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the - video mode. - @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 -BiosVideoGraphicsOutputQueryMode ( - IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, - IN UINT32 ModeNumber, - OUT UINTN *SizeOfInfo, - OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info - ) -{ - BIOS_VIDEO_DEV *BiosVideoPrivate; - BIOS_VIDEO_MODE_DATA *ModeData; - - BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); - - if (BiosVideoPrivate->HardwareNeedsStarting) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR, - BiosVideoPrivate->GopDevicePath - ); - return EFI_NOT_STARTED; - } - - if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { - return EFI_INVALID_PARAMETER; - } - - *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool ( - sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) - ); - if (NULL == *Info) { - return EFI_OUT_OF_RESOURCES; - } - - *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); - - ModeData = &BiosVideoPrivate->ModeData[ModeNumber]; - (*Info)->Version = 0; - (*Info)->HorizontalResolution = ModeData->HorizontalResolution; - (*Info)->VerticalResolution = ModeData->VerticalResolution; - (*Info)->PixelFormat = ModeData->PixelFormat; - CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask)); - - (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel; - - return EFI_SUCCESS; -} - -/** - Worker function to set video mode. - - @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV. - @param ModeData The mode data to be set. - @param DevicePath Pointer to Device Path Protocol. - - @retval EFI_SUCCESS Graphics mode was changed. - @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. - -**/ -EFI_STATUS -BiosVideoSetModeWorker ( - IN BIOS_VIDEO_DEV *BiosVideoPrivate, - IN BIOS_VIDEO_MODE_DATA *ModeData, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - EFI_STATUS Status; - EFI_IA32_REGISTER_SET Regs; - - if (BiosVideoPrivate->LineBuffer != NULL) { - FreePool (BiosVideoPrivate->LineBuffer); - } - - if (BiosVideoPrivate->VgaFrameBuffer != NULL) { - FreePool (BiosVideoPrivate->VgaFrameBuffer); - } - - if (BiosVideoPrivate->VbeFrameBuffer != NULL) { - FreePool (BiosVideoPrivate->VbeFrameBuffer); - } - - BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool ( - ModeData->BytesPerScanLine - ); - if (NULL == BiosVideoPrivate->LineBuffer) { - return EFI_OUT_OF_RESOURCES; - } - // - // Clear all registers - // - ZeroMem (&Regs, sizeof (Regs)); - - if (ModeData->VbeModeNumber < 0x100) { - // - // Allocate a working buffer for BLT operations to the VGA frame buffer - // - BiosVideoPrivate->VgaFrameBuffer = (UINT8 *) AllocatePool (4 * 480 * 80); - if (NULL == BiosVideoPrivate->VgaFrameBuffer) { - return EFI_OUT_OF_RESOURCES; - } - // - // Set VGA Mode - // - Regs.X.AX = ModeData->VbeModeNumber; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - } else { - // - // Allocate a working buffer for BLT operations to the VBE frame buffer - // - BiosVideoPrivate->VbeFrameBuffer = - (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool ( - ModeData->BytesPerScanLine * ModeData->VerticalResolution - ); - if (NULL == BiosVideoPrivate->VbeFrameBuffer) { - return EFI_OUT_OF_RESOURCES; - } - // - // Set VBE mode - // - Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE; - Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER); - ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)); - Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock); - Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock); - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - // - // Check to see if the call succeeded - // - if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR, - DevicePath - ); - return EFI_DEVICE_ERROR; - } - // - // Initialize the state of the VbeFrameBuffer - // - Status = BiosVideoPrivate->PciIo->Mem.Read ( - BiosVideoPrivate->PciIo, - EfiPciIoWidthUint32, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) ModeData->LinearFrameBuffer, - (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2, - BiosVideoPrivate->VbeFrameBuffer - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -} - -/** - Graphics Output protocol interface to set video mode. - - @param This Protocol instance pointer. - @param ModeNumber The mode number to be set. - - @retval EFI_SUCCESS Graphics mode was changed. - @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. - -**/ -EFI_STATUS -EFIAPI -BiosVideoGraphicsOutputSetMode ( - IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, - IN UINT32 ModeNumber - ) -{ - EFI_STATUS Status; - BIOS_VIDEO_DEV *BiosVideoPrivate; - BIOS_VIDEO_MODE_DATA *ModeData; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); - - ModeData = &BiosVideoPrivate->ModeData[ModeNumber]; - - if (ModeNumber >= This->Mode->MaxMode) { - return EFI_UNSUPPORTED; - } - - if (ModeNumber == This->Mode->Mode) { - // - // Clear screen to black - // - ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); - BiosVideoGraphicsOutputVbeBlt ( - This, - &Background, - EfiBltVideoFill, - 0, - 0, - 0, - 0, - ModeData->HorizontalResolution, - ModeData->VerticalResolution, - 0 - ); - return EFI_SUCCESS; - } - - Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->GopDevicePath); - if (EFI_ERROR (Status)) { - return Status; - } - - This->Mode->Mode = ModeNumber; - This->Mode->Info->Version = 0; - This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; - This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; - This->Mode->Info->PixelFormat = ModeData->PixelFormat; - CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask)); - This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel; - This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); - This->Mode->FrameBufferSize = ModeData->FrameBufferSize; - This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer; - - BiosVideoPrivate->HardwareNeedsStarting = FALSE; - - return EFI_SUCCESS; -} - -/** - Update physical frame buffer, copy 4 bytes block, then copy remaining bytes. - - @param PciIo The pointer of EFI_PCI_IO_PROTOCOL - @param VbeBuffer The data to transfer to screen - @param MemAddress Physical frame buffer base address - @param DestinationX The X coordinate of the destination for BltOperation - @param DestinationY The Y coordinate of the destination for BltOperation - @param TotalBytes The total bytes of copy - @param VbePixelWidth Bytes per pixel - @param BytesPerScanLine Bytes per scan line - -**/ -VOID -CopyVideoBuffer ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT8 *VbeBuffer, - IN VOID *MemAddress, - IN UINTN DestinationX, - IN UINTN DestinationY, - IN UINTN TotalBytes, - IN UINT32 VbePixelWidth, - IN UINTN BytesPerScanLine - ) -{ - UINTN FrameBufferAddr; - UINTN CopyBlockNum; - UINTN RemainingBytes; - UINTN UnalignedBytes; - EFI_STATUS Status; - - FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth; - - // - // If TotalBytes is less than 4 bytes, only start byte copy. - // - if (TotalBytes < 4) { - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) FrameBufferAddr, - TotalBytes, - VbeBuffer - ); - ASSERT_EFI_ERROR (Status); - return; - } - - // - // If VbeBuffer is not 4-byte aligned, start byte copy. - // - UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3; - - if (UnalignedBytes != 0) { - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) FrameBufferAddr, - UnalignedBytes, - VbeBuffer - ); - ASSERT_EFI_ERROR (Status); - FrameBufferAddr += UnalignedBytes; - VbeBuffer += UnalignedBytes; - } - - // - // Calculate 4-byte block count and remaining bytes. - // - CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2; - RemainingBytes = (TotalBytes - UnalignedBytes) & 3; - - // - // Copy 4-byte block and remaining bytes to physical frame buffer. - // - if (CopyBlockNum != 0) { - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint32, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) FrameBufferAddr, - CopyBlockNum, - VbeBuffer - ); - ASSERT_EFI_ERROR (Status); - } - - if (RemainingBytes != 0) { - FrameBufferAddr += (CopyBlockNum << 2); - VbeBuffer += (CopyBlockNum << 2); - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) FrameBufferAddr, - RemainingBytes, - VbeBuffer - ); - ASSERT_EFI_ERROR (Status); - } -} - -/** - Worker function to block transfer for VBE device. - - @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV - @param BltBuffer The data to transfer to screen - @param BltOperation The operation to perform - @param SourceX The X coordinate of the source for BltOperation - @param SourceY The Y coordinate of the source for BltOperation - @param DestinationX The X coordinate of the destination for - BltOperation - @param DestinationY The Y coordinate of the destination for - BltOperation - @param Width The width of a rectangle in the blt rectangle in - pixels - @param Height The height of a rectangle in the blt rectangle in - pixels - @param Delta Not used for EfiBltVideoFill and - EfiBltVideoToVideo operation. If a Delta of 0 is - used, the entire BltBuffer will be operated on. If - a subrectangle of the BltBuffer is used, then - Delta represents the number of bytes in a row of - the BltBuffer. - @param Mode Mode data. - - @retval EFI_INVALID_PARAMETER Invalid parameter passed in - @retval EFI_SUCCESS Blt operation success - -**/ -EFI_STATUS -BiosVideoVbeBltWorker ( - IN BIOS_VIDEO_DEV *BiosVideoPrivate, - 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, - IN BIOS_VIDEO_MODE_DATA *Mode - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_TPL OriginalTPL; - UINTN DstY; - UINTN SrcY; - UINTN DstX; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; - VOID *MemAddress; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; - UINTN BytesPerScanLine; - UINTN Index; - UINT8 *VbeBuffer; - UINT8 *VbeBuffer1; - UINT8 *BltUint8; - UINT32 VbePixelWidth; - UINT32 Pixel; - UINTN TotalBytes; - - PciIo = BiosVideoPrivate->PciIo; - - VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer; - MemAddress = Mode->LinearFrameBuffer; - BytesPerScanLine = Mode->BytesPerScanLine; - VbePixelWidth = Mode->BitsPerPixel / 8; - BltUint8 = (UINT8 *) BltBuffer; - TotalBytes = Width * VbePixelWidth; - - if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { - return EFI_INVALID_PARAMETER; - } - - if (Width == 0 || Height == 0) { - return EFI_INVALID_PARAMETER; - } - // - // We need to fill the Virtual Screen buffer with the blt data. - // The virtual screen is upside down, as the first row is the bootom row of - // the image. - // - if (BltOperation == EfiBltVideoToBltBuffer) { - // - // Video to BltBuffer: Source is Video, destination is BltBuffer - // - if (SourceY + Height > Mode->VerticalResolution) { - return EFI_INVALID_PARAMETER; - } - - if (SourceX + Width > Mode->HorizontalResolution) { - return EFI_INVALID_PARAMETER; - } - } else { - // - // BltBuffer to Video: Source is BltBuffer, destination is Video - // - if (DestinationY + Height > Mode->VerticalResolution) { - return EFI_INVALID_PARAMETER; - } - - if (DestinationX + Width > Mode->HorizontalResolution) { - return EFI_INVALID_PARAMETER; - } - } - // - // If Delta is zero, then the entire BltBuffer is being used, so Delta - // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, - // the number of bytes in each row can be computed. - // - if (Delta == 0) { - Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); - } - // - // We have to raise to TPL Notify, so we make an atomic write the frame buffer. - // We would not want a timer based event (Cursor, ...) to come in while we are - // doing this operation. - // - OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY); - - switch (BltOperation) { - case EfiBltVideoToBltBuffer: - for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) { - Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); - // - // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL - // - VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth)); - for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { - Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24; - Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask); - Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask); - Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask); - Blt->Reserved = 0; - Blt++; - VbeBuffer += VbePixelWidth; - } - - } - break; - - case EfiBltVideoToVideo: - for (Index = 0; Index < Height; Index++) { - if (DestinationY <= SourceY) { - SrcY = SourceY + Index; - DstY = DestinationY + Index; - } else { - SrcY = SourceY + Height - Index - 1; - DstY = DestinationY + Height - Index - 1; - } - - VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth); - VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth); - - gBS->CopyMem ( - VbeBuffer, - VbeBuffer1, - TotalBytes - ); - - // - // Update physical frame buffer. - // - CopyVideoBuffer ( - PciIo, - VbeBuffer, - MemAddress, - DestinationX, - DstY, - TotalBytes, - VbePixelWidth, - BytesPerScanLine - ); - } - break; - - case EfiBltVideoFill: - VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); - Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8; - // - // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer - // - Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | - ( - (Blt->Green & Mode->Green.Mask) << - Mode->Green.Position - ) | - ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); - - for (Index = 0; Index < Width; Index++) { - gBS->CopyMem ( - VbeBuffer, - &Pixel, - VbePixelWidth - ); - VbeBuffer += VbePixelWidth; - } - - VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); - for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) { - gBS->CopyMem ( - (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), - VbeBuffer, - TotalBytes - ); - } - - for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) { - // - // Update physical frame buffer. - // - CopyVideoBuffer ( - PciIo, - VbeBuffer, - MemAddress, - DestinationX, - DstY, - TotalBytes, - VbePixelWidth, - BytesPerScanLine - ); - } - break; - - case EfiBltBufferToVideo: - for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) { - Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); - VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); - for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { - // - // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer - // - Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | - ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) | - ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); - gBS->CopyMem ( - VbeBuffer, - &Pixel, - VbePixelWidth - ); - Blt++; - VbeBuffer += VbePixelWidth; - } - - VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); - - // - // Update physical frame buffer. - // - CopyVideoBuffer ( - PciIo, - VbeBuffer, - MemAddress, - DestinationX, - DstY, - TotalBytes, - VbePixelWidth, - BytesPerScanLine - ); - } - break; - - default: ; - } - - gBS->RestoreTPL (OriginalTPL); - - return EFI_SUCCESS; -} - -/** - Graphics Output protocol instance to block transfer for VBE device. - - @param This Pointer to Graphics Output protocol instance - @param BltBuffer The data to transfer to screen - @param BltOperation The operation to perform - @param SourceX The X coordinate of the source for BltOperation - @param SourceY The Y coordinate of the source for BltOperation - @param DestinationX The X coordinate of the destination for - BltOperation - @param DestinationY The Y coordinate of the destination for - BltOperation - @param Width The width of a rectangle in the blt rectangle in - pixels - @param Height The height of a rectangle in the blt rectangle in - pixels - @param Delta Not used for EfiBltVideoFill and - EfiBltVideoToVideo operation. If a Delta of 0 is - used, the entire BltBuffer will be operated on. If - a subrectangle of the BltBuffer is used, then - Delta represents the number of bytes in a row of - the BltBuffer. - - @retval EFI_INVALID_PARAMETER Invalid parameter passed in - @retval EFI_SUCCESS Blt operation success - -**/ -EFI_STATUS -EFIAPI -BiosVideoGraphicsOutputVbeBlt ( - 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 - ) -{ - BIOS_VIDEO_DEV *BiosVideoPrivate; - BIOS_VIDEO_MODE_DATA *Mode; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); - Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode]; - - return BiosVideoVbeBltWorker ( - BiosVideoPrivate, - BltBuffer, - BltOperation, - SourceX, - SourceY, - DestinationX, - DestinationY, - Width, - Height, - Delta, - Mode - ); -} - -/** - Write graphics controller registers. - - @param PciIo Pointer to PciIo protocol instance of the - controller - @param Address Register address - @param Data Data to be written to register - - @return None - -**/ -VOID -WriteGraphicsController ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINTN Address, - IN UINTN Data - ) -{ - Address = Address | (Data << 8); - PciIo->Io.Write ( - PciIo, - EfiPciIoWidthUint16, - EFI_PCI_IO_PASS_THROUGH_BAR, - VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER, - 1, - &Address - ); -} - - -/** - Read the four bit plane of VGA frame buffer. - - @param PciIo Pointer to PciIo protocol instance of the - controller - @param HardwareBuffer Hardware VGA frame buffer address - @param MemoryBuffer Memory buffer address - @param WidthInBytes Number of bytes in a line to read - @param Height Height of the area to read - - @return None - -**/ -VOID -VgaReadBitPlanes ( - EFI_PCI_IO_PROTOCOL *PciIo, - UINT8 *HardwareBuffer, - UINT8 *MemoryBuffer, - UINTN WidthInBytes, - UINTN Height - ) -{ - UINTN BitPlane; - UINTN Rows; - UINTN FrameBufferOffset; - UINT8 *Source; - UINT8 *Destination; - - // - // Program the Mode Register Write mode 0, Read mode 0 - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, - VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 - ); - - for (BitPlane = 0, FrameBufferOffset = 0; - BitPlane < VGA_NUMBER_OF_BIT_PLANES; - BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE - ) { - // - // Program the Read Map Select Register to select the correct bit plane - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER, - BitPlane - ); - - Source = HardwareBuffer; - Destination = MemoryBuffer + FrameBufferOffset; - - for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) { - PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) Source, - WidthInBytes, - (VOID *) Destination - ); - } - } -} - - -/** - Internal routine to convert VGA color to Grahpics Output color. - - @param MemoryBuffer Buffer containing VGA color - @param CoordinateX The X coordinate of pixel on screen - @param CoordinateY The Y coordinate of pixel on screen - @param BltBuffer Buffer to contain converted Grahpics Output color - - @return None - -**/ -VOID -VgaConvertToGraphicsOutputColor ( - UINT8 *MemoryBuffer, - UINTN CoordinateX, - UINTN CoordinateY, - EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer - ) -{ - UINTN Mask; - UINTN Bit; - UINTN Color; - - MemoryBuffer += ((CoordinateY << 6) + (CoordinateY << 4) + (CoordinateX >> 3)); - Mask = mVgaBitMaskTable[CoordinateX & 0x07]; - for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) { - if ((*MemoryBuffer & Mask) != 0) { - Color |= Bit; - } - } - - *BltBuffer = mVgaColorToGraphicsOutputColor[Color]; -} - -/** - Internal routine to convert Grahpics Output color to VGA color. - - @param BltBuffer buffer containing Grahpics Output color - - @return Converted VGA color - -**/ -UINT8 -VgaConvertColor ( - IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer - ) -{ - UINT8 Color; - - Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04)); - if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) { - Color |= 0x08; - } - - return Color; -} - - -/** - Grahpics Output protocol instance to block transfer for VGA device. - - @param This Pointer to Grahpics Output protocol instance - @param BltBuffer The data to transfer to screen - @param BltOperation The operation to perform - @param SourceX The X coordinate of the source for BltOperation - @param SourceY The Y coordinate of the source for BltOperation - @param DestinationX The X coordinate of the destination for - BltOperation - @param DestinationY The Y coordinate of the destination for - BltOperation - @param Width The width of a rectangle in the blt rectangle in - pixels - @param Height The height of a rectangle in the blt rectangle in - pixels - @param Delta Not used for EfiBltVideoFill and - EfiBltVideoToVideo operation. If a Delta of 0 is - used, the entire BltBuffer will be operated on. If - a subrectangle of the BltBuffer is used, then - Delta represents the number of bytes in a row of - the BltBuffer. - - @retval EFI_INVALID_PARAMETER Invalid parameter passed in - @retval EFI_SUCCESS Blt operation success - -**/ -EFI_STATUS -EFIAPI -BiosVideoGraphicsOutputVgaBlt ( - 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 - ) -{ - BIOS_VIDEO_DEV *BiosVideoPrivate; - EFI_TPL OriginalTPL; - UINT8 *MemAddress; - UINTN BytesPerScanLine; - UINTN Bit; - UINTN Index; - UINTN Index1; - UINTN StartAddress; - UINTN Bytes; - UINTN Offset; - UINT8 LeftMask; - UINT8 RightMask; - UINTN Address; - UINTN AddressFix; - UINT8 *Address1; - UINT8 *SourceAddress; - UINT8 *DestinationAddress; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT8 Data; - UINT8 PixelColor; - UINT8 *VgaFrameBuffer; - UINTN SourceOffset; - UINTN SourceWidth; - UINTN Rows; - UINTN Columns; - UINTN CoordinateX; - UINTN CoordinateY; - UINTN CurrentMode; - - if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { - return EFI_INVALID_PARAMETER; - } - - BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); - - CurrentMode = This->Mode->Mode; - PciIo = BiosVideoPrivate->PciIo; - MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer; - BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3; - VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer; - - - if (Width == 0 || Height == 0) { - return EFI_INVALID_PARAMETER; - } - // - // We need to fill the Virtual Screen buffer with the blt data. - // The virtual screen is upside down, as the first row is the bootom row of - // the image. - // - if (BltOperation == EfiBltVideoToBltBuffer) { - // - // Video to BltBuffer: Source is Video, destination is BltBuffer - // - if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) { - return EFI_INVALID_PARAMETER; - } - - if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) { - return EFI_INVALID_PARAMETER; - } - } else { - // - // BltBuffer to Video: Source is BltBuffer, destination is Video - // - if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) { - return EFI_INVALID_PARAMETER; - } - - if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) { - return EFI_INVALID_PARAMETER; - } - } - // - // If Delta is zero, then the entire BltBuffer is being used, so Delta - // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, - // the number of bytes in each row can be computed. - // - if (Delta == 0) { - Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); - } - // - // We have to raise to TPL Notify, so we make an atomic write the frame buffer. - // We would not want a timer based event (Cursor, ...) to come in while we are - // doing this operation. - // - OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Compute some values we need for VGA - // - switch (BltOperation) { - case EfiBltVideoToBltBuffer: - - SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); - SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1; - - // - // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer - // - VgaReadBitPlanes ( - PciIo, - MemAddress + SourceOffset, - VgaFrameBuffer + SourceOffset, - SourceWidth, - Height - ); - - // - // Convert VGA Bit Planes to a Graphics Output 32-bit color value - // - BltBuffer += (DestinationY * (Delta >> 2) + DestinationX); - for (Rows = 0, CoordinateY = SourceY; Rows < Height; Rows++, CoordinateY++, BltBuffer += (Delta >> 2)) { - for (Columns = 0, CoordinateX = SourceX; Columns < Width; Columns++, CoordinateX++, BltBuffer++) { - VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, CoordinateY, BltBuffer); - } - - BltBuffer -= Width; - } - - break; - - case EfiBltVideoToVideo: - // - // Check for an aligned Video to Video operation - // - if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) { - // - // Program the Mode Register Write mode 1, Read mode 0 - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, - VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 - ); - - SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3)); - DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); - Bytes = Width >> 3; - for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) { - PciIo->CopyMem ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) (DestinationAddress + Offset), - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) (SourceAddress + Offset), - Bytes - ); - } - } else { - SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); - SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1; - - // - // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer - // - VgaReadBitPlanes ( - PciIo, - MemAddress + SourceOffset, - VgaFrameBuffer + SourceOffset, - SourceWidth, - Height - ); - } - - break; - - case EfiBltVideoFill: - StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); - Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3); - LeftMask = mVgaLeftMaskTable[DestinationX & 0x07]; - RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07]; - if (Bytes == 0) { - LeftMask = (UINT8) (LeftMask & RightMask); - RightMask = 0; - } - - if (LeftMask == 0xff) { - StartAddress--; - Bytes++; - LeftMask = 0; - } - - if (RightMask == 0xff) { - Bytes++; - RightMask = 0; - } - - PixelColor = VgaConvertColor (BltBuffer); - - // - // Program the Mode Register Write mode 2, Read mode 0 - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, - VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 - ); - - // - // Program the Data Rotate/Function Select Register to replace - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER, - VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE - ); - - if (LeftMask != 0) { - // - // Program the BitMask register with the Left column mask - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, - LeftMask - ); - - for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) { - // - // Read data from the bit planes into the latches - // - PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) Address, - 1, - &Data - ); - // - // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask - // - PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) Address, - 1, - &PixelColor - ); - } - } - - if (Bytes > 1) { - // - // Program the BitMask register with the middle column mask of 0xff - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, - 0xff - ); - - for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) { - PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthFillUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) Address, - Bytes - 1, - &PixelColor - ); - } - } - - if (RightMask != 0) { - // - // Program the BitMask register with the Right column mask - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, - RightMask - ); - - for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) { - // - // Read data from the bit planes into the latches - // - PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) Address, - 1, - &Data - ); - // - // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask - // - PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) Address, - 1, - &PixelColor - ); - } - } - break; - - case EfiBltBufferToVideo: - StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); - LeftMask = mVgaBitMaskTable[DestinationX & 0x07]; - - // - // Program the Mode Register Write mode 2, Read mode 0 - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, - VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 - ); - - // - // Program the Data Rotate/Function Select Register to replace - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER, - VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE - ); - - for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) { - for (Index1 = 0; Index1 < Width; Index1++) { - BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]); - } - AddressFix = Address; - - for (Bit = 0; Bit < 8; Bit++) { - // - // Program the BitMask register with the Left column mask - // - WriteGraphicsController ( - PciIo, - VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, - LeftMask - ); - - for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) { - // - // Read data from the bit planes into the latches - // - PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) Address1, - 1, - &Data - ); - - PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) (UINTN) Address1, - 1, - &BiosVideoPrivate->LineBuffer[Index1] - ); - } - - LeftMask = (UINT8) (LeftMask >> 1); - if (LeftMask == 0) { - LeftMask = 0x80; - AddressFix++; - } - } - } - - break; - - default: ; - } - - gBS->RestoreTPL (OriginalTPL); - - return EFI_SUCCESS; -} - -// -// VGA Mini Port Protocol Functions -// - -/** - VgaMiniPort protocol interface to set mode. - - @param This Pointer to VgaMiniPort protocol instance - @param ModeNumber The index of the mode - - @retval EFI_UNSUPPORTED The requested mode is not supported - @retval EFI_SUCCESS The requested mode is set successfully - -**/ -EFI_STATUS -EFIAPI -BiosVideoVgaMiniPortSetMode ( - IN EFI_VGA_MINI_PORT_PROTOCOL *This, - IN UINTN ModeNumber - ) -{ - BIOS_VIDEO_DEV *BiosVideoPrivate; - EFI_IA32_REGISTER_SET Regs; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Make sure the ModeNumber is a valid value - // - if (ModeNumber >= This->MaxMode) { - return EFI_UNSUPPORTED; - } - // - // Get the device structure for this device - // - BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This); - - switch (ModeNumber) { - case 0: - // - // Set the 80x25 Text VGA Mode - // - Regs.H.AH = 0x00; - Regs.H.AL = 0x83; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - Regs.H.AH = 0x11; - Regs.H.AL = 0x14; - Regs.H.BL = 0; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - break; - - case 1: - // - // Set the 80x50 Text VGA Mode - // - Regs.H.AH = 0x00; - Regs.H.AL = 0x83; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - Regs.H.AH = 0x11; - Regs.H.AL = 0x12; - Regs.H.BL = 0; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - break; - - default: - return EFI_UNSUPPORTED; - } - - return EFI_SUCCESS; -} - -/** - Event handler for Exit Boot Service. - - @param Event The event that be siganlled when exiting boot service. - @param Context Pointer to instance of BIOS_VIDEO_DEV. - -**/ -VOID -EFIAPI -BiosVideoNotifyExitBootServices ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - BIOS_VIDEO_DEV *BiosVideoPrivate; - EFI_IA32_REGISTER_SET Regs; - - BiosVideoPrivate = (BIOS_VIDEO_DEV *)Context; - - // - // Set the 80x25 Text VGA Mode - // - Regs.H.AH = 0x00; - Regs.H.AL = 0x03; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - Regs.H.AH = 0x00; - Regs.H.AL = 0x83; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); - - Regs.H.AH = 0x11; - Regs.H.AL = 0x04; - Regs.H.BL = 0; - BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs); -} - -/** - The user Entry Point for module UefiBiosVideo. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -BiosVideoEntryPoint( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gBiosVideoDriverBinding, - ImageHandle, - &gBiosVideoComponentName, - &gBiosVideoComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - // - // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver - // - return gBS->InstallMultipleProtocolInterfaces ( - &ImageHandle, - &gEfiLegacyBiosGuid, - NULL, - NULL - ); -} - diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h deleted file mode 100644 index 88ab1d7cf4..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h +++ /dev/null @@ -1,539 +0,0 @@ -/** @file - -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 _BIOS_GRAPHICS_OUTPUT_H_ -#define _BIOS_GRAPHICS_OUTPUT_H_ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "VesaBiosExtensions.h" - -// -// Packed format support: The number of bits reserved for each of the colors and the actual -// position of RGB in the frame buffer is specified in the VBE Mode information -// -typedef struct { - UINT8 Position; // Position of the color - UINT8 Mask; // The number of bits expressed as a mask -} BIOS_VIDEO_COLOR_PLACEMENT; - -// -// BIOS Graphics Output Graphical Mode Data -// -typedef struct { - UINT16 VbeModeNumber; - UINT16 BytesPerScanLine; - VOID *LinearFrameBuffer; - UINTN FrameBufferSize; - UINT32 HorizontalResolution; - UINT32 VerticalResolution; - UINT32 ColorDepth; - UINT32 RefreshRate; - UINT32 BitsPerPixel; - BIOS_VIDEO_COLOR_PLACEMENT Red; - BIOS_VIDEO_COLOR_PLACEMENT Green; - BIOS_VIDEO_COLOR_PLACEMENT Blue; - BIOS_VIDEO_COLOR_PLACEMENT Reserved; - EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; - EFI_PIXEL_BITMASK PixelBitMask; -} BIOS_VIDEO_MODE_DATA; - -// -// BIOS video child handle private data Structure -// -#define BIOS_VIDEO_DEV_SIGNATURE SIGNATURE_32 ('B', 'V', 'M', 'p') - -typedef struct { - UINTN Signature; - EFI_HANDLE Handle; - - // - // Consumed Protocols - // - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - - // - // Produced Protocols - // - EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; - EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered; - EFI_EDID_ACTIVE_PROTOCOL EdidActive; - EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort; - - // - // General fields - // - BOOLEAN VgaCompatible; - BOOLEAN ProduceGraphicsOutput; - - // - // Graphics Output Protocol related fields - // - BOOLEAN HardwareNeedsStarting; - UINTN CurrentMode; - UINTN MaxMode; - BIOS_VIDEO_MODE_DATA *ModeData; - UINT8 *LineBuffer; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; - UINT8 *VgaFrameBuffer; - - // - // VESA Bios Extensions related fields - // - UINTN NumberOfPagesBelow1MB; // Number of 4KB pages in PagesBelow1MB - EFI_PHYSICAL_ADDRESS PagesBelow1MB; // Buffer for all VBE Information Blocks - VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *VbeInformationBlock; // 0x200 bytes. Must be allocated below 1MB - VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; // 0x100 bytes. Must be allocated below 1MB - VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *VbeEdidDataBlock; // 0x80 bytes. Must be allocated below 1MB - VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; // 59 bytes. Must be allocated below 1MB - UINTN VbeSaveRestorePages; // Number of 4KB pages in VbeSaveRestoreBuffer - EFI_PHYSICAL_ADDRESS VbeSaveRestoreBuffer; // Must be allocated below 1MB - // - // Status code - // - EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; - - EFI_EVENT ExitBootServicesEvent; -} BIOS_VIDEO_DEV; - -#define BIOS_VIDEO_DEV_FROM_PCI_IO_THIS(a) CR (a, BIOS_VIDEO_DEV, PciIo, BIOS_VIDEO_DEV_SIGNATURE) -#define BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS(a) CR (a, BIOS_VIDEO_DEV, GraphicsOutput, BIOS_VIDEO_DEV_SIGNATURE) -#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV, VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE) - -#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding; -extern EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2; - -// -// Driver Binding Protocol functions -// - -/** - Supported. - - @param This Pointer to driver binding protocol - @param Controller Controller handle to connect - @param RemainingDevicePath A pointer to the remaining portion of a device - path - - @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this - driver, Otherwise, this controller cannot be - managed by this driver - -**/ -EFI_STATUS -EFIAPI -BiosVideoDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - - -/** - Install Graphics Output Protocol onto VGA device handles. - - @param This Pointer to driver binding protocol - @param Controller Controller handle to connect - @param RemainingDevicePath A pointer to the remaining portion of a device - path - - @return EFI_STATUS - -**/ -EFI_STATUS -EFIAPI -BiosVideoDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - - -/** - Stop. - - @param This Pointer to driver binding protocol - @param Controller Controller handle to connect - @param NumberOfChildren Number of children handle created by this driver - @param ChildHandleBuffer Buffer containing child handle created - - @retval EFI_SUCCESS Driver disconnected successfully from controller - @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure - -**/ -EFI_STATUS -EFIAPI -BiosVideoDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// Private worker functions -// - -/** - Check for VBE device. - - @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure - - @retval EFI_SUCCESS VBE device found - -**/ -EFI_STATUS -BiosVideoCheckForVbe ( - IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate - ); - - -/** - Check for VGA device. - - @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure - - @retval EFI_SUCCESS Standard VGA device found - -**/ -EFI_STATUS -BiosVideoCheckForVga ( - IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate - ); - - - - -/** - Release resource for biso video instance. - - @param BiosVideoPrivate Video child device private data structure - -**/ -VOID -BiosVideoDeviceReleaseResource ( - BIOS_VIDEO_DEV *BiosVideoPrivate - ); - -// -// BIOS Graphics Output Protocol functions -// - -/** - Graphics Output protocol interface to get video mode. - - @param This Protocol instance pointer. - @param ModeNumber The mode number to return information on. - @param SizeOfInfo A pointer to the size, in bytes, of the Info - buffer. - @param Info Caller 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_NOT_STARTED Video display is not initialized. Call SetMode () - @retval EFI_INVALID_PARAMETER One of the input args was NULL. - -**/ -EFI_STATUS -EFIAPI -BiosVideoGraphicsOutputQueryMode ( - IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, - IN UINT32 ModeNumber, - OUT UINTN *SizeOfInfo, - OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info - ); - - -/** - Graphics Output protocol interface to set video mode. - - @param This Protocol instance pointer. - @param ModeNumber The mode number to be set. - - @retval EFI_SUCCESS Graphics mode was changed. - @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. - -**/ -EFI_STATUS -EFIAPI -BiosVideoGraphicsOutputSetMode ( - IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, - IN UINT32 ModeNumber - ); - - -/** - Graphics Output protocol instance to block transfer for VBE device. - - @param This Pointer to Graphics Output protocol instance - @param BltBuffer The data to transfer to screen - @param BltOperation The operation to perform - @param SourceX The X coordinate of the source for BltOperation - @param SourceY The Y coordinate of the source for BltOperation - @param DestinationX The X coordinate of the destination for - BltOperation - @param DestinationY The Y coordinate of the destination for - BltOperation - @param Width The width of a rectangle in the blt rectangle in - pixels - @param Height The height of a rectangle in the blt rectangle in - pixels - @param Delta Not used for EfiBltVideoFill and - EfiBltVideoToVideo operation. If a Delta of 0 is - used, the entire BltBuffer will be operated on. If - a subrectangle of the BltBuffer is used, then - Delta represents the number of bytes in a row of - the BltBuffer. - - @retval EFI_INVALID_PARAMETER Invalid parameter passed in - @retval EFI_SUCCESS Blt operation success - -**/ -EFI_STATUS -EFIAPI -BiosVideoGraphicsOutputVbeBlt ( - 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 - ); - - -/** - Grahpics Output protocol instance to block transfer for VGA device. - - @param This Pointer to Grahpics Output protocol instance - @param BltBuffer The data to transfer to screen - @param BltOperation The operation to perform - @param SourceX The X coordinate of the source for BltOperation - @param SourceY The Y coordinate of the source for BltOperation - @param DestinationX The X coordinate of the destination for - BltOperation - @param DestinationY The Y coordinate of the destination for - BltOperation - @param Width The width of a rectangle in the blt rectangle in - pixels - @param Height The height of a rectangle in the blt rectangle in - pixels - @param Delta Not used for EfiBltVideoFill and - EfiBltVideoToVideo operation. If a Delta of 0 is - used, the entire BltBuffer will be operated on. If - a subrectangle of the BltBuffer is used, then - Delta represents the number of bytes in a row of - the BltBuffer. - - @retval EFI_INVALID_PARAMETER Invalid parameter passed in - @retval EFI_SUCCESS Blt operation success - -**/ -EFI_STATUS -EFIAPI -BiosVideoGraphicsOutputVgaBlt ( - 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 - ); - -// -// BIOS VGA Mini Port Protocol functions -// - -/** - VgaMiniPort protocol interface to set mode. - - @param This Pointer to VgaMiniPort protocol instance - @param ModeNumber The index of the mode - - @retval EFI_UNSUPPORTED The requested mode is not supported - @retval EFI_SUCCESS The requested mode is set successfully - -**/ -EFI_STATUS -EFIAPI -BiosVideoVgaMiniPortSetMode ( - IN EFI_VGA_MINI_PORT_PROTOCOL *This, - IN UINTN ModeNumber - ); - -/** - Event handler for Exit Boot Service. - - @param Event The event that be siganlled when exiting boot service. - @param Context Pointer to instance of BIOS_VIDEO_DEV. - -**/ -VOID -EFIAPI -BiosVideoNotifyExitBootServices ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -// -// Standard VGA Definitions -// -#define VGA_HORIZONTAL_RESOLUTION 640 -#define VGA_VERTICAL_RESOLUTION 480 -#define VGA_NUMBER_OF_BIT_PLANES 4 -#define VGA_PIXELS_PER_BYTE 8 -#define VGA_BYTES_PER_SCAN_LINE (VGA_HORIZONTAL_RESOLUTION / VGA_PIXELS_PER_BYTE) -#define VGA_BYTES_PER_BIT_PLANE (VGA_VERTICAL_RESOLUTION * VGA_BYTES_PER_SCAN_LINE) - -#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER 0x3ce -#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER 0x3cf - -#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER 0x00 - -#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01 - -#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER 0x02 - -#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER 0x03 -#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE 0x00 -#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND 0x08 -#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR 0x10 -#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR 0x18 - -#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER 0x04 - -#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER 0x05 -#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0 0x00 -#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1 0x08 -#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 0x00 -#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 0x01 -#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 0x02 -#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3 0x03 - -#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER 0x06 - -#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER 0x07 - -#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER 0x08 - -/** - Install child handles if the Handle supports MBR format. - - @param This Calling context. - @param ParentHandle Parent Handle - @param ParentPciIo Parent PciIo interface - @param ParentLegacyBios Parent LegacyBios interface - @param ParentDevicePath Parent Device Path - @param RemainingDevicePath Remaining Device Path - - @retval EFI_SUCCESS If a child handle was added - @retval other A child handle was not added - -**/ -EFI_STATUS -BiosVideoChildHandleInstall ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ParentHandle, - IN EFI_PCI_IO_PROTOCOL *ParentPciIo, - IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios, - IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Deregister an video child handle and free resources. - - @param This Protocol instance pointer. - @param Controller Video controller handle - @param Handle Video child handle - - @return EFI_STATUS - -**/ -EFI_STATUS -BiosVideoChildHandleUninstall ( - EFI_DRIVER_BINDING_PROTOCOL *This, - EFI_HANDLE Controller, - EFI_HANDLE Handle - ); - -/** - Release resource for biso video instance. - - @param BiosVideoPrivate Video child device private data structure - -**/ -VOID -BiosVideoDeviceReleaseResource ( - BIOS_VIDEO_DEV *BiosVideoPrivate - ); - -/** - Check if all video child handles have been uninstalled. - - @param Controller Video controller handle - - @return TRUE Child handles exist. - @return FALSE All video child handles have been uninstalled. - -**/ -BOOLEAN -HasChildHandle ( - IN EFI_HANDLE Controller - ); -#endif diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni deleted file mode 100644 index db9c068146..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni deleted file mode 100644 index 50334d82c4..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c deleted file mode 100644 index d9bd0a9238..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c +++ /dev/null @@ -1,313 +0,0 @@ -/** @file - -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 "BiosVideo.h" - -// -// EFI Component Name Functions -// -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -BiosVideoComponentNameGetDriverName ( - 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 -BiosVideoComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName = { - BiosVideoComponentNameGetDriverName, - BiosVideoComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosVideoComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosVideoComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = { - { - "eng;en", - L"BIOS[INT10] Video Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -BiosVideoComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mBiosVideoDriverNameTable, - DriverName, - (BOOLEAN)(This == &gBiosVideoComponentName) - ); -} - -/** - 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 -BiosVideoComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h deleted file mode 100644 index 25eee6921d..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h +++ /dev/null @@ -1,466 +0,0 @@ -/** @file - -Copyright (c) 2006 - 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 _VESA_BIOS_EXTENSIONS_H_ -#define _VESA_BIOS_EXTENSIONS_H_ - -// -// Turn on byte packing of data structures -// -#pragma pack(1) -// -// VESA BIOS Extensions status codes -// -#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f - -// -// VESA BIOS Extensions Services -// -#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION 0x4f00 - -/*++ - - Routine Description: - Function 00 : Return Controller Information - - Arguments: - Inputs: - AX = 0x4f00 - ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure - Outputs: - AX = Return Status - ---*/ -#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION 0x4f01 - -/*++ - - Routine Description: - Function 01 : Return Mode Information - - Arguments: - Inputs: - AX = 0x4f01 - CX = Mode Number - ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure - Outputs: - AX = Return Status - ---*/ -#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02 - -/*++ - - Routine Description: - Function 02 : Set Mode - - Arguments: - Inputs: - AX = 0x4f02 - BX = Desired mode to set - D0-D8 = Mode Number - D9-D10 = Reserved (must be 0) - D11 = 0 - Use current default refresh rate - = 1 - Use user specfieid CRTC values for refresh rate - D12-D13 = Reserved (must be 0) - D14 = 0 - Use windowed frame buffer model - = 1 - Use linear/flat frame buffer model - D15 = 0 - Clear display memory - = 1 - Don't clear display memory - ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure - Outputs: - AX = Return Status - ---*/ -#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE 0x4f03 - -/*++ - - Routine Description: - Function 03 : Return Current Mode - - Arguments: - Inputs: - AX = 0x4f03 - Outputs: - AX = Return Status - BX = Current mode - D0-D13 = Mode Number - D14 = 0 - Windowed frame buffer model - = 1 - Linear/flat frame buffer model - D15 = 0 - Memory cleared at last mode set - = 1 - Memory not cleared at last mode set - ---*/ -#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04 - -/*++ - - Routine Description: - Function 04 : Save/Restore State - - Arguments: - Inputs: - AX = 0x4f03 - DL = 0x00 - Return Save/Restore State buffer size - = 0x01 - Save State - = 0x02 - Restore State - CX = Requested Status - D0 = Save/Restore controller hardware state - D1 = Save/Restore BIOS data state - D2 = Save/Restore DAC state - D3 = Save/Restore Regsiter state - ES:BX = Pointer to buffer if DL=1 or DL=2 - Outputs: - AX = Return Status - BX = Number of 64 byte blocks to hold the state buffer if DL=0 - ---*/ -#define VESA_BIOS_EXTENSIONS_EDID 0x4f15 - -/*++ - - Routine Description: - Function 15 : implement VBE/DDC service - - Arguments: - Inputs: - AX = 0x4f15 - BL = 0x00 - Report VBE/DDC Capabilities - CX = 0x00 - Controller unit number (00 = primary controller) - ES:DI = Null pointer, must be 0:0 in version 1.0 - Outputs: - AX = Return Status - BH = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes) - BL = DDC level supported - D0 = 0 DDC1 not supported - = 1 DDC1 supported - D1 = 0 DDC2 not supported - = 1 DDC2 supported - D2 = 0 Screen not blanked during data transfer - = 1 Screen blanked during data transfer - - Inputs: - AX = 0x4f15 - BL = 0x01 - Read EDID - CX = 0x00 - Controller unit number (00 = primary controller) - DX = 0x00 - EDID block number - ES:DI = Pointer to buffer in which the EDID block is returned - Outputs: - AX = Return Status ---*/ - -// -// Timing data from EDID data block -// -#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE 128 -#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17 - -// -// Established Timings: 24 possible resolutions -// Standard Timings: 8 possible resolutions -// Detailed Timings: 4 possible resolutions -// -#define VESA_BIOS_EXTENSIONS_EDID_TIMING_MAX_NUMBER 36 - -// -// Timing data size for Established Timings, Standard Timings and Detailed Timings -// -#define VESA_BIOS_EXTENSIONS_ESTABLISHED_TIMING_SIZE 3 -#define VESA_BIOS_EXTENSIONS_STANDARD_TIMING_SIZE 16 -#define VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE 18 -#define VESA_BIOS_EXTENSIONS_DETAILED_TIMING_DESCRIPTOR_MAX_SIZE 72 - -typedef struct { - UINT16 HorizontalResolution; - UINT16 VerticalResolution; - UINT16 RefreshRate; -} VESA_BIOS_EXTENSIONS_EDID_TIMING; - -typedef struct { - UINT32 ValidNumber; - UINT32 Key[VESA_BIOS_EXTENSIONS_EDID_TIMING_MAX_NUMBER]; -} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING; - -typedef struct { - UINT8 Header[8]; //EDID header "00 FF FF FF FF FF FF 00" - UINT16 ManufactureName; //EISA 3-character ID - UINT16 ProductCode; //Vendor assigned code - UINT32 SerialNumber; //32-bit serial number - UINT8 WeekOfManufacture; //Week number - UINT8 YearOfManufacture; //Year - UINT8 EdidVersion; //EDID Structure Version - UINT8 EdidRevision; //EDID Structure Revision - UINT8 VideoInputDefinition; - UINT8 MaxHorizontalImageSize; //cm - UINT8 MaxVerticalImageSize; //cm - UINT8 DisplayTransferCharacteristic; - UINT8 FeatureSupport; - UINT8 RedGreenLowBits; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0 - UINT8 BlueWhiteLowBits; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0 - UINT8 RedX; //Red-x Bits 9 - 2 - UINT8 RedY; //Red-y Bits 9 - 2 - UINT8 GreenX; //Green-x Bits 9 - 2 - UINT8 GreenY; //Green-y Bits 9 - 2 - UINT8 BlueX; //Blue-x Bits 9 - 2 - UINT8 BlueY; //Blue-y Bits 9 - 2 - UINT8 WhiteX; //White-x Bits 9 - 2 - UINT8 WhiteY; //White-x Bits 9 - 2 - UINT8 EstablishedTimings[VESA_BIOS_EXTENSIONS_ESTABLISHED_TIMING_SIZE]; - UINT8 StandardTimingIdentification[VESA_BIOS_EXTENSIONS_STANDARD_TIMING_SIZE]; - UINT8 DetailedTimingDescriptions[VESA_BIOS_EXTENSIONS_DETAILED_TIMING_DESCRIPTOR_MAX_SIZE]; - UINT8 ExtensionFlag; //Number of (optional) 128-byte EDID extension blocks to follow - UINT8 Checksum; -} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK; - -// -// Super VGA Information Block -// -typedef struct { - UINT32 VESASignature; // 'VESA' 4 byte signature - UINT16 VESAVersion; // VBE version number - UINT32 OEMStringPtr; // Pointer to OEM string - UINT32 Capabilities; // Capabilities of video card - UINT32 VideoModePtr; // Pointer to an array of 16-bit supported modes values terminated by 0xFFFF - UINT16 TotalMemory; // Number of 64kb memory blocks - UINT16 OemSoftwareRev; // VBE implementation Software revision - UINT32 OemVendorNamePtr; // VbeFarPtr to Vendor Name String - UINT32 OemProductNamePtr; // VbeFarPtr to Product Name String - UINT32 OemProductRevPtr; // VbeFarPtr to Product Revision String - UINT8 Reserved[222]; // Reserved for VBE implementation scratch area - UINT8 OemData[256]; // Data area for OEM strings. Pad to 512 byte block size -} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK; - -// -// Super VGA Information Block VESASignature values -// -#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE SIGNATURE_32 ('V', 'E', 'S', 'A') -#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE SIGNATURE_32 ('V', 'B', 'E', '2') - -// -// Super VGA Information Block VESAVersion values -// -#define VESA_BIOS_EXTENSIONS_VERSION_1_2 0x0102 -#define VESA_BIOS_EXTENSIONS_VERSION_2_0 0x0200 -#define VESA_BIOS_EXTENSIONS_VERSION_3_0 0x0300 - -// -// Super VGA Information Block Capabilities field bit defintions -// -#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01 // 0: DAC width is fixed at 6 bits/color -// 1: DAC width switchable to 8 bits/color -// -#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02 // 0: Controller is VGA compatible -// 1: Controller is not VGA compatible -// -#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04 // 0: Normal RAMDAC operation -// 1: Use blank bit in function 9 to program RAMDAC -// -#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC 0x08 // 0: No hardware stereoscopic signal support -// 1: Hardware stereoscopic signal support -// -#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC 0x10 // 0: Stero signaling supported via external VESA stereo connector -// 1: Stero signaling supported via VESA EVC connector -// -// Super VGA mode number bite field definitions -// -#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100 // 0: Not a VESA defined VBE mode -// 1: A VESA defined VBE mode -// -#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800 // 0: Use current BIOS default referesh rate -// 1: Use the user specified CRTC values for refresh rate -// -#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER 0x4000 // 0: Use a banked/windowed frame buffer -// 1: Use a linear/flat frame buffer -// -#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY 0x8000 // 0: Clear display memory -// 1: Preseve display memory -// -// Super VGA Information Block mode list terminator value -// -#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff - -// -// Window Function -// -typedef -VOID -(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) ( - VOID - ); - -// -// Super VGA Mode Information Block -// -typedef struct { - // - // Manadory fields for all VESA Bios Extensions revisions - // - UINT16 ModeAttributes; // Mode attributes - UINT8 WinAAttributes; // Window A attributes - UINT8 WinBAttributes; // Window B attributes - UINT16 WinGranularity; // Window granularity in k - UINT16 WinSize; // Window size in k - UINT16 WinASegment; // Window A segment - UINT16 WinBSegment; // Window B segment - UINT32 WindowFunction; // Pointer to window function - UINT16 BytesPerScanLine; // Bytes per scanline - // - // Manadory fields for VESA Bios Extensions 1.2 and above - // - UINT16 XResolution; // Horizontal resolution - UINT16 YResolution; // Vertical resolution - UINT8 XCharSize; // Character cell width - UINT8 YCharSize; // Character cell height - UINT8 NumberOfPlanes; // Number of memory planes - UINT8 BitsPerPixel; // Bits per pixel - UINT8 NumberOfBanks; // Number of CGA style banks - UINT8 MemoryModel; // Memory model type - UINT8 BankSize; // Size of CGA style banks - UINT8 NumberOfImagePages; // Number of images pages - UINT8 Reserved1; // Reserved - UINT8 RedMaskSize; // Size of direct color red mask - UINT8 RedFieldPosition; // Bit posn of lsb of red mask - UINT8 GreenMaskSize; // Size of direct color green mask - UINT8 GreenFieldPosition; // Bit posn of lsb of green mask - UINT8 BlueMaskSize; // Size of direct color blue mask - UINT8 BlueFieldPosition; // Bit posn of lsb of blue mask - UINT8 RsvdMaskSize; // Size of direct color res mask - UINT8 RsvdFieldPosition; // Bit posn of lsb of res mask - UINT8 DirectColorModeInfo; // Direct color mode attributes - // - // Manadory fields for VESA Bios Extensions 2.0 and above - // - UINT32 PhysBasePtr; // Physical Address for flat memory frame buffer - UINT32 Reserved2; // Reserved - UINT16 Reserved3; // Reserved - // - // Manadory fields for VESA Bios Extensions 3.0 and above - // - UINT16 LinBytesPerScanLine; // Bytes/scan line for linear modes - UINT8 BnkNumberOfImagePages; // Number of images for banked modes - UINT8 LinNumberOfImagePages; // Number of images for linear modes - UINT8 LinRedMaskSize; // Size of direct color red mask (linear mode) - UINT8 LinRedFieldPosition; // Bit posiiton of lsb of red mask (linear modes) - UINT8 LinGreenMaskSize; // Size of direct color green mask (linear mode) - UINT8 LinGreenFieldPosition; // Bit posiiton of lsb of green mask (linear modes) - UINT8 LinBlueMaskSize; // Size of direct color blue mask (linear mode) - UINT8 LinBlueFieldPosition; // Bit posiiton of lsb of blue mask (linear modes) - UINT8 LinRsvdMaskSize; // Size of direct color reserved mask (linear mode) - UINT8 LinRsvdFieldPosition; // Bit posiiton of lsb of reserved mask (linear modes) - UINT32 MaxPixelClock; // Maximum pixel clock (in Hz) for graphics mode - UINT8 Pad[190]; // Pad to 256 byte block size -} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK; - -// -// Super VGA Mode Information Block ModeAttributes field bit defintions -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE 0x0001 // 0: Mode not supported in handware -// 1: Mode supported in handware -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004 // 0: TTY Output functions not supported by BIOS -// 1: TTY Output functions supported by BIOS -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008 // 0: Monochrome mode -// 1: Color mode -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS 0x0010 // 0: Text mode -// 1: Graphics mode -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020 // 0: VGA compatible mode -// 1: Not a VGA compatible mode -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED 0x0040 // 0: VGA compatible windowed memory mode -// 1: Not a VGA compatible windowed memory mode -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080 // 0: No linear fram buffer mode available -// 1: Linear frame buffer mode available -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100 // 0: No double scan mode available -// 1: Double scan mode available -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED 0x0200 // 0: No interlaced mode is available -// 1: Interlaced mode is available -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400 // 0: No hardware triple buffer mode support available -// 1: Hardware triple buffer mode support available -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC 0x0800 // 0: No hardware steroscopic display support -// 1: Hardware steroscopic display support -// -#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY 0x1000 // 0: No dual display start address support -// 1: Dual display start address support -// -// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit defintions -// -#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01 // 0: Single non-relocatable window only -// 1: Relocatable window(s) are supported -// -#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE 0x02 // 0: Window is not readable -// 1: Window is readable -// -#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE 0x04 // 0: Window is not writable -// 1: Window is writable -// -// Super VGA Mode Information Block DirectColorMode field bit defintions -// -#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP 0x01 // 0: Color ram is fixed -// 1: Color ramp is programmable -// -#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE 0x02 // 0: Bits in Rsvd field are reserved -// 1: Bits in Rsdv field are usable -// -// Super VGA Memory Models -// -typedef enum { - MemPL = 3, // Planar memory model - MemPK = 4, // Packed pixel memory model - MemRGB= 6, // Direct color RGB memory model - MemYUV= 7 // Direct color YUV memory model -} VESA_BIOS_EXTENSIONS_MEMORY_MODELS; - -// -// Super VGA CRTC Information Block -// -typedef struct { - UINT16 HorizontalTotal; // Horizontal total in pixels - UINT16 HorizontalSyncStart; // Horizontal sync start in pixels - UINT16 HorizontalSyncEnd; // Horizontal sync end in pixels - UINT16 VericalTotal; // Vertical total in pixels - UINT16 VericalSyncStart; // Vertical sync start in pixels - UINT16 VericalSyncEnd; // Vertical sync end in pixels - UINT8 Flags; // Flags (Interlaced/DoubleScan/etc). - UINT32 PixelClock; // Pixel clock in units of Hz - UINT16 RefreshRate; // Refresh rate in units of 0.01 Hz - UINT8 Reserved[40]; // Pad -} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK; - -#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01 // 0: Graphics mode is not souble scanned -// 1: Graphics mode is double scanned -// -#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02 // 0: Graphics mode is not interlaced -// 1: Graphics mode is interlaced -// -#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE 0x04 // 0: Horizontal sync polarity is positive(+) -// 0: Horizontal sync polarity is negative(-) -// -#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08 // 0: Verical sync polarity is positive(+) -// 0: Verical sync polarity is negative(-) -// -// Turn off byte packing of data structures -// -#pragma pack() - -#endif diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf deleted file mode 100644 index 7b1764acfc..0000000000 --- a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf +++ /dev/null @@ -1,87 +0,0 @@ -## @file -# Video driver based on legacy bios. -# -# This driver by using Legacy Bios protocol service to support csm Video -# and produce Graphics Output Protocol. -# -# 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 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 = BiosVideoDxe - MODULE_UNI_FILE = BiosVideoDxe.uni - FILE_GUID = 0B04B2ED-861C-42cd-A22F-C3AAFACCB896 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - - ENTRY_POINT = BiosVideoEntryPoint - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# -# DRIVER_BINDING = gBiosVideoDriverBinding -# COMPONENT_NAME = gBiosVideoComponentName -# - -[Sources] - BiosVideo.c - BiosVideo.h - ComponentName.c - VesaBiosExtensions.h - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - - -[LibraryClasses] - MemoryAllocationLib - DevicePathLib - UefiLib - UefiBootServicesTableLib - UefiDriverEntryPoint - BaseMemoryLib - ReportStatusCodeLib - DebugLib - PcdLib - - -[Guids] - gEfiLegacyBiosGuid ## PRODUCES ##GUID # Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver - gEfiEventExitBootServicesGuid ## CONSUMES ##Event - -[Protocols] - gEfiVgaMiniPortProtocolGuid ## BY_START - gEfiEdidDiscoveredProtocolGuid ## BY_START - gEfiGraphicsOutputProtocolGuid ## BY_START - gEfiEdidActiveProtocolGuid ## BY_START - gEfiLegacyBiosProtocolGuid ## CONSUMES - gEfiPciIoProtocolGuid ## TO_START - gEfiDevicePathProtocolGuid ## TO_START - gEfiDevicePathProtocolGuid ## BY_START - gEfiEdidOverrideProtocolGuid ## SOMETIMES_CONSUMES - -[Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable ## SOMETIMES_CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## SOMETIMES_CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## SOMETIMES_CONSUMES - -[UserExtensions.TianoCore."ExtraFiles"] - BiosVideoDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.S b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.S deleted file mode 100644 index a785256052..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.S +++ /dev/null @@ -1,67 +0,0 @@ -## @file -# Interrupt Redirection Template -# -# Copyright (c) 2006, Intel 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. -# -## - -ASM_GLOBAL ASM_PFX(InterruptRedirectionTemplate) - -#---------------------------------------------------------------------------- -# Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F -# -# Input: None -# -# Output: None -# -# Prototype: VOID -# InterruptRedirectionTemplate ( -# VOID -# ); -# -# Saves: None -# -# Modified: None -# -# Description: Contains the code that is copied into low memory (below 640K). -# This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. -# This template must be copied into low memory, and the IDT entries -# 0x68-0x6F must be point to the low memory copy of this code. Each -# entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily -# computed. -# -#---------------------------------------------------------------------------- -ASM_PFX(InterruptRedirectionTemplate): - int $0x8 - .byte 0xcf - nop - int $0x9 - .byte 0xcf - nop - int $0xa - .byte 0xcf - nop - int $0xb - .byte 0xcf - nop - int $0xc - .byte 0xcf - nop - int $0xd - .byte 0xcf - nop - int $0xe - .byte 0xcf - nop - int $0xf - .byte 0xcf - nop diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.asm b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.asm deleted file mode 100644 index 410ce5be6e..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/IA32/InterruptTable.asm +++ /dev/null @@ -1,73 +0,0 @@ -;; @file -; Interrupt Redirection Template -; -; Copyright (c) 2006, Intel 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. -; -;; - -.686P -.MODEL FLAT, C -.CODE - -;---------------------------------------------------------------------------- -; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F -; -; Input: None -; -; Output: None -; -; Prototype: VOID -; InterruptRedirectionTemplate ( -; VOID -; ); -; -; Saves: None -; -; Modified: None -; -; Description: Contains the code that is copied into low memory (below 640K). -; This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. -; This template must be copied into low memory, and the IDT entries -; 0x68-0x6F must be point to the low memory copy of this code. Each -; entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily -; computed. -; -;---------------------------------------------------------------------------- - -InterruptRedirectionTemplate PROC C - int 08h - DB 0cfh ; IRET - nop - int 09h - DB 0cfh ; IRET - nop - int 0ah - DB 0cfh ; IRET - nop - int 0bh - DB 0cfh ; IRET - nop - int 0ch - DB 0cfh ; IRET - nop - int 0dh - DB 0cfh ; IRET - nop - int 0eh - DB 0cfh ; IRET - nop - int 0fh - DB 0cfh ; IRET - nop -InterruptRedirectionTemplate ENDP - -END \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c deleted file mode 100644 index 8c8f6d321b..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c +++ /dev/null @@ -1,277 +0,0 @@ -/** @file - -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 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 "LegacyBiosInterface.h" - -/** - Assign drive number to legacy HDD drives prior to booting an EFI - aware OS so the OS can access drives without an EFI driver. - Note: BBS compliant drives ARE NOT available until this call by - either shell or EFI. - - @param This Protocol instance pointer. - @param BbsCount Number of BBS_TABLE structures - @param BbsTable List BBS entries - - @retval EFI_SUCCESS Drive numbers assigned - -**/ -EFI_STATUS -EFIAPI -LegacyBiosPrepareToBootEfi ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - OUT UINT16 *BbsCount, - OUT BBS_TABLE **BbsTable - ) -{ - // - // Shadow All Opion ROM - // - LegacyBiosShadowAllLegacyOproms (This); - return EFI_SUCCESS; -} - - -/** - To boot from an unconventional device like parties and/or execute - HDD diagnostics. - - @param This Protocol instance pointer. - @param Attributes How to interpret the other input parameters - @param BbsEntry The 0-based index into the BbsTable for the - parent device. - @param BeerData Pointer to the 128 bytes of ram BEER data. - @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. - The caller must provide a pointer to the specific - Service Area and not the start all Service Areas. - EFI_INVALID_PARAMETER if error. Does NOT return if no error. - -**/ -EFI_STATUS -EFIAPI -LegacyBiosBootUnconventionalDevice ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UDC_ATTRIBUTES Attributes, - IN UINTN BbsEntry, - IN VOID *BeerData, - IN VOID *ServiceAreaData - ) -{ - return EFI_INVALID_PARAMETER; -} - - -/** - Attempt to legacy boot the BootOption. If the EFI contexted has been - compromised this function will not return. - - @param This Protocol instance pointer. - @param BbsDevicePath EFI Device Path from BootXXXX variable. - @param LoadOptionsSize Size of LoadOption in size. - @param LoadOptions LoadOption from BootXXXX variable - - @retval EFI_SUCCESS Removable media not present - -**/ -EFI_STATUS -EFIAPI -LegacyBiosLegacyBoot ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN BBS_BBS_DEVICE_PATH *BbsDevicePath, - IN UINT32 LoadOptionsSize, - IN VOID *LoadOptions - ) -{ - return EFI_UNSUPPORTED; -} - -/** - Build the E820 table. - - @param Private Legacy BIOS Instance data - @param Size Size of E820 Table - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosBuildE820 ( - IN LEGACY_BIOS_INSTANCE *Private, - OUT UINTN *Size - ) -{ - *Size = 0; - return EFI_SUCCESS; -} - -/** - Get all BBS info - - @param This Protocol instance pointer. - @param HddCount Number of HDD_INFO structures - @param HddInfo Onboard IDE controller information - @param BbsCount Number of BBS_TABLE structures - @param BbsTable List BBS entries - - @retval EFI_SUCCESS Tables returned - @retval EFI_NOT_FOUND resource not found - @retval EFI_DEVICE_ERROR can not get BBS table - -**/ -EFI_STATUS -EFIAPI -LegacyBiosGetBbsInfo ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - OUT UINT16 *HddCount, - OUT HDD_INFO **HddInfo, - OUT UINT16 *BbsCount, - OUT BBS_TABLE **BbsTable - ) -{ - return EFI_UNSUPPORTED; -} - -/** - Fill in the standard BDA for Keyboard LEDs - - @param This Protocol instance pointer. - @param Leds Current LED status - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -EFIAPI -LegacyBiosUpdateKeyboardLedStatus ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT8 Leds - ) -{ - return EFI_UNSUPPORTED; -} - -/** - Relocate this image under 4G memory for IPF. - - @param ImageHandle Handle of driver image. - @param SystemTable Pointer to system table. - - @retval EFI_SUCCESS Image successfully relocated. - @retval EFI_ABORTED Failed to relocate image. - -**/ -EFI_STATUS -RelocateImageUnder4GIfNeeded ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - UINTN NumberOfPages; - EFI_PHYSICAL_ADDRESS LoadedImageBase; - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; - EFI_PHYSICAL_ADDRESS MemoryAddress; - EFI_HANDLE NewImageHandle; - - Status = gBS->HandleProtocol ( - ImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID *) &LoadedImage - ); - - if (!EFI_ERROR (Status)) { - LoadedImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImage->ImageBase; - if (LoadedImageBase > 0xffffffff) { - NumberOfPages = (UINTN) (DivU64x32(LoadedImage->ImageSize, EFI_PAGE_SIZE) + 1); - - // - // Allocate buffer below 4GB here - // - Status = AllocateLegacyMemory ( - AllocateMaxAddress, - 0x7FFFFFFF, - NumberOfPages, // do we have to convert this to pages?? - &MemoryAddress - ); - if (EFI_ERROR (Status)) { - return Status; - } - - ZeroMem (&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); - ImageContext.Handle = (VOID *)(UINTN)LoadedImageBase; - ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; - - // - // Get information about the image being loaded - // - Status = PeCoffLoaderGetImageInfo (&ImageContext); - if (EFI_ERROR (Status)) { - return Status; - } - ImageContext.ImageAddress = (PHYSICAL_ADDRESS)MemoryAddress; - // - // Align buffer on section boundry - // - ImageContext.ImageAddress += ImageContext.SectionAlignment - 1; - ImageContext.ImageAddress &= ~((PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1); - - // - // Load the image to our new buffer - // - Status = PeCoffLoaderLoadImage (&ImageContext); - if (EFI_ERROR (Status)) { - gBS->FreePages (MemoryAddress, NumberOfPages); - return Status; - } - - // - // Relocate the image in our new buffer - // - Status = PeCoffLoaderRelocateImage (&ImageContext); - if (EFI_ERROR (Status)) { - gBS->FreePages (MemoryAddress, NumberOfPages); - return Status; - } - - // - // Create a new handle with gEfiCallerIdGuid to be used as the ImageHandle fore the reloaded image - // - NewImageHandle = NULL; - Status = gBS->InstallProtocolInterface ( - &NewImageHandle, - &gEfiCallerIdGuid, - EFI_NATIVE_INTERFACE, - NULL - ); - - // - // Flush the instruction cache so the image data is written before we execute it - // - InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); - - Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable); - if (EFI_ERROR (Status)) { - gBS->FreePages (MemoryAddress, NumberOfPages); - return Status; - } - // - // return error directly the BS will unload this image - // - return EFI_ABORTED; - } - } - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h deleted file mode 100644 index 26aa3a694b..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h +++ /dev/null @@ -1,102 +0,0 @@ -/** @file - -Copyright (c) 2007 - 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 _IPF_THUNK_H_ -#define _IPF_THUNK_H_ - -#include "LegacyBiosInterface.h" -#include - -/** - Template of real mode code. - - @param CodeStart Start address of code. - @param CodeEnd End address of code - @param ReverseThunkStart Start of reverse thunk. - @param IntThunk Low memory thunk. - -**/ -VOID -RealModeTemplate ( - OUT UINTN *CodeStart, - OUT UINTN *CodeEnd, - OUT UINTN *ReverseThunkStart, - LOW_MEMORY_THUNK *IntThunk - ); - -/** - Register physical address of Esal Data Area - - @param ReverseThunkCodeAddress Reverse Thunk Address - @param IntThunkAddress IntThunk Address - - @retval EFI_SUCCESS ESAL data area set successfully. - -**/ -EFI_STATUS -EsalSetSalDataArea ( - IN UINTN ReverseThunkCodeAddress, - IN UINTN IntThunkAddress - ); - -/** - Get address of reverse thunk. - - @retval EFI_SAL_SUCCESS Address of reverse thunk returned successfully. - -**/ -SAL_RETURN_REGS -EsalGetReverseThunkAddress ( - VOID - ); - -typedef struct { - UINT32 Eax; // 0 - UINT32 Ecx; // 4 - UINT32 Edx; // 8 - UINT32 Ebx; // 12 - UINT32 Esp; // 16 - UINT32 Ebp; // 20 - UINT32 Esi; // 24 - UINT32 Edi; // 28 - UINT32 Eflag; // 32 - UINT32 Eip; // 36 - UINT16 Cs; // 40 - UINT16 Ds; // 42 - UINT16 Es; // 44 - UINT16 Fs; // 46 - UINT16 Gs; // 48 - UINT16 Ss; // 50 -} IPF_DWORD_REGS; - -/** - Entrypoint of IA32 code. - - @param CallTypeData Data of call type - @param DwordRegister Register set of IA32 general registers - and segment registers - @param StackPointer Stack pointer. - @param StackSize Size of stack. - -**/ -VOID -EfiIaEntryPoint ( - UINT64 CallTypeData, - IPF_DWORD_REGS *DwordRegister, - UINT64 StackPointer, - UINT64 StackSize - ); - -#endif diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i deleted file mode 100644 index 441bb25e3d..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i +++ /dev/null @@ -1,89 +0,0 @@ -//// @file -// -// Copyright (c) 2006, Intel 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. -// -//// - -#define NUM_REAL_GDT_ENTRIES 3 -#define LOW_STACK_SIZE (8*1024) // 8k? - -// -// Low memory Thunk Structure -// -#define Code 0 -#define LowReverseThunkStart Code + 4096 -#define GdtDesc LowReverseThunkStart + 4 -#define IdtDesc GdtDesc + 6 -#define FlatSs IdtDesc + 6 -#define FlatEsp FlatSs + 4 -#define LowCodeSelector FlatEsp + 4 -#define LowDataSelector LowCodeSelector + 4 -#define LowStack LowDataSelector + 4 -#define RealModeIdtDesc LowStack + 4 -#define RealModeGdt RealModeIdtDesc + 6 -#define RealModeGdtDesc RealModeGdt + (8 * NUM_REAL_GDT_ENTRIES) -#define RevRealDs RealModeGdtDesc + 6 -#define RevRealSs RevRealDs + 2 -#define RevRealEsp RevRealSs + 2 -#define RevRealIdtDesc RevRealEsp + 4 -#define RevFlatDataSelector RevRealIdtDesc + 6 -#define RevFlatStack RevFlatDataSelector + 2 -#define Stack RevFlatStack + 4 -#define RevThunkStack Stack + LOW_STACK_SIZE - -#define EfiToLegacy16InitTable RevThunkStack + LOW_STACK_SIZE -#define InitTableBiosLessThan1MB EfiToLegacy16InitTable -#define InitTableHiPmmMemory InitTableBiosLessThan1MB + 4 -#define InitTablePmmMemorySizeInBytes InitTableHiPmmMemory + 4 -#define InitTableReverseThunkCallSegment InitTablePmmMemorySizeInBytes + 4 -#define InitTableReverseThunkCallOffset InitTableReverseThunkCallSegment + 2 -#define InitTableNumberE820Entries InitTableReverseThunkCallOffset + 2 -#define InitTableOsMemoryAbove1Mb InitTableNumberE820Entries + 4 -#define InitTableThunkStart InitTableOsMemoryAbove1Mb + 4 -#define InitTableThunkSizeInBytes InitTableThunkStart + 4 -#define InitTable16InitTableEnd InitTableThunkSizeInBytes + 4 - -#define EfiToLegacy16BootTable InitTable16InitTableEnd -#define BootTableBiosLessThan1MB EfiToLegacy16BootTable -#define BootTableHiPmmMemory BootTableBiosLessThan1MB + 4 -#define BootTablePmmMemorySizeInBytes BootTableHiPmmMemory + 4 -#define BootTableReverseThunkCallSegment BootTablePmmMemorySizeInBytes + 4 -#define BootTableReverseThunkCallOffset BootTableReverseThunkCallSegment + 2 -#define BootTableNumberE820Entries BootTableReverseThunkCallOffset + 2 -#define BootTableOsMemoryAbove1Mb BootTableNumberE820Entries + 4 -#define BootTableThunkStart BootTableOsMemoryAbove1Mb + 4 -#define BootTableThunkSizeInBytes BootTableThunkStart + 4 -#define EfiToLegacy16BootTableEnd BootTableThunkSizeInBytes + 4 - -#define InterruptRedirectionCode EfiToLegacy16BootTableEnd -#define PciHandler InterruptRedirectionCode + 32 - - -// -// Register Sets (16 Bit) -// - -#define AX 0 -#define BX 2 -#define CX 4 -#define DX 6 -#define SI 8 -#define DI 10 -#define Flags 12 -#define ES 14 -#define CS 16 -#define SS 18 -#define DS 20 -#define BP 22 - - - diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s deleted file mode 100644 index fc56176934..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s +++ /dev/null @@ -1,524 +0,0 @@ -//// @file -// -// Copyright (c) 1999 - 2008, Intel 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. -// -//// - -.file "IpfThunk.s" - -#include "IpfMacro.i" -#include "Ipf/IpfThunk.i" - -.align 0x10 -//----------------------------------------------------------------------------- -//++ -// EfiIaEntryPoint -// -// Register physical address of Esal Data Area -// -// On Entry : -// in1 = ptr to legacy bios reg -// in2 = ptr to Call Stack -// in3 = Call Stack Size -// -// Return Value: -// r8 = SAL_SUCCESS -// -// As per static calling conventions. -// -//-- -//--------------------------------------------------------------------------- -PROCEDURE_ENTRY(EfiIaEntryPoint) - - alloc loc0 = 8,10,8,0;; - - mov out0 = r0;; - mov out1 = r0;; - mov out2 = r0;; - mov out3 = r0;; - mov out4 = r0;; - mov out5 = r0;; - mov out6 = r0;; - mov out7 = r0;; - - mov loc1 = b0;; // save efi (b0) - mov loc2 = psr;; // save efi (PSR) - mov loc3 = gp;; // save efi (GP) - mov loc4 = pr;; // save efi (PR) - mov loc5 = sp;; // save efi (SP) - mov loc6 = r13;; // save efi (TP) - mov loc7 = ar.lc;; // save efi (LC) - mov loc8 = ar.fpsr;; // save efi (FPSR) - - mov r8 = r0;; // return status - mov r9 = r0;; // return value - mov r10 = r0;; // return value - mov r11 = r0;; // return value - -bios_int_func:: - rsm 0x4000;; // i(14)=0, disable interrupt - srlz.d;; - srlz.i;; - -//---------------------// -// save fp registers // -//---------------------// - - dep sp = 0,sp,0,4;; // align 16 - add sp = -16,sp;; // post decrement - -int_ip_1x:: - mov r2 = ip;; - add r2 = (int_ip_1y - int_ip_1x),r2;; - mov b7 = r2;; - br save_fp_registers;; - -int_ip_1y:: - add sp = 16,sp;; // adjust (SP) - mov loc9 = sp;; // save (SP) - adds sp = 0x10,in1;; // in1 + 0x10 = SP - ld4 sp = [sp];; // SP - adds r17 = 0x32,in1;; // in1 + 0x32 = SS - ld2 r17 = [r17];; // SS - movl r2 = 0xffffffff;; // if no SS:SP, then define new SS:SP - cmp.ne p6,p0 = sp,r2;; - movl r2 = 0xffff;; - cmp.ne.or p6,p0 = r17,r2;; - (p6) br.sptk bif_1;; - - mov sp = in3;; // 16-bit stack pointer - mov r2 = psr;; - tbit.z p6,p7 = r2,17;; // psr.dt (Physical OR Virtual) - -bif_ip1x:: - mov r2 = in2;; // ia32 callback stack top - mov r3 = in3;; // 16-bit stack pointer - sub r2 = r2,r3;; - shr.u r17 = r2,4;; // 16-bit stack segment - -bif_1:: - extr.u sp = sp,0,16;; // SP (16-bit sp for legacy code) - dep sp = 0,sp,0,3;; // align 8 - cmp.eq p6,p0 = 0,sp;; // if SP=0000 then wrap to 0x10000 - (p6) dep sp = -1,sp,16,1;; - shladd r2 = r17,4,sp;; // ESP = SS<<4+SP - add r2 = -8,r2;; // post decrement 64 bit pointer - add sp = -8,sp;; // post decrement SP - -sale_ip1x:: - mov r18 = ip;; - adds r18 = (sale_ip1y - sale_ip1x),r18;; - sub r18 = r18,r2;; // return address - CS base - add r18 = r18,sp;; // adjustment for stack - shl r18 = r18,32;; - movl r19 = 0xb80f66fa;; // CLI, JMPE xxxxxxxx - or r18 = r18,r19;; - st8 [r2] = r18;; // (FA,66,0F,B8,xx,xx,xx,xx) - - cmp.eq p6,p0 = 0,sp;; // if SP=0000 then wrap to 0x10000 - (p6) dep sp = -1,sp,16,1;; - shladd r2 = r17,4,sp;; // ESP=SS<<4+SP - add r2 = -2,r2;; // post decrement 64 bit pointer - add sp = -2,sp;; // post decrement SP - - movl r18 = 0x8000000000000100;; // CALL FAR function - cmp.eq p6,p7 = in0,r18;; - (p6) add r19 = 0x28,in1;; // in1 + 0x28 = CS - (p6) ld2 r18 = [r19],-4;; // CS - (p6) st2 [r2] = r18,-2;; // in1 + 0x24 = EIP - (p6) ld2 r18 = [r19];; // EIP - (p6) st2 [r2] = r18,-2;; // - (p6) movl r18 = 0x9a90;; // nop, CALLFAR xxxx:yyyy - - (p7) movl r18 = 0xcd;; // INT xx - (p7) dep r18 = in0,r18,8,8;; - st2 [r2] = r18;; // (CD,xx) - - mov r18 = r2;; // EIP for legacy execution - -//------------------------------// -// flush 32 bytes legacy code // -//------------------------------// - - dep r2 = 0,r2,0,5;; // align to 32 - fc r2;; - sync.i;; - srlz.i;; - srlz.d;; - -//------------------------------// -// load legacy registers // -//------------------------------// - mov r2 = in1;; // IA32 BIOS register state - ld4 r8 = [r2],4;; // in1 + 0 = EAX - ld4 r9 = [r2],4;; // in1 + 4 = ECX - ld4 r10 = [r2],4;; // in1 + 8 = EDX - ld4 r11 = [r2],4;; // in1 + 12 = EBX - - add r2 = 4,r2;; // in1 + 16 = ESP (skip) - - ld4 r13 = [r2],4;; // in1 + 20 = EBP - ld4 r14 = [r2],4;; // in1 + 24 = ESI - ld4 r15 = [r2],4;; // in1 + 28 = EDI - ld4 r3 = [r2],4;; // in1 + 32 = EFLAGS - mov ar.eflag = r3;; - - add r2 = 4,r2;; // in1 + 36 = EIP (skip) - add r2 = 2,r2;; // in1 + 40 = CS (skip) - - ld2 r16 = [r2],2;; // in1 + 42 = DS, (r16 = GS,FS,ES,DS) - movl r27 = 0xc93fffff00000000;; - dep r27 = r16,r27,4,16;; // r27 = DSD - - ld2 r19 = [r2],2;; // in1 + 44 = ES - dep r16 = r19,r16,16,16;; - movl r24 = 0xc93fffff00000000;; - dep r24 = r19,r24,4,16;; // r24 = ESD - - ld2 r19 = [r2],2;; // in1 + 46 = FS - dep r16 = r19,r16,32,16;; - movl r28 = 0xc93fffff00000000;; - dep r28 = r19,r28,4,16;; // r28 = FSD - - ld2 r19 = [r2],2;; // in1 + 48 = GS - dep r16 = r19,r16,48,16;; - movl r29 = 0xc93fffff00000000;; - dep r29 = r19,r29,4,16;; // r29 = GSD - - mov r30 = r0;; // r30 = LDTD, clear NaT - mov r31 = r0;; // r31 = GDTD, clear NaT - - dep r17 = r17,r17,16,16;; // CS = SS, (r17 = TSS,LDT,SS,CS) - - movl r3 = 0x0930ffff00000000;; - dep r3 = r17,r3,4,16;; - mov ar.csd = r3;; // ar25 = CSD - mov ar.ssd = r3;; // ar26 = SSD - -//------------------------------// -// give control to INT function // -//------------------------------// - - br.call.sptk b0 = execute_int_function;; - -//------------------------------// -// store legacy registers // -//------------------------------// - - mov r2 = in1;; - st4 [r2] = r8,4;; // EAX - st4 [r2] = r9,4;; // ECX - st4 [r2] = r10,4;; // EDX - st4 [r2] = r11,4;; // EBX - - add r2 = 4,r2;; // ESP (skip) - - st4 [r2] = r13,4;; // EBP - st4 [r2] = r14,4;; // ESI - st4 [r2] = r15,4;; // EDI - - mov r3 = ar.eflag;; - st4 [r2] = r3,4;; // EFLAGS - - add r2 = 4,r2;; // EIP (skip) - add r2 = 2,r2;; // CS (skip) - - st2 [r2] = r16,2;; // DS, (r16 = GS,FS,ES,DS) - - extr.u r3 = r16,16,16;; - st2 [r2] = r3,2;; // ES - - extr.u r3 = r16,32,16;; - st2 [r2] = r3,2;; // FS - - extr.u r3 = r16,48,16;; - st2 [r2] = r3,2;; // GS - -//------------------------------// -// restore fp registers // -//------------------------------// - mov sp = loc9;; // restore (SP) -int_ip_2x:: - mov r2 = ip;; - add r2 = (int_ip_2y - int_ip_2x),r2;; - mov b7 = r2;; - br restore_fp_registers;; - -int_ip_2y:: - mov r8 = r0;; // return status - mov r9 = r0;; // return value - mov r10 = r0;; // return value - mov r11 = r0;; // return value - - mov ar.fpsr = loc8;; // restore efi (FPSR) - mov ar.lc = loc7;; // restore efi (LC) - mov r13 = loc6;; // restore efi (TP) - mov sp = loc5;; // restore efi (SP) - mov pr = loc4;; // restore efi (PR) - mov gp = loc3;; // restore efi (GP) - mov psr.l = loc2;; // restore efi (PSR) - srlz.d;; - srlz.i;; - mov b0 = loc1;; // restore efi (b0) - mov ar.pfs = loc0;; - br.ret.sptk b0;; // return to efi - -PROCEDURE_EXIT (EfiIaEntryPoint) - -//==============================// -// EXECUTE_INT_FUNCTION // -//==============================// -// switch to virtual address // -//------------------------------// - -execute_int_function:: - - alloc r2 = 0,0,0,0;; // cfm.sof=0 - flushrs;; - - rsm 0x2000;; // ic(13)=0 for control register programming - srlz.d;; - srlz.i;; - - mov r2 = psr;; - dep r2 = -1,r2,34,1;; // set is(34) - dep r2 = -1,r2,44,1;; // set bn(44) - dep r2 = -1,r2,36,1;; // set it(36) - dep r2 = -1,r2,27,1;; // set rt(27) - dep r2 = -1,r2,17,1;; // set dt(17) - dep r2 = 0,r2,3,1;; // reset ac(3) - dep r2 = -1,r2,13,1;; // set ic(13) - - mov cr.ipsr = r2;; - mov cr.ifs = r0;; // clear interruption function state register - mov cr.iip = r18;; - - rfi;; // go to legacy code execution - -//------------------------------// -// back from legacy code // -//------------------------------// -// switch to physical address // -//------------------------------// - -sale_ip1y:: - rsm 0x6000;; // i(14)=0,ic(13)=0 for control reg programming - srlz.d;; - srlz.i;; - - mov r2 = psr;; - dep r2 = -1,r2,44,1;; // set bn(44) - dep r2 = 0,r2,36,1;; // reset it(36) - dep r2 = 0,r2,27,1;; // reset rt(27) - dep r2 = 0,r2,17,1;; // reset dt(17) - dep r2 = -1,r2,13,1;; // set ic(13) - mov cr.ipsr = r2;; - -sale_ip2x:: - mov r2 = ip;; - add r2 = (sale_ip2y - sale_ip2x),r2;; - mov cr.ifs = r0;; // clear interruption function state register - mov cr.iip = r2;; - rfi;; - -sale_ip2y:: - br.ret.sptk b0;; // return to SAL - -//------------------------------// -// store fp registers // -//------------------------------// -save_fp_registers:: - stf.spill [sp]=f2,-16;; stf.spill [sp]=f3,-16;; - stf.spill [sp]=f4,-16;; stf.spill [sp]=f5,-16;; stf.spill [sp]=f6,-16;; stf.spill [sp]=f7,-16;; - stf.spill [sp]=f8,-16;; stf.spill [sp]=f9,-16;; stf.spill [sp]=f10,-16;; stf.spill [sp]=f11,-16;; - stf.spill [sp]=f12,-16;; stf.spill [sp]=f13,-16;; stf.spill [sp]=f14,-16;; stf.spill [sp]=f15,-16;; - stf.spill [sp]=f16,-16;; stf.spill [sp]=f17,-16;; stf.spill [sp]=f18,-16;; stf.spill [sp]=f19,-16;; - stf.spill [sp]=f20,-16;; stf.spill [sp]=f21,-16;; stf.spill [sp]=f22,-16;; stf.spill [sp]=f23,-16;; - stf.spill [sp]=f24,-16;; stf.spill [sp]=f25,-16;; stf.spill [sp]=f26,-16;; stf.spill [sp]=f27,-16;; - stf.spill [sp]=f28,-16;; stf.spill [sp]=f29,-16;; stf.spill [sp]=f30,-16;; stf.spill [sp]=f31,-16;; - stf.spill [sp]=f32,-16;; stf.spill [sp]=f33,-16;; stf.spill [sp]=f34,-16;; stf.spill [sp]=f35,-16;; - stf.spill [sp]=f36,-16;; stf.spill [sp]=f37,-16;; stf.spill [sp]=f38,-16;; stf.spill [sp]=f39,-16;; - stf.spill [sp]=f40,-16;; stf.spill [sp]=f41,-16;; stf.spill [sp]=f42,-16;; stf.spill [sp]=f43,-16;; - stf.spill [sp]=f44,-16;; stf.spill [sp]=f45,-16;; stf.spill [sp]=f46,-16;; stf.spill [sp]=f47,-16;; - stf.spill [sp]=f48,-16;; stf.spill [sp]=f49,-16;; stf.spill [sp]=f50,-16;; stf.spill [sp]=f51,-16;; - stf.spill [sp]=f52,-16;; stf.spill [sp]=f53,-16;; stf.spill [sp]=f54,-16;; stf.spill [sp]=f55,-16;; - stf.spill [sp]=f56,-16;; stf.spill [sp]=f57,-16;; stf.spill [sp]=f58,-16;; stf.spill [sp]=f59,-16;; - stf.spill [sp]=f60,-16;; stf.spill [sp]=f61,-16;; stf.spill [sp]=f62,-16;; stf.spill [sp]=f63,-16;; - stf.spill [sp]=f64,-16;; stf.spill [sp]=f65,-16;; stf.spill [sp]=f66,-16;; stf.spill [sp]=f67,-16;; - stf.spill [sp]=f68,-16;; stf.spill [sp]=f69,-16;; stf.spill [sp]=f70,-16;; stf.spill [sp]=f71,-16;; - stf.spill [sp]=f72,-16;; stf.spill [sp]=f73,-16;; stf.spill [sp]=f74,-16;; stf.spill [sp]=f75,-16;; - stf.spill [sp]=f76,-16;; stf.spill [sp]=f77,-16;; stf.spill [sp]=f78,-16;; stf.spill [sp]=f79,-16;; - stf.spill [sp]=f80,-16;; stf.spill [sp]=f81,-16;; stf.spill [sp]=f82,-16;; stf.spill [sp]=f83,-16;; - stf.spill [sp]=f84,-16;; stf.spill [sp]=f85,-16;; stf.spill [sp]=f86,-16;; stf.spill [sp]=f87,-16;; - stf.spill [sp]=f88,-16;; stf.spill [sp]=f89,-16;; stf.spill [sp]=f90,-16;; stf.spill [sp]=f91,-16;; - stf.spill [sp]=f92,-16;; stf.spill [sp]=f93,-16;; stf.spill [sp]=f94,-16;; stf.spill [sp]=f95,-16;; - stf.spill [sp]=f96,-16;; stf.spill [sp]=f97,-16;; stf.spill [sp]=f98,-16;; stf.spill [sp]=f99,-16;; - stf.spill [sp]=f100,-16;;stf.spill [sp]=f101,-16;;stf.spill [sp]=f102,-16;;stf.spill [sp]=f103,-16;; - stf.spill [sp]=f104,-16;;stf.spill [sp]=f105,-16;;stf.spill [sp]=f106,-16;;stf.spill [sp]=f107,-16;; - stf.spill [sp]=f108,-16;;stf.spill [sp]=f109,-16;;stf.spill [sp]=f110,-16;;stf.spill [sp]=f111,-16;; - stf.spill [sp]=f112,-16;;stf.spill [sp]=f113,-16;;stf.spill [sp]=f114,-16;;stf.spill [sp]=f115,-16;; - stf.spill [sp]=f116,-16;;stf.spill [sp]=f117,-16;;stf.spill [sp]=f118,-16;;stf.spill [sp]=f119,-16;; - stf.spill [sp]=f120,-16;;stf.spill [sp]=f121,-16;;stf.spill [sp]=f122,-16;;stf.spill [sp]=f123,-16;; - stf.spill [sp]=f124,-16;;stf.spill [sp]=f125,-16;;stf.spill [sp]=f126,-16;;stf.spill [sp]=f127,-16;; - invala;; - br b7;; - -//------------------------------// -// restore fp registers // -//------------------------------// -restore_fp_registers:: - ldf.fill f127=[sp],16;;ldf.fill f126=[sp],16;;ldf.fill f125=[sp],16;;ldf.fill f124=[sp],16;; - ldf.fill f123=[sp],16;;ldf.fill f122=[sp],16;;ldf.fill f121=[sp],16;;ldf.fill f120=[sp],16;; - ldf.fill f119=[sp],16;;ldf.fill f118=[sp],16;;ldf.fill f117=[sp],16;;ldf.fill f116=[sp],16;; - ldf.fill f115=[sp],16;;ldf.fill f114=[sp],16;;ldf.fill f113=[sp],16;;ldf.fill f112=[sp],16;; - ldf.fill f111=[sp],16;;ldf.fill f110=[sp],16;;ldf.fill f109=[sp],16;;ldf.fill f108=[sp],16;; - ldf.fill f107=[sp],16;;ldf.fill f106=[sp],16;;ldf.fill f105=[sp],16;;ldf.fill f104=[sp],16;; - ldf.fill f103=[sp],16;;ldf.fill f102=[sp],16;;ldf.fill f101=[sp],16;;ldf.fill f100=[sp],16;; - ldf.fill f99=[sp],16;; ldf.fill f98=[sp],16;; ldf.fill f97=[sp],16;; ldf.fill f96=[sp],16;; - ldf.fill f95=[sp],16;; ldf.fill f94=[sp],16;; ldf.fill f93=[sp],16;; ldf.fill f92=[sp],16;; - ldf.fill f91=[sp],16;; ldf.fill f90=[sp],16;; ldf.fill f89=[sp],16;; ldf.fill f88=[sp],16;; - ldf.fill f87=[sp],16;; ldf.fill f86=[sp],16;; ldf.fill f85=[sp],16;; ldf.fill f84=[sp],16;; - ldf.fill f83=[sp],16;; ldf.fill f82=[sp],16;; ldf.fill f81=[sp],16;; ldf.fill f80=[sp],16;; - ldf.fill f79=[sp],16;; ldf.fill f78=[sp],16;; ldf.fill f77=[sp],16;; ldf.fill f76=[sp],16;; - ldf.fill f75=[sp],16;; ldf.fill f74=[sp],16;; ldf.fill f73=[sp],16;; ldf.fill f72=[sp],16;; - ldf.fill f71=[sp],16;; ldf.fill f70=[sp],16;; ldf.fill f69=[sp],16;; ldf.fill f68=[sp],16;; - ldf.fill f67=[sp],16;; ldf.fill f66=[sp],16;; ldf.fill f65=[sp],16;; ldf.fill f64=[sp],16;; - ldf.fill f63=[sp],16;; ldf.fill f62=[sp],16;; ldf.fill f61=[sp],16;; ldf.fill f60=[sp],16;; - ldf.fill f59=[sp],16;; ldf.fill f58=[sp],16;; ldf.fill f57=[sp],16;; ldf.fill f56=[sp],16;; - ldf.fill f55=[sp],16;; ldf.fill f54=[sp],16;; ldf.fill f53=[sp],16;; ldf.fill f52=[sp],16;; - ldf.fill f51=[sp],16;; ldf.fill f50=[sp],16;; ldf.fill f49=[sp],16;; ldf.fill f48=[sp],16;; - ldf.fill f47=[sp],16;; ldf.fill f46=[sp],16;; ldf.fill f45=[sp],16;; ldf.fill f44=[sp],16;; - ldf.fill f43=[sp],16;; ldf.fill f42=[sp],16;; ldf.fill f41=[sp],16;; ldf.fill f40=[sp],16;; - ldf.fill f39=[sp],16;; ldf.fill f38=[sp],16;; ldf.fill f37=[sp],16;; ldf.fill f36=[sp],16;; - ldf.fill f35=[sp],16;; ldf.fill f34=[sp],16;; ldf.fill f33=[sp],16;; ldf.fill f32=[sp],16;; - ldf.fill f31=[sp],16;; ldf.fill f30=[sp],16;; ldf.fill f29=[sp],16;; ldf.fill f28=[sp],16;; - ldf.fill f27=[sp],16;; ldf.fill f26=[sp],16;; ldf.fill f25=[sp],16;; ldf.fill f24=[sp],16;; - ldf.fill f23=[sp],16;; ldf.fill f22=[sp],16;; ldf.fill f21=[sp],16;; ldf.fill f20=[sp],16;; - ldf.fill f19=[sp],16;; ldf.fill f18=[sp],16;; ldf.fill f17=[sp],16;; ldf.fill f16=[sp],16;; - ldf.fill f15=[sp],16;; ldf.fill f14=[sp],16;; ldf.fill f13=[sp],16;; ldf.fill f12=[sp],16;; - ldf.fill f11=[sp],16;; ldf.fill f10=[sp],16;; ldf.fill f9=[sp],16;; ldf.fill f8=[sp],16;; - ldf.fill f7=[sp],16;; ldf.fill f6=[sp],16;; ldf.fill f5=[sp],16;; ldf.fill f4=[sp],16;; - ldf.fill f3=[sp],16;; ldf.fill f2=[sp],16;; - invala;; - br b7;; - -//----------------------------------------------------------------------------- -//++ -// EsalSetSalDataArea -// -// Register physical address of Esal Data Area -// -// On Entry : -// in0 = Reverse Thunk Address -// in1 = IntThunk Address -// -// Return Value: -// r8 = SAL_SUCCESS -// -// As per static calling conventions. -// -//-- -//--------------------------------------------------------------------------- - -PROCEDURE_ENTRY (EsalSetSalDataArea) - - NESTED_SETUP (4,8,0,0) - -EsalCalcStart1_3:: - mov r8 = ip;; - add r8 = (ReverseThunkAddress - EsalCalcStart1_3), r8;; - st8 [r8] = in0;; - -EsalCalcStart1_4:: - mov r8 = ip;; - add r8 = (IntThunkAddress - EsalCalcStart1_4), r8;; - st8 [r8] = in1;; - - mov r8 = r0;; - - NESTED_RETURN - -PROCEDURE_EXIT (EsalSetSalDataArea) - -//----------------------------------------------------------------------------- -//++ -// EsagGetReverseThunkAddress -// -// Register physical address of Esal Data Area -// -// On Entry : -// out0 = CodeStart -// out1 = CodeEnd -// out1 = ReverseThunkCode -// -// Return Value: -// r8 = SAL_SUCCESS -// -// As per static calling conventions. -// -//-- -//--------------------------------------------------------------------------- - -PROCEDURE_ENTRY (EsalGetReverseThunkAddress) - - NESTED_SETUP (4,8,0,0) - -EsalCalcStart1_31:: - mov r8 = ip;; - add r8 = (Ia32CodeStart - EsalCalcStart1_31), r8;; - mov r9 = r8;; - -EsalCalcStart1_41:: - mov r8 = ip;; - add r8 = (Ia32CodeEnd - EsalCalcStart1_41), r8;; - mov r10 = r8;; - -EsalCalcStart1_51:: - mov r8 = ip;; - add r8 = (ReverseThunkAddress - EsalCalcStart1_51), r8;; - mov r11 = r8;; - mov r8 = r0;; - - NESTED_RETURN - -PROCEDURE_EXIT (EsalGetReverseThunkAddress) - - -.align 16 -PROCEDURE_ENTRY (InterruptRedirectionTemplate) - data8 0x90CFCD08 - data8 0x90CFCD09 - data8 0x90CFCD0A - data8 0x90CFCD0B - data8 0x90CFCD0C - data8 0x90CFCD0D - data8 0x90CFCD0E - data8 0x90CFCD0F -PROCEDURE_EXIT (InterruptRedirectionTemplate) - -//------------------------------// -// Reverse Thunk Code // -//------------------------------// - -Ia32CodeStart:: - br.sptk.few Ia32CodeStart;; // IPF CSM integration -Bug (Write This Code) -ReverseThunkCode:: - data8 0xb80f66fa // CLI, JMPE xxxx -ReverseThunkAddress:: - data8 0 // Return Address -IntThunkAddress:: - data8 0 // IntThunk Address -Ia32CodeEnd:: - - - - diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c deleted file mode 100644 index e601bbd63b..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c +++ /dev/null @@ -1,550 +0,0 @@ -/** @file - Call into 16-bit BIOS code - - BugBug: Thunker does A20 gate. Can we get rid of this code or - put it into Legacy16 code. - -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 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 "LegacyBiosInterface.h" -#include "IpfThunk.h" - -/** - Gets the current flat GDT and IDT descriptors and store them in - Private->IntThunk. These values are used by the Thunk code. - This method must be called before every thunk in order to assure - that the correct GDT and IDT are restored after the thunk. - - @param Private Private context for Legacy BIOS - - @retval EFI_SUCCESS Should only pass. - -**/ -EFI_STATUS -LegacyBiosGetFlatDescs ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - return EFI_SUCCESS; -} - - -/** - BIOS interrupt call function. - - @param BiosInt Int number of BIOS call - @param Segment Segment number - @param Offset Offset in segment - @param Regs IA32 Register set. - @param Stack Base address of stack - @param StackSize Size of stack - - @retval EFI_SUCCESS BIOS interrupt call succeeds. - -**/ -EFI_STATUS -BiosIntCall ( - IN UINT16 BiosInt, - IN UINT16 Segment, - IN UINT16 Offset, - IN EFI_IA32_REGISTER_SET *Regs, - IN VOID *Stack, - IN UINTN StackSize - ) -{ - IPF_DWORD_REGS DwordRegs; - UINT64 IntTypeVariable; - - IntTypeVariable = 0x8000000000000000; - IntTypeVariable |= (UINT64)BiosInt; - - DwordRegs.Cs = Segment; - DwordRegs.Eip = Offset; - - DwordRegs.Ds = Regs->X.DS; - DwordRegs.Es = Regs->X.ES; - DwordRegs.Fs = Regs->X.ES; - DwordRegs.Gs = Regs->X.ES; - DwordRegs.Ss = 0xFFFF; - - DwordRegs.Eax = Regs->X.AX; - DwordRegs.Ebx = Regs->X.BX; - // - // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, AX = B10Dh is - // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to write. - // - DwordRegs.Ecx = Regs->E.ECX; - DwordRegs.Edx = Regs->X.DX; - - DwordRegs.Ebp = Regs->X.BP; - DwordRegs.Eflag = *((UINT16 *) &Regs->X.Flags); - - DwordRegs.Edi = Regs->X.DI; - DwordRegs.Esi = Regs->X.SI; - DwordRegs.Esp = 0xFFFFFFFF; - - EfiIaEntryPoint (IntTypeVariable, &DwordRegs, ((UINTN) Stack + StackSize), StackSize); - - Regs->X.CS = DwordRegs.Cs; - - Regs->X.DS = (UINT16) DwordRegs.Ds; - Regs->X.SS = (UINT16) DwordRegs.Ss; - - Regs->E.EAX = DwordRegs.Eax; - Regs->E.EBX = DwordRegs.Ebx; - Regs->E.ECX = DwordRegs.Ecx; - Regs->E.EDX = DwordRegs.Edx; - - Regs->E.EBP = DwordRegs.Ebp; - CopyMem (&Regs->X.Flags, &DwordRegs.Eflag, sizeof (EFI_FLAGS_REG)); - - Regs->E.EDI = DwordRegs.Edi; - Regs->E.ESI = DwordRegs.Esi; - - return EFI_SUCCESS; -} - - -/** - Template of real mode code. - - @param CodeStart Start address of code. - @param CodeEnd End address of code - @param ReverseThunkStart Start of reverse thunk. - @param IntThunk Low memory thunk. - -**/ -VOID -RealModeTemplate ( - OUT UINTN *CodeStart, - OUT UINTN *CodeEnd, - OUT UINTN *ReverseThunkStart, - LOW_MEMORY_THUNK *IntThunk - ) -{ - SAL_RETURN_REGS SalStatus; - - SalStatus = EsalGetReverseThunkAddress (); - - *CodeStart = SalStatus.r9; - *CodeEnd = SalStatus.r10; - *ReverseThunkStart = SalStatus.r11; - -} - - -/** - Allocate memory < 1 MB and copy the thunker code into low memory. Se up - all the descriptors. - - @param Private Private context for Legacy BIOS - - @retval EFI_SUCCESS Should only pass. - -**/ -EFI_STATUS -LegacyBiosInitializeThunk ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - GDT32 *CodeGdt; - GDT32 *DataGdt; - UINTN CodeStart; - UINTN CodeEnd; - UINTN ReverseThunkStart; - UINT32 Base; - LOW_MEMORY_THUNK *IntThunk; - UINTN TempData; - - ASSERT (Private); - - IntThunk = Private->IntThunk; - - // - // Clear the reserved descriptor - // - ZeroMem (&(IntThunk->RealModeGdt[0]), sizeof (GDT32)); - - // - // Setup a descriptor for real-mode code - // - CodeGdt = &(IntThunk->RealModeGdt[1]); - - // - // Fill in the descriptor with our real-mode segment value - // - CodeGdt->Type = 0xA; - // - // code/read - // - CodeGdt->System = 1; - CodeGdt->Dpl = 0; - CodeGdt->Present = 1; - CodeGdt->Software = 0; - CodeGdt->Reserved = 0; - CodeGdt->DefaultSize = 0; - // - // 16 bit operands - // - CodeGdt->Granularity = 0; - - CodeGdt->LimitHi = 0; - CodeGdt->LimitLo = 0xffff; - - Base = (*((UINT32 *) &IntThunk->Code)); - CodeGdt->BaseHi = (Base >> 24) & 0xFF; - CodeGdt->BaseMid = (Base >> 16) & 0xFF; - CodeGdt->BaseLo = Base & 0xFFFF; - - // - // Setup a descriptor for read-mode data - // - DataGdt = &(IntThunk->RealModeGdt[2]); - CopyMem (DataGdt, CodeGdt, sizeof (GDT32)); - - DataGdt->Type = 0x2; - // - // read/write data - // - DataGdt->BaseHi = 0x0; - // - // Base = 0 - // - DataGdt->BaseMid = 0x0; - // - DataGdt->BaseLo = 0x0; - // - DataGdt->LimitHi = 0x0F; - // - // Limit = 4Gb - // - DataGdt->LimitLo = 0xFFFF; - // - DataGdt->Granularity = 0x1; - // - // - // Compute selector value - // - IntThunk->RealModeGdtDesc.Limit = (UINT16) (sizeof (IntThunk->RealModeGdt) - 1); - CopyMem (&IntThunk->RealModeGdtDesc.Base, (UINT32 *) &IntThunk->RealModeGdt, sizeof (UINT32)); - // - // IntThunk->RealModeGdtDesc.Base = *((UINT32*) &IntThunk->RealModeGdt); - // - IntThunk->RealModeIdtDesc.Limit = 0xFFFF; - IntThunk->RealModeIdtDesc.Base = 0; - IntThunk->LowCodeSelector = (UINT32) ((UINTN) CodeGdt - IntThunk->RealModeGdtDesc.Base); - IntThunk->LowDataSelector = (UINT32) ((UINTN) DataGdt - IntThunk->RealModeGdtDesc.Base); - - // - // Initialize low real-mode code thunk - // - RealModeTemplate (&CodeStart, &CodeEnd, &ReverseThunkStart, IntThunk); - - TempData = (UINTN) &(IntThunk->Code); - IntThunk->LowReverseThunkStart = ((UINT32) TempData + (UINT32) (ReverseThunkStart - CodeStart)); - - EsalSetSalDataArea (TempData, (UINTN) IntThunk); - CopyMem (IntThunk->Code, (VOID *) CodeStart, CodeEnd - CodeStart); - - IntThunk->EfiToLegacy16InitTable.ReverseThunkCallSegment = EFI_SEGMENT (*((UINT32 *) &IntThunk->LowReverseThunkStart)); - IntThunk->EfiToLegacy16InitTable.ReverseThunkCallOffset = EFI_OFFSET (*((UINT32 *) &IntThunk->LowReverseThunkStart)); - - return EFI_SUCCESS; -} - - -/** - Thunk to 16-bit real mode and execute a software interrupt with a vector - of BiosInt. Regs will contain the 16-bit register context on entry and - exit. - - @param This Protocol instance pointer. - @param BiosInt Processor interrupt vector to invoke - @param Regs Register contexted passed into (and returned) from - thunk to 16-bit mode - - @retval FALSE Thunk completed, and there were no BIOS errors in the - target code. See Regs for status. - @retval TRUE There was a BIOS erro in the target code. - -**/ -BOOLEAN -EFIAPI -LegacyBiosInt86 ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT8 BiosInt, - IN EFI_IA32_REGISTER_SET *Regs - ) -{ - EFI_STATUS Status; - LEGACY_BIOS_INSTANCE *Private; - LOW_MEMORY_THUNK *IntThunk; - UINT16 *Stack16; - EFI_TPL OriginalTpl; - UINTN IaSegment; - UINTN IaOffset; - UINTN *Address; - UINTN TempData; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - IntThunk = Private->IntThunk; - - // - // Get the current flat GDT, IDT, and SS and store them in Private->IntThunk. - // - Status = LegacyBiosGetFlatDescs (Private); - ASSERT_EFI_ERROR (Status); - - Regs->X.Flags.Reserved1 = 1; - Regs->X.Flags.Reserved2 = 0; - Regs->X.Flags.Reserved3 = 0; - Regs->X.Flags.Reserved4 = 0; - Regs->X.Flags.IOPL = 3; - Regs->X.Flags.NT = 0; - Regs->X.Flags.IF = 1; - Regs->X.Flags.TF = 0; - Regs->X.Flags.CF = 0; - // - // Clear the error flag; thunk code may set it. - // - Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE); - - // - // Copy regs to low memory stack - // - Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); - CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET)); - - // - // Provide low stack esp - // - TempData = ((UINTN) Stack16) - ((UINTN) IntThunk); - IntThunk->LowStack = *((UINT32 *) &TempData); - - // - // Stack for reverse thunk flat mode. - // It must point to top of stack (end of stack space). - // - TempData = ((UINTN) IntThunk->RevThunkStack) + LOW_STACK_SIZE; - IntThunk->RevFlatStack = *((UINT32 *) &TempData); - - // - // The call to Legacy16 is a critical section to EFI - // - OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - // - // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. - // - Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - // - // Call the real mode thunk code - // - TempData = BiosInt * 4; - Address = (UINTN *) TempData; - IaOffset = 0xFFFF & (*Address); - IaSegment = 0xFFFF & ((*Address) >> 16); - - Status = BiosIntCall ( - BiosInt, - (UINT16) IaSegment, - (UINT16) IaOffset, - (EFI_IA32_REGISTER_SET *) Stack16, - IntThunk, - IntThunk->LowStack - ); - - // - // Check for errors with the thunk - // - switch (Status) { - case THUNK_OK: - break; - - case THUNK_ERR_A20_UNSUP: - case THUNK_ERR_A20_FAILED: - default: - // - // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error). - // - Regs->X.Flags.CF = 1; - break; - } - - Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - // - // End critical section - // - gBS->RestoreTPL (OriginalTpl); - - // - // Return the resulting registers - // - CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET)); - - return (BOOLEAN) (Regs->X.Flags.CF != 0); -} - - -/** - Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the - 16-bit register context on entry and exit. Arguments can be passed on - the Stack argument - - @param This Protocol instance pointer. - @param Segment Segemnt of 16-bit mode call - @param Offset Offset of 16-bit mdoe call - @param Regs Register contexted passed into (and returned) from - thunk to 16-bit mode - @param Stack Caller allocated stack used to pass arguments - @param StackSize Size of Stack in bytes - - @retval FALSE Thunk completed, and there were no BIOS errors in the - target code. See Regs for status. - @retval TRUE There was a BIOS erro in the target code. - -**/ -BOOLEAN -EFIAPI -LegacyBiosFarCall86 ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT16 Segment, - IN UINT16 Offset, - IN EFI_IA32_REGISTER_SET *Regs, - IN VOID *Stack, - IN UINTN StackSize - ) -{ - EFI_STATUS Status; - LEGACY_BIOS_INSTANCE *Private; - LOW_MEMORY_THUNK *IntThunk; - UINT16 *Stack16; - EFI_TPL OriginalTpl; - UINTN IaSegment; - UINTN IaOffset; - UINTN TempData; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - IntThunk = Private->IntThunk; - IaSegment = Segment; - IaOffset = Offset; - - // - // Get the current flat GDT and IDT and store them in Private->IntThunk. - // - Status = LegacyBiosGetFlatDescs (Private); - ASSERT_EFI_ERROR (Status); - - Regs->X.Flags.Reserved1 = 1; - Regs->X.Flags.Reserved2 = 0; - Regs->X.Flags.Reserved3 = 0; - Regs->X.Flags.Reserved4 = 0; - Regs->X.Flags.IOPL = 3; - Regs->X.Flags.NT = 0; - Regs->X.Flags.IF = 1; - Regs->X.Flags.TF = 0; - Regs->X.Flags.CF = 0; - // - // Clear the error flag; thunk code may set it. - // - Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE); - if (Stack != NULL && StackSize != 0) { - // - // Copy Stack to low memory stack - // - Stack16 -= StackSize / sizeof (UINT16); - CopyMem (Stack16, Stack, StackSize); - } - // - // Copy regs to low memory stack - // - Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); - CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET)); - - // - // Provide low stack esp - // - TempData = ((UINTN) Stack16) - ((UINTN) IntThunk); - IntThunk->LowStack = *((UINT32 *) &TempData); - - // - // The call to Legacy16 is a critical section to EFI - // - OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - // - // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. - // - Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - // - // Call the real mode thunk code - // - Status = BiosIntCall ( - 0x100, - (UINT16) IaSegment, - (UINT16) IaOffset, - (EFI_IA32_REGISTER_SET *) Stack16, - IntThunk, - IntThunk->LowStack - ); - - // - // Check for errors with the thunk - // - switch (Status) { - case THUNK_OK: - break; - - case THUNK_ERR_A20_UNSUP: - case THUNK_ERR_A20_FAILED: - default: - // - // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error). - // - Regs->X.Flags.CF = 1; - break; - } - // - // Restore protected mode interrupt state - // - Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - // - // End critical section - // - gBS->RestoreTPL (OriginalTpl); - - // - // Return the resulting registers - // - CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET)); - Stack16 += sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); - - if (Stack != NULL && StackSize != 0) { - // - // Copy low memory stack to Stack - // - CopyMem (Stack, Stack16, StackSize); - Stack16 += StackSize / sizeof (UINT16); - } - - return (BOOLEAN) (Regs->X.Flags.CF != 0); -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c deleted file mode 100644 index 6ee43ad676..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c +++ /dev/null @@ -1,384 +0,0 @@ -/** @file - -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 "LegacyBiosInterface.h" -#include - -// Give floppy 3 states -// FLOPPY_PRESENT_WITH_MEDIA = Floppy controller present and media is inserted -// FLOPPY_NOT_PRESENT = No floppy controller present -// FLOPPY_PRESENT_NO_MEDIA = Floppy controller present but no media inserted -// -#define FLOPPY_NOT_PRESENT 0 -#define FLOPPY_PRESENT_WITH_MEDIA 1 -#define FLOPPY_PRESENT_NO_MEDIA 2 - -BBS_TABLE *mBbsTable; -BOOLEAN mBbsTableDoneFlag = FALSE; -BOOLEAN IsHaveMediaInFloppy = TRUE; - -/** - Checks the state of the floppy and if media is inserted. - - This routine checks the state of the floppy and if media is inserted. - There are 3 cases: - No floppy present - Set BBS entry to ignore - Floppy present & no media - Set BBS entry to lowest priority. We cannot - set it to ignore since 16-bit CSM will - indicate no floppy and thus drive A: is - unusable. CSM-16 will not try floppy since - lowest priority and thus not incur boot - time penality. - Floppy present & media - Set BBS entry to some priority. - - @return State of floppy media - -**/ -UINT8 -HasMediaInFloppy ( - VOID - ) -{ - EFI_STATUS Status; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINTN Index; - EFI_ISA_IO_PROTOCOL *IsaIo; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - - HandleBuffer = NULL; - HandleCount = 0; - - gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiIsaIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - - // - // If don't find any ISA/IO protocol assume no floppy. Need for floppy - // free system - // - if (HandleCount == 0) { - return FLOPPY_NOT_PRESENT; - } - - ASSERT (HandleBuffer != NULL); - - for (Index = 0; Index < HandleCount; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo - ); - if (EFI_ERROR (Status)) { - continue; - } - - if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) { - continue; - } - // - // Update blockio in case the floppy is inserted in during BdsTimeout - // - Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); - - if (EFI_ERROR (Status)) { - continue; - } - - Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); - - if (EFI_ERROR (Status)) { - continue; - } - - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo - ); - if (EFI_ERROR (Status)) { - continue; - } - - if (BlkIo->Media->MediaPresent) { - FreePool (HandleBuffer); - return FLOPPY_PRESENT_WITH_MEDIA; - } else { - FreePool (HandleBuffer); - return FLOPPY_PRESENT_NO_MEDIA; - } - } - - FreePool (HandleBuffer); - - return FLOPPY_NOT_PRESENT; - -} - - -/** - Complete build of BBS TABLE. - - @param Private Legacy BIOS Instance data - @param BbsTable BBS Table passed to 16-bit code - - @retval EFI_SUCCESS Removable media not present - -**/ -EFI_STATUS -LegacyBiosBuildBbs ( - IN LEGACY_BIOS_INSTANCE *Private, - IN BBS_TABLE *BbsTable - ) -{ - UINTN BbsIndex; - HDD_INFO *HddInfo; - UINTN HddIndex; - UINTN Index; - - // - // First entry is floppy. - // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE. - // Next n entries are filled in after each ROM is dispatched. - // Entry filled in if follow BBS spec. See LegacyPci.c - // Next entries are for non-BBS compliant ROMS. They are filled in by - // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority - // occurs after that invocation. - // - // Floppy - // Set default state. - // - IsHaveMediaInFloppy = HasMediaInFloppy (); - if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) { - BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY; - } else { - if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) { - BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY; - } else { - BbsTable[0].BootPriority = BBS_IGNORE_ENTRY; - } - } - - BbsTable[0].Bus = 0xff; - BbsTable[0].Device = 0xff; - BbsTable[0].Function = 0xff; - BbsTable[0].DeviceType = BBS_FLOPPY; - BbsTable[0].Class = 01; - BbsTable[0].SubClass = 02; - BbsTable[0].StatusFlags.OldPosition = 0; - BbsTable[0].StatusFlags.Reserved1 = 0; - BbsTable[0].StatusFlags.Enabled = 0; - BbsTable[0].StatusFlags.Failed = 0; - BbsTable[0].StatusFlags.MediaPresent = 0; - BbsTable[0].StatusFlags.Reserved2 = 0; - - // - // Onboard HDD - Note Each HDD controller controls 2 drives - // Master & Slave - // - HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; - // - // Get IDE Drive Info - // - LegacyBiosBuildIdeData (Private, &HddInfo, 0); - - for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) { - - BbsIndex = HddIndex * 2 + 1; - for (Index = 0; Index < 2; ++Index) { - - BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus; - BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device; - BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function; - BbsTable[BbsIndex + Index].Class = 01; - BbsTable[BbsIndex + Index].SubClass = 01; - BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0; - BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0; - BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0; - BbsTable[BbsIndex + Index].StatusFlags.Failed = 0; - BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0; - BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0; - - // - // If no controller found or no device found set to ignore - // else set to unprioritized and set device type - // - if (HddInfo[HddIndex].CommandBaseAddress == 0) { - BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; - } else { - if (Index == 0) { - if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) { - BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; - if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) { - BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; - } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) { - BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; - } else { - // - // for ZIPDISK - // - BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; - } - } else { - BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; - } - } else { - if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) { - BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; - if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) { - BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; - } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) { - BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; - } else { - // - // for ZIPDISK - // - BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; - } - } else { - BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; - } - } - } - } - } - - return EFI_SUCCESS; - -} - - -/** - Get all BBS info - - @param This Protocol instance pointer. - @param HddCount Number of HDD_INFO structures - @param HddInfo Onboard IDE controller information - @param BbsCount Number of BBS_TABLE structures - @param BbsTable List BBS entries - - @retval EFI_SUCCESS Tables returned - @retval EFI_NOT_FOUND resource not found - @retval EFI_DEVICE_ERROR can not get BBS table - -**/ -EFI_STATUS -EFIAPI -LegacyBiosGetBbsInfo ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - OUT UINT16 *HddCount, - OUT HDD_INFO **HddInfo, - OUT UINT16 *BbsCount, - OUT BBS_TABLE **BbsTable - ) -{ - LEGACY_BIOS_INSTANCE *Private; - EFI_IA32_REGISTER_SET Regs; - EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; -// HDD_INFO *LocalHddInfo; -// IN BBS_TABLE *LocalBbsTable; - UINTN NumHandles; - EFI_HANDLE *HandleBuffer; - UINTN Index; - UINTN TempData; - UINT32 Granularity; - - HandleBuffer = NULL; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; -// LocalHddInfo = EfiToLegacy16BootTable->HddInfo; -// LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; - - if (!mBbsTableDoneFlag) { - mBbsTable = Private->BbsTablePtr; - - // - // Always enable disk controllers so 16-bit CSM code has valid information for all - // drives. - // - // - // Get PciRootBridgeIO protocol - // - gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciRootBridgeIoProtocolGuid, - NULL, - &NumHandles, - &HandleBuffer - ); - - if (NumHandles == 0) { - return EFI_NOT_FOUND; - } - - mBbsTableDoneFlag = TRUE; - for (Index = 0; Index < NumHandles; Index++) { - // - // Connect PciRootBridgeIO protocol handle with FALSE parameter to let - // PCI bus driver enumerate all subsequent handles - // - gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); - - } - - LegacyBiosBuildBbs (Private, mBbsTable); - - Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity); - - // - // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs. - // - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16UpdateBbs; - - // - // Pass in handoff data - // - TempData = (UINTN) EfiToLegacy16BootTable; - Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINT32) TempData); - Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINT32) TempData); - - Private->LegacyBios.FarCall86 ( - This, - Private->Legacy16CallSegment, - Private->Legacy16CallOffset, - &Regs, - NULL, - 0 - ); - - Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); - Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity); - - if (Regs.X.AX != 0) { - return EFI_DEVICE_ERROR; - } - } - - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - } - - *HddCount = MAX_IDE_CONTROLLER; - *HddInfo = EfiToLegacy16BootTable->HddInfo; - *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; - *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c deleted file mode 100644 index c45d5d4c3e..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c +++ /dev/null @@ -1,66 +0,0 @@ -/** @file - This code fills in BDA (0x400) and EBDA (pointed to by 0x4xx) - information. There is support for doing initializeation before - Legacy16 is loaded and before a legacy boot is attempted. - -Copyright (c) 2006 - 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 "LegacyBiosInterface.h" - -/** - Fill in the standard BDA and EBDA stuff before Legacy16 load - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosInitBda ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - BDA_STRUC *Bda; - UINT8 *Ebda; - - Bda = (BDA_STRUC *) ((UINTN) 0x400); - Ebda = (UINT8 *) ((UINTN) 0x9fc00); - - ZeroMem (Bda, 0x100); - ZeroMem (Ebda, 0x400); - // - // 640k-1k for EBDA - // - Bda->MemSize = 0x27f; - Bda->KeyHead = 0x1e; - Bda->KeyTail = 0x1e; - Bda->FloppyData = 0x00; - Bda->FloppyTimeout = 0xff; - - Bda->KeyStart = 0x001E; - Bda->KeyEnd = 0x003E; - Bda->KeyboardStatus = 0x10; - Bda->Ebda = 0x9fc0; - - // - // Move LPT time out here and zero out LPT4 since some SCSI OPROMS - // use this as scratch pad (LPT4 is Reserved) - // - Bda->Lpt1_2Timeout = 0x1414; - Bda->Lpt3_4Timeout = 0x1400; - - *Ebda = 0x01; - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c deleted file mode 100644 index dd2e2b9167..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c +++ /dev/null @@ -1,1154 +0,0 @@ -/** @file - -Copyright (c) 2006 - 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 "LegacyBiosInterface.h" - -#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address)) - -// -// define maximum number of HDD system supports -// -#define MAX_HDD_ENTRIES 0x30 - -// -// Module Global: -// Since this driver will only ever produce one instance of the Private Data -// protocol you are not required to dynamically allocate the PrivateData. -// -LEGACY_BIOS_INSTANCE mPrivateData; - -// -// The SMBIOS table in EfiRuntimeServicesData memory -// -VOID *mRuntimeSmbiosEntryPoint = NULL; - -// -// The SMBIOS table in EfiReservedMemoryType memory -// -EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint = 0; -EFI_PHYSICAL_ADDRESS mStructureTableAddress = 0; -UINTN mStructureTablePages = 0; - -/** - Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode - memory. - - @param AllocateType Allocated Legacy Memory Type - @param StartPageAddress Start address of range - @param Pages Number of pages to allocate - @param Result Result of allocation - - @retval EFI_SUCCESS Legacy16 code loaded - @retval Other No protocol installed, unload driver. - -**/ -EFI_STATUS -AllocateLegacyMemory ( - IN EFI_ALLOCATE_TYPE AllocateType, - IN EFI_PHYSICAL_ADDRESS StartPageAddress, - IN UINTN Pages, - OUT EFI_PHYSICAL_ADDRESS *Result - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS MemPage; - - // - // Allocate Pages of memory less <= StartPageAddress - // - MemPage = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPageAddress; - Status = gBS->AllocatePages ( - AllocateType, - EfiBootServicesCode, - Pages, - &MemPage - ); - // - // Do not ASSERT on Status error but let caller decide since some cases - // memory is already taken but that is ok. - // - if (!EFI_ERROR (Status)) { - *Result = (EFI_PHYSICAL_ADDRESS) (UINTN) MemPage; - } - // - // If reach here the status = EFI_SUCCESS - // - return Status; -} - - -/** - This function is called when EFI needs to reserve an area in the 0xE0000 or 0xF0000 - 64 KB blocks. - - Note: inconsistency with the Framework CSM spec. Per the spec, this function may be - invoked only once. This limitation is relaxed to allow multiple calls in this implemenation. - - @param This Protocol instance pointer. - @param LegacyMemorySize Size of required region - @param Region Region to use. 00 = Either 0xE0000 or 0xF0000 - block Bit0 = 1 0xF0000 block Bit1 = 1 0xE0000 - block - @param Alignment Address alignment. Bit mapped. First non-zero - bit from right is alignment. - @param LegacyMemoryAddress Region Assigned - - @retval EFI_SUCCESS Region assigned - @retval EFI_ACCESS_DENIED Procedure previously invoked - @retval Other Region not assigned - -**/ -EFI_STATUS -EFIAPI -LegacyBiosGetLegacyRegion ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINTN LegacyMemorySize, - IN UINTN Region, - IN UINTN Alignment, - OUT VOID **LegacyMemoryAddress - ) -{ - - LEGACY_BIOS_INSTANCE *Private; - EFI_IA32_REGISTER_SET Regs; - EFI_STATUS Status; - UINT32 Granularity; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity); - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16GetTableAddress; - Regs.X.BX = (UINT16) Region; - Regs.X.CX = (UINT16) LegacyMemorySize; - Regs.X.DX = (UINT16) Alignment; - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Private->Legacy16CallSegment, - Private->Legacy16CallOffset, - &Regs, - NULL, - 0 - ); - - if (Regs.X.AX == 0) { - *LegacyMemoryAddress = (VOID *) (UINTN) ((Regs.X.DS << 4) + Regs.X.BX); - Status = EFI_SUCCESS; - } else { - Status = EFI_OUT_OF_RESOURCES; - } - - Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); - Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity); - - return Status; -} - - -/** - This function is called when copying data to the region assigned by - EFI_LEGACY_BIOS_PROTOCOL.GetLegacyRegion(). - - @param This Protocol instance pointer. - @param LegacyMemorySize Size of data to copy - @param LegacyMemoryAddress Legacy Region destination address Note: must - be in region assigned by - LegacyBiosGetLegacyRegion - @param LegacyMemorySourceAddress Source of data - - @retval EFI_SUCCESS The data was copied successfully. - @retval EFI_ACCESS_DENIED Either the starting or ending address is out of bounds. -**/ -EFI_STATUS -EFIAPI -LegacyBiosCopyLegacyRegion ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINTN LegacyMemorySize, - IN VOID *LegacyMemoryAddress, - IN VOID *LegacyMemorySourceAddress - ) -{ - - LEGACY_BIOS_INSTANCE *Private; - UINT32 Granularity; - - if ((LegacyMemoryAddress < (VOID *)(UINTN)0xE0000 ) || - ((UINTN) LegacyMemoryAddress + LegacyMemorySize > (UINTN) 0x100000) - ) { - return EFI_ACCESS_DENIED; - } - // - // There is no protection from writes over lapping if this function is - // called multiple times. - // - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity); - CopyMem (LegacyMemoryAddress, LegacyMemorySourceAddress, LegacyMemorySize); - - Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); - Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity); - - return EFI_SUCCESS; -} - - -/** - Find Legacy16 BIOS image in the FLASH device and shadow it into memory. Find - the $EFI table in the shadow area. Thunk into the Legacy16 code after it had - been shadowed. - - @param Private Legacy BIOS context data - - @retval EFI_SUCCESS Legacy16 code loaded - @retval Other No protocol installed, unload driver. - -**/ -EFI_STATUS -ShadowAndStartLegacy16 ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_STATUS Status; - UINT8 *Ptr; - UINT8 *PtrEnd; - BOOLEAN Done; - EFI_COMPATIBILITY16_TABLE *Table; - UINT8 CheckSum; - EFI_IA32_REGISTER_SET Regs; - EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable; - EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; - VOID *LegacyBiosImage; - UINTN LegacyBiosImageSize; - UINTN E820Size; - UINT32 *ClearPtr; - BBS_TABLE *BbsTable; - LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable; - UINTN Index; - UINT32 TpmPointer; - VOID *TpmBinaryImage; - UINTN TpmBinaryImageSize; - UINTN Location; - UINTN Alignment; - UINTN TempData; - EFI_PHYSICAL_ADDRESS Address; - UINT16 OldMask; - UINT16 NewMask; - UINT32 Granularity; - EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; - - Location = 0; - Alignment = 0; - - // - // we allocate the C/D/E/F segment as RT code so no one will use it any more. - // - Address = 0xC0000; - gDS->GetMemorySpaceDescriptor (Address, &Descriptor); - if (Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) { - // - // If it is already reserved, we should be safe, or else we allocate it. - // - Status = gBS->AllocatePages ( - AllocateAddress, - EfiRuntimeServicesCode, - 0x40000/EFI_PAGE_SIZE, - &Address - ); - if (EFI_ERROR (Status)) { - // - // Bugbug: need to figure out whether C/D/E/F segment should be marked as reserved memory. - // - DEBUG ((DEBUG_ERROR, "Failed to allocate the C/D/E/F segment Status = %r", Status)); - } - } - - // - // start testtest - // GetTimerValue (&Ticker); - // - // gRT->SetVariable (L"StartLegacy", - // &gEfiGlobalVariableGuid, - // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - // sizeof (UINT64), - // (VOID *)&Ticker - // ); - // end testtest - // - EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; - Status = Private->LegacyBiosPlatform->GetPlatformInfo ( - Private->LegacyBiosPlatform, - EfiGetPlatformBinarySystemRom, - &LegacyBiosImage, - &LegacyBiosImageSize, - &Location, - &Alignment, - 0, - 0 - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Private->BiosStart = (UINT32) (0x100000 - LegacyBiosImageSize); - Private->OptionRom = 0xc0000; - Private->LegacyBiosImageSize = (UINT32) LegacyBiosImageSize; - - // - // Can only shadow into memory allocated for legacy useage. - // - ASSERT (Private->BiosStart > Private->OptionRom); - - // - // Shadow Legacy BIOS. Turn on memory and copy image - // - Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity); - - ClearPtr = (VOID *) ((UINTN) 0xc0000); - - // - // Initialize region from 0xc0000 to start of BIOS to all ffs. This allows unused - // regions to be used by EMM386 etc. - // - SetMem ((VOID *) ClearPtr, (UINTN) (0x40000 - LegacyBiosImageSize), 0xff); - - TempData = Private->BiosStart; - - CopyMem ( - (VOID *) TempData, - LegacyBiosImage, - (UINTN) LegacyBiosImageSize - ); - - Private->Cpu->FlushDataCache (Private->Cpu, 0xc0000, 0x40000, EfiCpuFlushTypeWriteBackInvalidate); - - // - // Search for Legacy16 table in Shadowed ROM - // - Done = FALSE; - Table = NULL; - for (Ptr = (UINT8 *) TempData; Ptr < (UINT8 *) ((UINTN) 0x100000) && !Done; Ptr += 0x10) { - if (*(UINT32 *) Ptr == SIGNATURE_32 ('I', 'F', 'E', '$')) { - Table = (EFI_COMPATIBILITY16_TABLE *) Ptr; - PtrEnd = Ptr + Table->TableLength; - for (CheckSum = 0; Ptr < PtrEnd; Ptr++) { - CheckSum = (UINT8) (CheckSum +*Ptr); - } - - Done = TRUE; - } - } - - if (Table == NULL) { - DEBUG ((EFI_D_ERROR, "No Legacy16 table found\n")); - return EFI_NOT_FOUND; - } - - if (!Done) { - // - // Legacy16 table header checksum error. - // - DEBUG ((EFI_D_ERROR, "Legacy16 table found with bad talbe header checksum\n")); - } - - // - // Remember location of the Legacy16 table - // - Private->Legacy16Table = Table; - Private->Legacy16CallSegment = Table->Compatibility16CallSegment; - Private->Legacy16CallOffset = Table->Compatibility16CallOffset; - EfiToLegacy16InitTable = &Private->IntThunk->EfiToLegacy16InitTable; - Private->Legacy16InitPtr = EfiToLegacy16InitTable; - Private->Legacy16BootPtr = &Private->IntThunk->EfiToLegacy16BootTable; - Private->InternalIrqRoutingTable = NULL; - Private->NumberIrqRoutingEntries = 0; - Private->BbsTablePtr = NULL; - Private->LegacyEfiHddTable = NULL; - Private->DiskEnd = 0; - Private->Disk4075 = 0; - Private->HddTablePtr = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo; - Private->NumberHddControllers = MAX_IDE_CONTROLLER; - Private->Dump[0] = 'D'; - Private->Dump[1] = 'U'; - Private->Dump[2] = 'M'; - Private->Dump[3] = 'P'; - - ZeroMem ( - Private->Legacy16BootPtr, - sizeof (EFI_TO_COMPATIBILITY16_BOOT_TABLE) - ); - - // - // Store away a copy of the EFI System Table - // - Table->EfiSystemTable = (UINT32) (UINTN) gST; - - // - // IPF CSM integration -Bug - // - // Construct the Legacy16 boot memory map. This sets up number of - // E820 entries. - // - LegacyBiosBuildE820 (Private, &E820Size); - // - // Initialize BDA and EBDA standard values needed to load Legacy16 code - // - LegacyBiosInitBda (Private); - LegacyBiosInitCmos (Private); - - // - // All legacy interrupt should be masked when do initialization work from legacy 16 code. - // - Private->Legacy8259->GetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL); - NewMask = 0xFFFF; - Private->Legacy8259->SetMask(Private->Legacy8259, &NewMask, NULL, NULL, NULL); - - // - // Call into Legacy16 code to do an INIT - // - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16InitializeYourself; - Regs.X.ES = EFI_SEGMENT (*((UINT32 *) &EfiToLegacy16InitTable)); - Regs.X.BX = EFI_OFFSET (*((UINT32 *) &EfiToLegacy16InitTable)); - - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Table->Compatibility16CallSegment, - Table->Compatibility16CallOffset, - &Regs, - NULL, - 0 - ); - - // - // Restore original legacy interrupt mask value - // - Private->Legacy8259->SetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL); - - if (Regs.X.AX != 0) { - return EFI_DEVICE_ERROR; - } - - // - // start testtest - // GetTimerValue (&Ticker); - // - // gRT->SetVariable (L"BackFromInitYourself", - // &gEfiGlobalVariableGuid, - // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - // sizeof (UINT64), - // (VOID *)&Ticker - // ); - // end testtest - // - // Copy E820 table after InitializeYourself is completed - // - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16GetTableAddress; - Regs.X.CX = (UINT16) E820Size; - Regs.X.DX = 1; - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Table->Compatibility16CallSegment, - Table->Compatibility16CallOffset, - &Regs, - NULL, - 0 - ); - - Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); - Table->E820Length = (UINT32) E820Size; - if (Regs.X.AX != 0) { - DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n")); - } else { - TempData = Table->E820Pointer; - CopyMem ((VOID *) TempData, Private->E820Table, E820Size); - } - // - // Get PnPInstallationCheck Info. - // - Private->PnPInstallationCheckSegment = Table->PnPInstallationCheckSegment; - Private->PnPInstallationCheckOffset = Table->PnPInstallationCheckOffset; - - // - // Check if PCI Express is supported. If yes, Save base address. - // - Status = Private->LegacyBiosPlatform->GetPlatformInfo ( - Private->LegacyBiosPlatform, - EfiGetPlatformPciExpressBase, - NULL, - NULL, - &Location, - &Alignment, - 0, - 0 - ); - if (!EFI_ERROR (Status)) { - Private->Legacy16Table->PciExpressBase = (UINT32)Location; - Location = 0; - } - // - // Check if TPM is supported. If yes get a region in E0000,F0000 to copy it - // into, copy it and update pointer to binary image. This needs to be - // done prior to any OPROM for security purposes. - // - Status = Private->LegacyBiosPlatform->GetPlatformInfo ( - Private->LegacyBiosPlatform, - EfiGetPlatformBinaryTpmBinary, - &TpmBinaryImage, - &TpmBinaryImageSize, - &Location, - &Alignment, - 0, - 0 - ); - if (!EFI_ERROR (Status)) { - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16GetTableAddress; - Regs.X.CX = (UINT16) TpmBinaryImageSize; - Regs.X.DX = 1; - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Table->Compatibility16CallSegment, - Table->Compatibility16CallOffset, - &Regs, - NULL, - 0 - ); - - TpmPointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); - if (Regs.X.AX != 0) { - DEBUG ((EFI_D_ERROR, "TPM cannot be loaded\n")); - } else { - CopyMem ((VOID *) (UINTN)TpmPointer, TpmBinaryImage, TpmBinaryImageSize); - Table->TpmSegment = Regs.X.DS; - Table->TpmOffset = Regs.X.BX; - - } - } - // - // Lock the Legacy BIOS region - // - Private->Cpu->FlushDataCache (Private->Cpu, Private->BiosStart, (UINT32) LegacyBiosImageSize, EfiCpuFlushTypeWriteBackInvalidate); - Private->LegacyRegion->Lock (Private->LegacyRegion, Private->BiosStart, (UINT32) LegacyBiosImageSize, &Granularity); - - // - // Get the BbsTable from LOW_MEMORY_THUNK - // - BbsTable = (BBS_TABLE *)(UINTN)Private->IntThunk->BbsTable; - ZeroMem ((VOID *)BbsTable, sizeof (Private->IntThunk->BbsTable)); - - EfiToLegacy16BootTable->BbsTable = (UINT32)(UINTN)BbsTable; - Private->BbsTablePtr = (VOID *) BbsTable; - // - // Skip Floppy and possible onboard IDE drives - // - EfiToLegacy16BootTable->NumberBbsEntries = 1 + 2 * MAX_IDE_CONTROLLER; - - for (Index = 0; Index < (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); Index++) { - BbsTable[Index].BootPriority = BBS_IGNORE_ENTRY; - } - // - // Allocate space for Legacy HDD table - // - LegacyEfiHddTable = (LEGACY_EFI_HDD_TABLE *) AllocateZeroPool ((UINTN) MAX_HDD_ENTRIES * sizeof (LEGACY_EFI_HDD_TABLE)); - ASSERT (LegacyEfiHddTable); - - Private->LegacyEfiHddTable = LegacyEfiHddTable; - Private->LegacyEfiHddTableIndex = 0x00; - - // - // start testtest - // GetTimerValue (&Ticker); - // - // gRT->SetVariable (L"EndOfLoadFv", - // &gEfiGlobalVariableGuid, - // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - // sizeof (UINT64), - // (VOID *)&Ticker - // ); - // end testtest - // - return EFI_SUCCESS; -} - -/** - Shadow all legacy16 OPROMs that haven't been shadowed. - Warning: Use this with caution. This routine disconnects all EFI - drivers. If used externally then caller must re-connect EFI - drivers. - - @param This Protocol instance pointer. - - @retval EFI_SUCCESS OPROMs shadowed - -**/ -EFI_STATUS -EFIAPI -LegacyBiosShadowAllLegacyOproms ( - IN EFI_LEGACY_BIOS_PROTOCOL *This - ) -{ - LEGACY_BIOS_INSTANCE *Private; - - // - // EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; - // EFI_LEGACY16_TABLE *Legacy16Table; - // - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - - // - // LegacyBiosPlatform = Private->LegacyBiosPlatform; - // Legacy16Table = Private->Legacy16Table; - // - // Shadow PCI ROMs. We must do this near the end since this will kick - // of Native EFI drivers that may be needed to collect info for Legacy16 - // - // WARNING: PciIo is gone after this call. - // - PciProgramAllInterruptLineRegisters (Private); - - PciShadowRoms (Private); - - // - // Shadow PXE base code, BIS etc. - // - // LegacyBiosPlatform->ShadowServiceRoms (LegacyBiosPlatform, - // &Private->OptionRom, - // Legacy16Table); - // - return EFI_SUCCESS; -} - -/** - Get the PCI BIOS interface version. - - @param Private Driver private data. - - @return The PCI interface version number in Binary Coded Decimal (BCD) format. - E.g.: 0x0210 indicates 2.10, 0x0300 indicates 3.00 - -**/ -UINT16 -GetPciInterfaceVersion ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_IA32_REGISTER_SET Reg; - BOOLEAN ThunkFailed; - UINT16 PciInterfaceVersion; - - PciInterfaceVersion = 0; - - Reg.X.AX = 0xB101; - Reg.E.EDI = 0; - - ThunkFailed = Private->LegacyBios.Int86 (&Private->LegacyBios, 0x1A, &Reg); - if (!ThunkFailed) { - // - // From PCI Firmware 3.0 Specification: - // If the CARRY FLAG [CF] is cleared and AH is set to 00h, it is still necessary to examine the - // contents of [EDX] for the presence of the string "PCI" + (trailing space) to fully validate the - // presence of the PCI function set. [BX] will further indicate the version level, with enough - // granularity to allow for incremental changes in the code that don't affect the function interface. - // Version numbers are stored as Binary Coded Decimal (BCD) values. For example, Version 2.10 - // would be returned as a 02h in the [BH] registers and 10h in the [BL] registers. - // - if ((Reg.X.Flags.CF == 0) && (Reg.H.AH == 0) && (Reg.E.EDX == SIGNATURE_32 ('P', 'C', 'I', ' '))) { - PciInterfaceVersion = Reg.X.BX; - } - } - return PciInterfaceVersion; -} - -/** - Callback function to calculate SMBIOS table size, and allocate memory for SMBIOS table. - SMBIOS table will be copied into EfiReservedMemoryType memory in legacy boot path. - - @param Event Event whose notification function is being invoked. - @param Context The pointer to the notification function's context, - which is implementation-dependent. - -**/ -VOID -EFIAPI -InstallSmbiosEventCallback ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; - - // - // Get SMBIOS table from EFI configuration table - // - Status = EfiGetSystemConfigurationTable ( - &gEfiSmbiosTableGuid, - &mRuntimeSmbiosEntryPoint - ); - if ((EFI_ERROR (Status)) || (mRuntimeSmbiosEntryPoint == NULL)) { - return; - } - - EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint; - - // - // Allocate memory for SMBIOS Entry Point Structure. - // CSM framework spec requires SMBIOS table below 4GB in EFI_TO_COMPATIBILITY16_BOOT_TABLE. - // - if (mReserveSmbiosEntryPoint == 0) { - // - // Entrypoint structure with fixed size is allocated only once. - // - mReserveSmbiosEntryPoint = SIZE_4GB - 1; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiReservedMemoryType, - EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)), - &mReserveSmbiosEntryPoint - ); - if (EFI_ERROR (Status)) { - mReserveSmbiosEntryPoint = 0; - return; - } - DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Entry Point Structure\n")); - } - - if ((mStructureTableAddress != 0) && - (mStructureTablePages < (UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength))) { - // - // If original buffer is not enough for the new SMBIOS table, free original buffer and re-allocate - // - gBS->FreePages (mStructureTableAddress, mStructureTablePages); - mStructureTableAddress = 0; - mStructureTablePages = 0; - DEBUG ((EFI_D_INFO, "Original size is not enough. Re-allocate the memory.\n")); - } - - if (mStructureTableAddress == 0) { - // - // Allocate reserved memory below 4GB. - // Smbios spec requires the structure table is below 4GB. - // - mStructureTableAddress = SIZE_4GB - 1; - mStructureTablePages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength); - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiReservedMemoryType, - mStructureTablePages, - &mStructureTableAddress - ); - if (EFI_ERROR (Status)) { - gBS->FreePages ( - mReserveSmbiosEntryPoint, - EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)) - ); - mReserveSmbiosEntryPoint = 0; - mStructureTableAddress = 0; - mStructureTablePages = 0; - return; - } - DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Structure Table\n")); - } -} - -/** - Install Driver to produce Legacy BIOS protocol. - - @param ImageHandle Handle of driver image. - @param SystemTable Pointer to system table. - - @retval EFI_SUCCESS Legacy BIOS protocol installed - @retval No protocol installed, unload driver. - -**/ -EFI_STATUS -EFIAPI -LegacyBiosInstall ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - LEGACY_BIOS_INSTANCE *Private; - EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable; - EFI_PHYSICAL_ADDRESS MemoryAddress; - EFI_PHYSICAL_ADDRESS EbdaReservedBaseAddress; - VOID *MemoryPtr; - EFI_PHYSICAL_ADDRESS MemoryAddressUnder1MB; - UINTN Index; - UINT32 *BaseVectorMaster; - EFI_PHYSICAL_ADDRESS StartAddress; - UINT32 *ClearPtr; - EFI_PHYSICAL_ADDRESS MemStart; - UINT32 IntRedirCode; - UINT32 Granularity; - BOOLEAN DecodeOn; - UINT32 MemorySize; - EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; - UINT64 Length; - UINT8 *SecureBoot; - EFI_EVENT InstallSmbiosEvent; - - // - // Load this driver's image to memory - // - Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // When UEFI Secure Boot is enabled, CSM module will not start any more. - // - SecureBoot = NULL; - GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL); - if ((SecureBoot != NULL) && (*SecureBoot == SECURE_BOOT_MODE_ENABLE)) { - FreePool (SecureBoot); - return EFI_SECURITY_VIOLATION; - } - - if (SecureBoot != NULL) { - FreePool (SecureBoot); - } - - Private = &mPrivateData; - ZeroMem (Private, sizeof (LEGACY_BIOS_INSTANCE)); - - // - // Grab a copy of all the protocols we depend on. Any error would - // be a dispatcher bug!. - // - Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Private->Cpu); - ASSERT_EFI_ERROR (Status); - - Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &Private->Timer); - ASSERT_EFI_ERROR (Status); - - Status = gBS->LocateProtocol (&gEfiLegacyRegion2ProtocolGuid, NULL, (VOID **) &Private->LegacyRegion); - ASSERT_EFI_ERROR (Status); - - Status = gBS->LocateProtocol (&gEfiLegacyBiosPlatformProtocolGuid, NULL, (VOID **) &Private->LegacyBiosPlatform); - ASSERT_EFI_ERROR (Status); - - Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &Private->Legacy8259); - ASSERT_EFI_ERROR (Status); - - Status = gBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, (VOID **) &Private->LegacyInterrupt); - ASSERT_EFI_ERROR (Status); - - // - // Locate Memory Test Protocol if exists - // - Status = gBS->LocateProtocol ( - &gEfiGenericMemTestProtocolGuid, - NULL, - (VOID **) &Private->GenericMemoryTest - ); - ASSERT_EFI_ERROR (Status); - - // - // Make sure all memory from 0-640K is tested - // - for (StartAddress = 0; StartAddress < 0xa0000; ) { - gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor); - if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) { - StartAddress = Descriptor.BaseAddress + Descriptor.Length; - continue; - } - Length = MIN (Descriptor.Length, 0xa0000 - StartAddress); - Private->GenericMemoryTest->CompatibleRangeTest ( - Private->GenericMemoryTest, - StartAddress, - Length - ); - StartAddress = StartAddress + Length; - } - // - // Make sure all memory from 1MB to 16MB is tested and added to memory map - // - for (StartAddress = BASE_1MB; StartAddress < BASE_16MB; ) { - gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor); - if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) { - StartAddress = Descriptor.BaseAddress + Descriptor.Length; - continue; - } - Length = MIN (Descriptor.Length, BASE_16MB - StartAddress); - Private->GenericMemoryTest->CompatibleRangeTest ( - Private->GenericMemoryTest, - StartAddress, - Length - ); - StartAddress = StartAddress + Length; - } - - Private->Signature = LEGACY_BIOS_INSTANCE_SIGNATURE; - - Private->LegacyBios.Int86 = LegacyBiosInt86; - Private->LegacyBios.FarCall86 = LegacyBiosFarCall86; - Private->LegacyBios.CheckPciRom = LegacyBiosCheckPciRom; - Private->LegacyBios.InstallPciRom = LegacyBiosInstallPciRom; - Private->LegacyBios.LegacyBoot = LegacyBiosLegacyBoot; - Private->LegacyBios.UpdateKeyboardLedStatus = LegacyBiosUpdateKeyboardLedStatus; - Private->LegacyBios.GetBbsInfo = LegacyBiosGetBbsInfo; - Private->LegacyBios.ShadowAllLegacyOproms = LegacyBiosShadowAllLegacyOproms; - Private->LegacyBios.PrepareToBootEfi = LegacyBiosPrepareToBootEfi; - Private->LegacyBios.GetLegacyRegion = LegacyBiosGetLegacyRegion; - Private->LegacyBios.CopyLegacyRegion = LegacyBiosCopyLegacyRegion; - Private->LegacyBios.BootUnconventionalDevice = LegacyBiosBootUnconventionalDevice; - - Private->ImageHandle = ImageHandle; - - // - // Enable read attribute of legacy region. - // - DecodeOn = TRUE; - Private->LegacyRegion->Decode ( - Private->LegacyRegion, - 0xc0000, - 0x40000, - &Granularity, - &DecodeOn - ); - // - // Set Cachebility for legacy region - // BUGBUG: Comments about this legacy region cacheability setting - // This setting will make D865GCHProduction CSM Unhappy - // - if (PcdGetBool (PcdLegacyBiosCacheLegacyRegion)) { - gDS->SetMemorySpaceAttributes ( - 0x0, - 0xA0000, - EFI_MEMORY_WB - ); - gDS->SetMemorySpaceAttributes ( - 0xc0000, - 0x40000, - EFI_MEMORY_WB - ); - } - - gDS->SetMemorySpaceAttributes ( - 0xA0000, - 0x20000, - EFI_MEMORY_UC - ); - - // - // Allocate 0 - 4K for real mode interupt vectors and BDA. - // - AllocateLegacyMemory ( - AllocateAddress, - 0, - 1, - &MemoryAddress - ); - ASSERT (MemoryAddress == 0x000000000); - - ClearPtr = (VOID *) ((UINTN) 0x0000); - - // - // Initialize region from 0x0000 to 4k. This initializes interrupt vector - // range. - // - gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K); - ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00); - - // - // Allocate pages for OPROM usage - // - MemorySize = PcdGet32 (PcdEbdaReservedMemorySize); - ASSERT ((MemorySize & 0xFFF) == 0); - - Status = AllocateLegacyMemory ( - AllocateAddress, - CONVENTIONAL_MEMORY_TOP - MemorySize, - EFI_SIZE_TO_PAGES (MemorySize), - &MemoryAddress - ); - ASSERT_EFI_ERROR (Status); - - ZeroMem ((VOID *) ((UINTN) MemoryAddress), MemorySize); - - // - // Allocate all 32k chunks from 0x60000 ~ 0x88000 for Legacy OPROMs that - // don't use PMM but look for zeroed memory. Note that various non-BBS - // OpROMs expect different areas to be free - // - EbdaReservedBaseAddress = MemoryAddress; - MemoryAddress = PcdGet32 (PcdOpromReservedMemoryBase); - MemorySize = PcdGet32 (PcdOpromReservedMemorySize); - // - // Check if base address and size for reserved memory are 4KB aligned. - // - ASSERT ((MemoryAddress & 0xFFF) == 0); - ASSERT ((MemorySize & 0xFFF) == 0); - // - // Check if the reserved memory is below EBDA reserved range. - // - ASSERT ((MemoryAddress < EbdaReservedBaseAddress) && ((MemoryAddress + MemorySize - 1) < EbdaReservedBaseAddress)); - for (MemStart = MemoryAddress; MemStart < MemoryAddress + MemorySize; MemStart += 0x1000) { - Status = AllocateLegacyMemory ( - AllocateAddress, - MemStart, - 1, - &StartAddress - ); - if (!EFI_ERROR (Status)) { - MemoryPtr = (VOID *) ((UINTN) StartAddress); - ZeroMem (MemoryPtr, 0x1000); - } else { - DEBUG ((EFI_D_ERROR, "WARNING: Allocate legacy memory fail for SCSI card - %x\n", MemStart)); - } - } - - // - // Allocate low PMM memory and zero it out - // - MemorySize = PcdGet32 (PcdLowPmmMemorySize); - ASSERT ((MemorySize & 0xFFF) == 0); - Status = AllocateLegacyMemory ( - AllocateMaxAddress, - CONVENTIONAL_MEMORY_TOP, - EFI_SIZE_TO_PAGES (MemorySize), - &MemoryAddressUnder1MB - ); - ASSERT_EFI_ERROR (Status); - - ZeroMem ((VOID *) ((UINTN) MemoryAddressUnder1MB), MemorySize); - - // - // Allocate space for thunker and Init Thunker - // - Status = AllocateLegacyMemory ( - AllocateMaxAddress, - CONVENTIONAL_MEMORY_TOP, - (sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 2, - &MemoryAddress - ); - ASSERT_EFI_ERROR (Status); - Private->IntThunk = (LOW_MEMORY_THUNK *) (UINTN) MemoryAddress; - EfiToLegacy16InitTable = &Private->IntThunk->EfiToLegacy16InitTable; - EfiToLegacy16InitTable->ThunkStart = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress; - EfiToLegacy16InitTable->ThunkSizeInBytes = (UINT32) (sizeof (LOW_MEMORY_THUNK)); - - Status = LegacyBiosInitializeThunk (Private); - ASSERT_EFI_ERROR (Status); - - // - // Init the legacy memory map in memory < 1 MB. - // - EfiToLegacy16InitTable->BiosLessThan1MB = (UINT32) MemoryAddressUnder1MB; - EfiToLegacy16InitTable->LowPmmMemory = (UINT32) MemoryAddressUnder1MB; - EfiToLegacy16InitTable->LowPmmMemorySizeInBytes = MemorySize; - - MemorySize = PcdGet32 (PcdHighPmmMemorySize); - ASSERT ((MemorySize & 0xFFF) == 0); - // - // Allocate high PMM Memory under 16 MB - // - Status = AllocateLegacyMemory ( - AllocateMaxAddress, - 0x1000000, - EFI_SIZE_TO_PAGES (MemorySize), - &MemoryAddress - ); - if (EFI_ERROR (Status)) { - // - // If it fails, allocate high PMM Memory under 4GB - // - Status = AllocateLegacyMemory ( - AllocateMaxAddress, - 0xFFFFFFFF, - EFI_SIZE_TO_PAGES (MemorySize), - &MemoryAddress - ); - } - if (!EFI_ERROR (Status)) { - EfiToLegacy16InitTable->HiPmmMemory = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress; - EfiToLegacy16InitTable->HiPmmMemorySizeInBytes = MemorySize; - } - - // - // ShutdownAPs(); - // - // Start the Legacy BIOS; - // - Status = ShadowAndStartLegacy16 (Private); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Initialize interrupt redirection code and entries; - // IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. - // - CopyMem ( - Private->IntThunk->InterruptRedirectionCode, - (VOID *) (UINTN) InterruptRedirectionTemplate, - sizeof (Private->IntThunk->InterruptRedirectionCode) - ); - - // - // Save Unexpected interrupt vector so can restore it just prior to boot - // - BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER); - Private->BiosUnexpectedInt = BaseVectorMaster[0]; - IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode; - for (Index = 0; Index < 8; Index++) { - BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4); - } - // - // Save EFI value - // - Private->ThunkSeg = (UINT16) (EFI_SEGMENT (IntRedirCode)); - - // - // Allocate reserved memory for SMBIOS table used in legacy boot if SMBIOS table exists - // - InstallSmbiosEventCallback (NULL, NULL); - - // - // Create callback function to update the size of reserved memory after LegacyBiosDxe starts - // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - InstallSmbiosEventCallback, - NULL, - &gEfiSmbiosTableGuid, - &InstallSmbiosEvent - ); - ASSERT_EFI_ERROR (Status); - - // - // Make a new handle and install the protocol - // - Private->Handle = NULL; - Status = gBS->InstallProtocolInterface ( - &Private->Handle, - &gEfiLegacyBiosProtocolGuid, - EFI_NATIVE_INTERFACE, - &Private->LegacyBios - ); - Private->Csm16PciInterfaceVersion = GetPciInterfaceVersion (Private); - - DEBUG ((EFI_D_INFO, "CSM16 PCI BIOS Interface Version: %02x.%02x\n", - (UINT8) (Private->Csm16PciInterfaceVersion >> 8), - (UINT8) Private->Csm16PciInterfaceVersion - )); - ASSERT (Private->Csm16PciInterfaceVersion != 0); - return Status; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf deleted file mode 100644 index f8cc4f3fc4..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf +++ /dev/null @@ -1,150 +0,0 @@ -## @file -# Legacy Bios Module to support CSM. -# -# This driver installs Legacy Bios Protocol to support CSM module work in EFI system. -# -# 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 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 = LegacyBiosDxe - MODULE_UNI_FILE = LegacyBiosDxe.uni - FILE_GUID = F122A15C-C10B-4d54-8F48-60F4F06DD1AD - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - - ENTRY_POINT = LegacyBiosInstall - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF -# - -[Sources] - LegacyCmos.c - LegacyIde.c - LegacyBios.c - LegacyBda.c - LegacyBiosInterface.h - LegacyPci.c - -[Sources.Ia32] - IA32/InterruptTable.S - IA32/InterruptTable.asm - Thunk.c - LegacyBootSupport.c - LegacyBbs.c - LegacySio.c - -[Sources.X64] - X64/InterruptTable.asm - X64/InterruptTable.S - Thunk.c - LegacyBootSupport.c - LegacyBbs.c - LegacySio.c - -[Sources.IPF] - Ipf/IpfThunk.s - Ipf/Thunk.c - Ipf/IpfThunk.i - Ipf/IpfBootSupport.c - Ipf/IpfThunk.h - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - - -[LibraryClasses] - DevicePathLib - UefiBootServicesTableLib - MemoryAllocationLib - UefiDriverEntryPoint - BaseMemoryLib - UefiLib - DebugLib - DxeServicesTableLib - PcdLib - ReportStatusCodeLib - PeCoffLib - CacheMaintenanceLib - DebugAgentLib - -[LibraryClasses.IA32] - IoLib - HobLib - UefiRuntimeServicesTableLib - BaseLib - -[LibraryClasses.X64] - IoLib - HobLib - UefiRuntimeServicesTableLib - BaseLib - -[LibraryClasses.IPF] - IoLib - UefiRuntimeServicesTableLib - - -[Guids] - gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_CONSUMES ##GUID #Used in LegacyBiosBuildIdeData() to assure device is a disk - gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ##SystemTable - gEfiLegacyBiosGuid ## SOMETIMES_CONSUMES ##GUID #Used in LegacyBiosInstallVgaRom() to locate handle buffer - -[Guids.IA32] - gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ##SystemTable - gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ##SystemTable - -[Guids.X64] - gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ##SystemTable - gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ##SystemTable - - -[Protocols] - gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES - gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES - gEfiPciRootBridgeIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiCpuArchProtocolGuid ## CONSUMES - gEfiTimerArchProtocolGuid ## CONSUMES - gEfiIsaIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiGenericMemTestProtocolGuid ## CONSUMES - gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES - gEfiSimpleTextInProtocolGuid ## SOMETIMES_CONSUMES - gEfiLegacy8259ProtocolGuid ## CONSUMES - gEfiLegacyBiosPlatformProtocolGuid ## CONSUMES - gEfiLegacyInterruptProtocolGuid ## CONSUMES - gEfiLegacyRegion2ProtocolGuid ## CONSUMES - gEfiLegacyBiosProtocolGuid ## PRODUCES - -[Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEndOpromShadowAddress ## SOMETIMES_CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize ## CONSUMES - -[Depex] - gEfiLegacyRegion2ProtocolGuid AND gEfiLegacyInterruptProtocolGuid AND gEfiLegacyBiosPlatformProtocolGuid AND gEfiLegacy8259ProtocolGuid AND gEfiGenericMemTestProtocolGuid AND gEfiCpuArchProtocolGuid AND gEfiTimerArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid - -[UserExtensions.TianoCore."ExtraFiles"] - LegacyBiosDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni deleted file mode 100644 index 30e995c2dc..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni deleted file mode 100644 index c62c69e3cd..0000000000 Binary files a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h deleted file mode 100644 index fcc0190d1e..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h +++ /dev/null @@ -1,1541 +0,0 @@ -/** @file - -Copyright (c) 2006 - 2015, Intel 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 _LEGACY_BIOS_INTERFACE_ -#define _LEGACY_BIOS_INTERFACE_ - - -#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 - -// -// BUGBUG: This entry maybe changed to PCD in future and wait for -// redesign of BDS library -// -#define MAX_BBS_ENTRIES 0x100 - -// -// Thunk Status Codes -// (These apply only to errors with the thunk and not to the code that was -// thunked to.) -// -#define THUNK_OK 0x00 -#define THUNK_ERR_A20_UNSUP 0x01 -#define THUNK_ERR_A20_FAILED 0x02 - -// -// Vector base definitions -// -// -// 8259 Hardware definitions -// -#define LEGACY_MODE_BASE_VECTOR_MASTER 0x08 -#define LEGACY_MODE_BASE_VECTOR_SLAVE 0x70 - -// -// The original PC used INT8-F for master PIC. Since these mapped over -// processor exceptions TIANO moved the master PIC to INT68-6F. -// -// The vector base for slave PIC is set as 0x70 for PC-AT compatibility. -// -#define PROTECTED_MODE_BASE_VECTOR_MASTER 0x68 -#define PROTECTED_MODE_BASE_VECTOR_SLAVE 0x70 - -// -// When we call CSM16 functions, some CSM16 use es:[offset + 0xabcd] to get data passed from CSM32, -// offset + 0xabcd could overflow which exceeds 0xFFFF which is invalid in real mode. -// So this will keep offset as small as possible to avoid offset overflow in real mode. -// -#define NORMALIZE_EFI_SEGMENT(_Adr) (UINT16) (((UINTN) (_Adr)) >> 4) -#define NORMALIZE_EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xf) - -// -// Trace defines -// -// -#define LEGACY_BDA_TRACE 0x000 -#define LEGACY_BIOS_TRACE 0x040 -#define LEGACY_BOOT_TRACE 0x080 -#define LEGACY_CMOS_TRACE 0x0C0 -#define LEGACY_IDE_TRACE 0x100 -#define LEGACY_MP_TRACE 0x140 -#define LEGACY_PCI_TRACE 0x180 -#define LEGACY_SIO_TRACE 0x1C0 - -#define LEGACY_PCI_TRACE_000 LEGACY_PCI_TRACE + 0x00 -#define LEGACY_PCI_TRACE_001 LEGACY_PCI_TRACE + 0x01 -#define LEGACY_PCI_TRACE_002 LEGACY_PCI_TRACE + 0x02 -#define LEGACY_PCI_TRACE_003 LEGACY_PCI_TRACE + 0x03 -#define LEGACY_PCI_TRACE_004 LEGACY_PCI_TRACE + 0x04 -#define LEGACY_PCI_TRACE_005 LEGACY_PCI_TRACE + 0x05 -#define LEGACY_PCI_TRACE_006 LEGACY_PCI_TRACE + 0x06 -#define LEGACY_PCI_TRACE_007 LEGACY_PCI_TRACE + 0x07 -#define LEGACY_PCI_TRACE_008 LEGACY_PCI_TRACE + 0x08 -#define LEGACY_PCI_TRACE_009 LEGACY_PCI_TRACE + 0x09 -#define LEGACY_PCI_TRACE_00A LEGACY_PCI_TRACE + 0x0A -#define LEGACY_PCI_TRACE_00B LEGACY_PCI_TRACE + 0x0B -#define LEGACY_PCI_TRACE_00C LEGACY_PCI_TRACE + 0x0C -#define LEGACY_PCI_TRACE_00D LEGACY_PCI_TRACE + 0x0D -#define LEGACY_PCI_TRACE_00E LEGACY_PCI_TRACE + 0x0E -#define LEGACY_PCI_TRACE_00F LEGACY_PCI_TRACE + 0x0F - -#define BDA_VIDEO_MODE 0x49 - -#define IDE_PI_REGISTER_PNE BIT0 -#define IDE_PI_REGISTER_SNE BIT2 - -typedef struct { - UINTN PciSegment; - UINTN PciBus; - UINTN PciDevice; - UINTN PciFunction; - UINT32 ShadowAddress; - UINT32 ShadowedSize; - UINT8 DiskStart; - UINT8 DiskEnd; -} ROM_INSTANCE_ENTRY; - -// -// Values for RealModeGdt -// -#if defined (MDE_CPU_IA32) - -#define NUM_REAL_GDT_ENTRIES 3 -#define CONVENTIONAL_MEMORY_TOP 0xA0000 // 640 KB -#define INITIAL_VALUE_BELOW_1K 0x0 - -#elif defined (MDE_CPU_X64) - -#define NUM_REAL_GDT_ENTRIES 8 -#define CONVENTIONAL_MEMORY_TOP 0xA0000 // 640 KB -#define INITIAL_VALUE_BELOW_1K 0x0 - -#elif defined (MDE_CPU_IPF) - -#define NUM_REAL_GDT_ENTRIES 3 -#define CONVENTIONAL_MEMORY_TOP 0x80000 // 512 KB -#define INITIAL_VALUE_BELOW_1K 0xff - -#endif - -#pragma pack(1) - -// -// Define what a processor GDT looks like -// -typedef struct { - UINT32 LimitLo : 16; - UINT32 BaseLo : 16; - UINT32 BaseMid : 8; - UINT32 Type : 4; - UINT32 System : 1; - UINT32 Dpl : 2; - UINT32 Present : 1; - UINT32 LimitHi : 4; - UINT32 Software : 1; - UINT32 Reserved : 1; - UINT32 DefaultSize : 1; - UINT32 Granularity : 1; - UINT32 BaseHi : 8; -} GDT32; - -typedef struct { - UINT16 LimitLow; - UINT16 BaseLow; - UINT8 BaseMid; - UINT8 Attribute; - UINT8 LimitHi; - UINT8 BaseHi; -} GDT64; - -// -// Define what a processor descriptor looks like -// This data structure must be kept in sync with ASM STRUCT in Thunk.inc -// -typedef struct { - UINT16 Limit; - UINT64 Base; -} DESCRIPTOR64; - -typedef struct { - UINT16 Limit; - UINT32 Base; -} DESCRIPTOR32; - -// -// Low stub lay out -// -#define LOW_STACK_SIZE (8 * 1024) // 8k? -#define EFI_MAX_E820_ENTRY 100 -#define FIRST_INSTANCE 1 -#define NOT_FIRST_INSTANCE 0 - -#if defined (MDE_CPU_IA32) -typedef struct { - // - // Space for the code - // The address of Code is also the beginning of the relocated Thunk code - // - CHAR8 Code[4096]; // ? - // - // The address of the Reverse Thunk code - // Note that this member CONTAINS the address of the relocated reverse thunk - // code unlike the member variable 'Code', which IS the address of the Thunk - // code. - // - UINT32 LowReverseThunkStart; - - // - // Data for the code (cs releative) - // - DESCRIPTOR32 GdtDesc; // Protected mode GDT - DESCRIPTOR32 IdtDesc; // Protected mode IDT - UINT32 FlatSs; - UINT32 FlatEsp; - - UINT32 LowCodeSelector; // Low code selector in GDT - UINT32 LowDataSelector; // Low data selector in GDT - UINT32 LowStack; - DESCRIPTOR32 RealModeIdtDesc; - - // - // real-mode GDT (temporary GDT with two real mode segment descriptors) - // - GDT32 RealModeGdt[NUM_REAL_GDT_ENTRIES]; - DESCRIPTOR32 RealModeGdtDesc; - - // - // Members specifically for the reverse thunk - // The RevReal* members are used to store the current state of real mode - // before performing the reverse thunk. The RevFlat* members must be set - // before calling the reverse thunk assembly code. - // - UINT16 RevRealDs; - UINT16 RevRealSs; - UINT32 RevRealEsp; - DESCRIPTOR32 RevRealIdtDesc; - UINT16 RevFlatDataSelector; // Flat data selector in GDT - UINT32 RevFlatStack; - - // - // A low memory stack - // - CHAR8 Stack[LOW_STACK_SIZE]; - - // - // Stack for flat mode after reverse thunk - // @bug - This may no longer be necessary if the reverse thunk interface - // is changed to have the flat stack in a different location. - // - CHAR8 RevThunkStack[LOW_STACK_SIZE]; - - // - // Legacy16 Init memory map info - // - EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable; - - EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable; - - CHAR8 InterruptRedirectionCode[32]; - EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; - EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; - BBS_TABLE BbsTable[MAX_BBS_ENTRIES]; -} LOW_MEMORY_THUNK; - -#elif defined (MDE_CPU_X64) - -typedef struct { - // - // Space for the code - // The address of Code is also the beginning of the relocated Thunk code - // - CHAR8 Code[4096]; // ? - - // - // Data for the code (cs releative) - // - DESCRIPTOR64 X64GdtDesc; // Protected mode GDT - DESCRIPTOR64 X64IdtDesc; // Protected mode IDT - UINTN X64Ss; - UINTN X64Esp; - - UINTN RealStack; - DESCRIPTOR32 RealModeIdtDesc; - DESCRIPTOR32 RealModeGdtDesc; - - // - // real-mode GDT (temporary GDT with two real mode segment descriptors) - // - GDT64 RealModeGdt[NUM_REAL_GDT_ENTRIES]; - UINT64 PageMapLevel4; - - // - // A low memory stack - // - CHAR8 Stack[LOW_STACK_SIZE]; - - // - // Legacy16 Init memory map info - // - EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable; - - EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable; - - CHAR8 InterruptRedirectionCode[32]; - EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; - EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; - BBS_TABLE BbsTable[MAX_BBS_ENTRIES]; -} LOW_MEMORY_THUNK; - -#elif defined (MDE_CPU_IPF) - -typedef struct { - // - // Space for the code - // The address of Code is also the beginning of the relocated Thunk code - // - CHAR8 Code[4096]; // ? - // - // The address of the Reverse Thunk code - // Note that this member CONTAINS the address of the relocated reverse thunk - // code unlike the member variable 'Code', which IS the address of the Thunk - // code. - // - UINT32 LowReverseThunkStart; - - // - // Data for the code (cs releative) - // - DESCRIPTOR32 GdtDesc; // Protected mode GDT - DESCRIPTOR32 IdtDesc; // Protected mode IDT - UINT32 FlatSs; - UINT32 FlatEsp; - - UINT32 LowCodeSelector; // Low code selector in GDT - UINT32 LowDataSelector; // Low data selector in GDT - UINT32 LowStack; - DESCRIPTOR32 RealModeIdtDesc; - - // - // real-mode GDT (temporary GDT with two real mode segment descriptors) - // - GDT32 RealModeGdt[NUM_REAL_GDT_ENTRIES]; - DESCRIPTOR32 RealModeGdtDesc; - - // - // Members specifically for the reverse thunk - // The RevReal* members are used to store the current state of real mode - // before performing the reverse thunk. The RevFlat* members must be set - // before calling the reverse thunk assembly code. - // - UINT16 RevRealDs; - UINT16 RevRealSs; - UINT32 RevRealEsp; - DESCRIPTOR32 RevRealIdtDesc; - UINT16 RevFlatDataSelector; // Flat data selector in GDT - UINT32 RevFlatStack; - - // - // A low memory stack - // - CHAR8 Stack[LOW_STACK_SIZE]; - - // - // Stack for flat mode after reverse thunk - // @bug - This may no longer be necessary if the reverse thunk interface - // is changed to have the flat stack in a different location. - // - CHAR8 RevThunkStack[LOW_STACK_SIZE]; - - // - // Legacy16 Init memory map info - // - EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable; - - EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable; - - CHAR8 InterruptRedirectionCode[32]; - EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; - EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; - BBS_TABLE BbsTable[MAX_BBS_ENTRIES]; -} LOW_MEMORY_THUNK; - -#endif - -// -// PnP Expansion Header -// -typedef struct { - UINT32 PnpSignature; - UINT8 Revision; - UINT8 Length; - UINT16 NextHeader; - UINT8 Reserved1; - UINT8 Checksum; - UINT32 DeviceId; - UINT16 MfgPointer; - UINT16 ProductNamePointer; - UINT8 Class; - UINT8 SubClass; - UINT8 Interface; - UINT8 DeviceIndicators; - UINT16 Bcv; - UINT16 DisconnectVector; - UINT16 Bev; - UINT16 Reserved2; - UINT16 StaticResourceVector; -} LEGACY_PNP_EXPANSION_HEADER; - -typedef struct { - UINT8 PciSegment; - UINT8 PciBus; - UINT8 PciDevice; - UINT8 PciFunction; - UINT16 Vid; - UINT16 Did; - UINT16 SysSid; - UINT16 SVid; - UINT8 Class; - UINT8 SubClass; - UINT8 Interface; - UINT8 Reserved; - UINTN RomStart; - UINTN ManufacturerString; - UINTN ProductNameString; -} LEGACY_ROM_AND_BBS_TABLE; - -// -// Structure how EFI has mapped a devices HDD drive numbers. -// Boot to EFI aware OS or shell requires this mapping when -// 16-bit CSM assigns drive numbers. -// This mapping is ignored booting to a legacy OS. -// -typedef struct { - UINT8 PciSegment; - UINT8 PciBus; - UINT8 PciDevice; - UINT8 PciFunction; - UINT8 StartDriveNumber; - UINT8 EndDriveNumber; -} LEGACY_EFI_HDD_TABLE; - -// -// This data is passed to Leacy16Boot -// -typedef enum { - EfiAcpiAddressRangeMemory = 1, - EfiAcpiAddressRangeReserved = 2, - EfiAcpiAddressRangeACPI = 3, - EfiAcpiAddressRangeNVS = 4, - EfiAddressRangePersistentMemory = 7 -} EFI_ACPI_MEMORY_TYPE; - -typedef struct { - UINT64 BaseAddr; - UINT64 Length; - EFI_ACPI_MEMORY_TYPE Type; -} EFI_E820_ENTRY64; - -typedef struct { - UINT32 BassAddrLow; - UINT32 BaseAddrHigh; - UINT32 LengthLow; - UINT32 LengthHigh; - EFI_ACPI_MEMORY_TYPE Type; -} EFI_E820_ENTRY; - -#pragma pack() - -extern BBS_TABLE *mBbsTable; - -extern EFI_GENERIC_MEMORY_TEST_PROTOCOL *gGenMemoryTest; - -#define PORT_70 0x70 -#define PORT_71 0x71 - -#define CMOS_0A 0x0a ///< Status register A -#define CMOS_0D 0x0d ///< Status register D -#define CMOS_0E 0x0e ///< Diagnostic Status -#define CMOS_0F 0x0f ///< Shutdown status -#define CMOS_10 0x10 ///< Floppy type -#define CMOS_12 0x12 ///< IDE type -#define CMOS_14 0x14 ///< Same as BDA 40:10 -#define CMOS_15 0x15 ///< Low byte of base memory in 1k increments -#define CMOS_16 0x16 ///< High byte of base memory in 1k increments -#define CMOS_17 0x17 ///< Low byte of 1MB+ memory in 1k increments - max 15 MB -#define CMOS_18 0x18 ///< High byte of 1MB+ memory in 1k increments - max 15 MB -#define CMOS_19 0x19 ///< C: extended drive type -#define CMOS_1A 0x1a ///< D: extended drive type -#define CMOS_2E 0x2e ///< Most significient byte of standard checksum -#define CMOS_2F 0x2f ///< Least significient byte of standard checksum -#define CMOS_30 0x30 ///< CMOS 0x17 -#define CMOS_31 0x31 ///< CMOS 0x18 -#define CMOS_32 0x32 ///< Century byte - -// -// 8254 Timer registers -// -#define TIMER0_COUNT_PORT 0x40 -#define TIMER1_COUNT_PORT 0x41 -#define TIMER2_COUNT_PORT 0x42 -#define TIMER_CONTROL_PORT 0x43 - -// -// Timer 0, Read/Write LSB then MSB, Square wave output, binary count use. -// -#define TIMER0_CONTROL_WORD 0x36 - -#define LEGACY_BIOS_INSTANCE_SIGNATURE SIGNATURE_32 ('L', 'B', 'I', 'T') -typedef struct { - UINTN Signature; - - EFI_HANDLE Handle; - EFI_LEGACY_BIOS_PROTOCOL LegacyBios; - - EFI_HANDLE ImageHandle; - - // - // CPU Architectural Protocol - // - EFI_CPU_ARCH_PROTOCOL *Cpu; - - // - // Timer Architectural Protocol - // - EFI_TIMER_ARCH_PROTOCOL *Timer; - BOOLEAN TimerUses8254; - - // - // Protocol to Lock and Unlock 0xc0000 - 0xfffff - // - EFI_LEGACY_REGION2_PROTOCOL *LegacyRegion; - - EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; - - // - // Interrupt control for thunk and PCI IRQ - // - EFI_LEGACY_8259_PROTOCOL *Legacy8259; - - // - // PCI Interrupt PIRQ control - // - EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt; - - // - // Generic Memory Test - // - EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenericMemoryTest; - - // - // TRUE if PCI Interupt Line registers have been programmed. - // - BOOLEAN PciInterruptLine; - - // - // Code space below 1MB needed by thunker to transition to real mode. - // Contains stack and real mode code fragments - // - LOW_MEMORY_THUNK *IntThunk; - - // - // Starting shadow address of the Legacy BIOS - // - UINT32 BiosStart; - UINT32 LegacyBiosImageSize; - - // - // Start of variables used by CsmItp.mac ITP macro file and/os LegacyBios - // - UINT8 Dump[4]; - - // - // $EFI Legacy16 code entry info in memory < 1 MB; - // - EFI_COMPATIBILITY16_TABLE *Legacy16Table; - VOID *Legacy16InitPtr; - VOID *Legacy16BootPtr; - VOID *InternalIrqRoutingTable; - UINT32 NumberIrqRoutingEntries; - VOID *BbsTablePtr; - VOID *HddTablePtr; - UINT32 NumberHddControllers; - - // - // Cached copy of Legacy16 entry point - // - UINT16 Legacy16CallSegment; - UINT16 Legacy16CallOffset; - - // - // Returned from $EFI and passed in to OPROMS - // - UINT16 PnPInstallationCheckSegment; - UINT16 PnPInstallationCheckOffset; - - // - // E820 table - // - EFI_E820_ENTRY E820Table[EFI_MAX_E820_ENTRY]; - UINT32 NumberE820Entries; - - // - // True if legacy VGA INT 10h handler installed - // - BOOLEAN VgaInstalled; - - // - // Number of IDE drives - // - UINT8 IdeDriveCount; - - // - // Current Free Option ROM space. An option ROM must NOT go past - // BiosStart. - // - UINT32 OptionRom; - - // - // Save Legacy16 unexpected interrupt vector. Reprogram INT 68-6F from - // EFI values to legacy value just before boot. - // - UINT32 BiosUnexpectedInt; - UINT32 ThunkSavedInt[8]; - UINT16 ThunkSeg; - LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable; - UINT16 LegacyEfiHddTableIndex; - UINT8 DiskEnd; - UINT8 Disk4075; - UINT16 TraceIndex; - UINT16 Trace[0x200]; - - // - // Indicate that whether GenericLegacyBoot is entered or not - // - BOOLEAN LegacyBootEntered; - - // - // CSM16 PCI Interface Version - // - UINT16 Csm16PciInterfaceVersion; - -} LEGACY_BIOS_INSTANCE; - - -#pragma pack(1) - -/* - 40:00-01 Com1 - 40:02-03 Com2 - 40:04-05 Com3 - 40:06-07 Com4 - 40:08-09 Lpt1 - 40:0A-0B Lpt2 - 40:0C-0D Lpt3 - 40:0E-0E Ebda segment - 40:10-11 MachineConfig - 40:12 Bda12 - skip - 40:13-14 MemSize below 1MB - 40:15-16 Bda15_16 - skip - 40:17 Keyboard Shift status - 40:18-19 Bda18_19 - skip - 40:1A-1B Key buffer head - 40:1C-1D Key buffer tail - 40:1E-3D Bda1E_3D- key buffer -skip - 40:3E-3F FloppyData 3E = Calibration status 3F = Motor status - 40:40 FloppyTimeout - 40:41-74 Bda41_74 - skip - 40:75 Number of HDD drives - 40:76-77 Bda76_77 - skip - 40:78-79 78 = Lpt1 timeout, 79 = Lpt2 timeout - 40:7A-7B 7A = Lpt3 timeout, 7B = Lpt4 timeout - 40:7C-7D 7C = Com1 timeout, 7D = Com2 timeout - 40:7E-7F 7E = Com3 timeout, 7F = Com4 timeout - 40:80-81 Pointer to start of key buffer - 40:82-83 Pointer to end of key buffer - 40:84-87 Bda84_87 - skip - 40:88 HDD Data Xmit rate - 40:89-8f skip - 40:90 Floppy data rate - 40:91-95 skip - 40:96 Keyboard Status - 40:97 LED Status - 40:98-101 skip -*/ -typedef struct { - UINT16 Com1; - UINT16 Com2; - UINT16 Com3; - UINT16 Com4; - UINT16 Lpt1; - UINT16 Lpt2; - UINT16 Lpt3; - UINT16 Ebda; - UINT16 MachineConfig; - UINT8 Bda12; - UINT16 MemSize; - UINT8 Bda15_16[0x02]; - UINT8 ShiftStatus; - UINT8 Bda18_19[0x02]; - UINT16 KeyHead; - UINT16 KeyTail; - UINT16 Bda1E_3D[0x10]; - UINT16 FloppyData; - UINT8 FloppyTimeout; - UINT8 Bda41_74[0x34]; - UINT8 NumberOfDrives; - UINT8 Bda76_77[0x02]; - UINT16 Lpt1_2Timeout; - UINT16 Lpt3_4Timeout; - UINT16 Com1_2Timeout; - UINT16 Com3_4Timeout; - UINT16 KeyStart; - UINT16 KeyEnd; - UINT8 Bda84_87[0x4]; - UINT8 DataXmit; - UINT8 Bda89_8F[0x07]; - UINT8 FloppyXRate; - UINT8 Bda91_95[0x05]; - UINT8 KeyboardStatus; - UINT8 LedStatus; -} BDA_STRUC; -#pragma pack() - -#define LEGACY_BIOS_INSTANCE_FROM_THIS(this) CR (this, LEGACY_BIOS_INSTANCE, LegacyBios, LEGACY_BIOS_INSTANCE_SIGNATURE) - -/** - Thunk to 16-bit real mode and execute a software interrupt with a vector - of BiosInt. Regs will contain the 16-bit register context on entry and - exit. - - @param This Protocol instance pointer. - @param BiosInt Processor interrupt vector to invoke - @param Regs Register contexted passed into (and returned) from thunk to - 16-bit mode - - @retval FALSE Thunk completed, and there were no BIOS errors in the target code. - See Regs for status. - @retval TRUE There was a BIOS erro in the target code. - -**/ -BOOLEAN -EFIAPI -LegacyBiosInt86 ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT8 BiosInt, - IN EFI_IA32_REGISTER_SET *Regs - ); - - -/** - Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the - 16-bit register context on entry and exit. Arguments can be passed on - the Stack argument - - @param This Protocol instance pointer. - @param Segment Segemnt of 16-bit mode call - @param Offset Offset of 16-bit mdoe call - @param Regs Register contexted passed into (and returned) from - thunk to 16-bit mode - @param Stack Caller allocated stack used to pass arguments - @param StackSize Size of Stack in bytes - - @retval FALSE Thunk completed, and there were no BIOS errors in - the target code. See Regs for status. - @retval TRUE There was a BIOS erro in the target code. - -**/ -BOOLEAN -EFIAPI -LegacyBiosFarCall86 ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT16 Segment, - IN UINT16 Offset, - IN EFI_IA32_REGISTER_SET *Regs, - IN VOID *Stack, - IN UINTN StackSize - ); - - -/** - Test to see if a legacy PCI ROM exists for this device. Optionally return - the Legacy ROM instance for this PCI device. - - @param This Protocol instance pointer. - @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will - be loaded - @param RomImage Return the legacy PCI ROM for this device - @param RomSize Size of ROM Image - @param Flags Indicates if ROM found and if PC-AT. - - @retval EFI_SUCCESS Legacy Option ROM availible for this device - @retval EFI_UNSUPPORTED Legacy Option ROM not supported. - -**/ -EFI_STATUS -EFIAPI -LegacyBiosCheckPciRom ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN EFI_HANDLE PciHandle, - OUT VOID **RomImage, OPTIONAL - OUT UINTN *RomSize, OPTIONAL - OUT UINTN *Flags - ); - - -/** - Assign drive number to legacy HDD drives prior to booting an EFI - aware OS so the OS can access drives without an EFI driver. - Note: BBS compliant drives ARE NOT available until this call by - either shell or EFI. - - @param This Protocol instance pointer. - @param BbsCount Number of BBS_TABLE structures - @param BbsTable List BBS entries - - @retval EFI_SUCCESS Drive numbers assigned - -**/ -EFI_STATUS -EFIAPI -LegacyBiosPrepareToBootEfi ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - OUT UINT16 *BbsCount, - OUT BBS_TABLE **BbsTable - ); - - -/** - To boot from an unconventional device like parties and/or execute - HDD diagnostics. - - @param This Protocol instance pointer. - @param Attributes How to interpret the other input parameters - @param BbsEntry The 0-based index into the BbsTable for the parent - device. - @param BeerData Pointer to the 128 bytes of ram BEER data. - @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. - The caller must provide a pointer to the specific - Service Area and not the start all Service Areas. - EFI_INVALID_PARAMETER if error. Does NOT return if no error. - -**/ -EFI_STATUS -EFIAPI -LegacyBiosBootUnconventionalDevice ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UDC_ATTRIBUTES Attributes, - IN UINTN BbsEntry, - IN VOID *BeerData, - IN VOID *ServiceAreaData - ); - - -/** - Load a legacy PC-AT OPROM on the PciHandle device. Return information - about how many disks were added by the OPROM and the shadow address and - size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: - - @param This Protocol instance pointer. - @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will - be loaded. This value is NULL if RomImage is - non-NULL. This is the normal case. - @param RomImage A PCI PC-AT ROM image. This argument is non-NULL - if there is no hardware associated with the ROM - and thus no PciHandle, otherwise is must be NULL. - Example is PXE base code. - @param Flags Indicates if ROM found and if PC-AT. - @param DiskStart Disk number of first device hooked by the ROM. If - DiskStart is the same as DiskEnd no disked were - hooked. - @param DiskEnd Disk number of the last device hooked by the ROM. - @param RomShadowAddress Shadow address of PC-AT ROM - @param RomShadowedSize Size of RomShadowAddress in bytes - - @retval EFI_SUCCESS Legacy ROM loaded for this device - @retval EFI_INVALID_PARAMETER PciHandle not found - @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no onboard - ROM - -**/ -EFI_STATUS -EFIAPI -LegacyBiosInstallPciRom ( - IN EFI_LEGACY_BIOS_PROTOCOL * This, - IN EFI_HANDLE PciHandle, - IN VOID **RomImage, - OUT UINTN *Flags, - OUT UINT8 *DiskStart, OPTIONAL - OUT UINT8 *DiskEnd, OPTIONAL - OUT VOID **RomShadowAddress, OPTIONAL - OUT UINT32 *RomShadowedSize OPTIONAL - ); - - -/** - Fill in the standard BDA for Keyboard LEDs - - @param This Protocol instance pointer. - @param Leds Current LED status - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -EFIAPI -LegacyBiosUpdateKeyboardLedStatus ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT8 Leds - ); - - -/** - Get all BBS info - - @param This Protocol instance pointer. - @param HddCount Number of HDD_INFO structures - @param HddInfo Onboard IDE controller information - @param BbsCount Number of BBS_TABLE structures - @param BbsTable List BBS entries - - @retval EFI_SUCCESS Tables returned - @retval EFI_NOT_FOUND resource not found - @retval EFI_DEVICE_ERROR can not get BBS table - -**/ -EFI_STATUS -EFIAPI -LegacyBiosGetBbsInfo ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - OUT UINT16 *HddCount, - OUT HDD_INFO **HddInfo, - OUT UINT16 *BbsCount, - OUT BBS_TABLE **BbsTable - ); - - -/** - Shadow all legacy16 OPROMs that haven't been shadowed. - Warning: Use this with caution. This routine disconnects all EFI - drivers. If used externally then caller must re-connect EFI - drivers. - - @param This Protocol instance pointer. - - @retval EFI_SUCCESS OPROMs shadowed - -**/ -EFI_STATUS -EFIAPI -LegacyBiosShadowAllLegacyOproms ( - IN EFI_LEGACY_BIOS_PROTOCOL *This - ); - - -/** - Attempt to legacy boot the BootOption. If the EFI contexted has been - compromised this function will not return. - - @param This Protocol instance pointer. - @param BbsDevicePath EFI Device Path from BootXXXX variable. - @param LoadOptionsSize Size of LoadOption in size. - @param LoadOptions LoadOption from BootXXXX variable - - @retval EFI_SUCCESS Removable media not present - -**/ -EFI_STATUS -EFIAPI -LegacyBiosLegacyBoot ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN BBS_BBS_DEVICE_PATH *BbsDevicePath, - IN UINT32 LoadOptionsSize, - IN VOID *LoadOptions - ); - - -/** - Allocate memory < 1 MB and copy the thunker code into low memory. Se up - all the descriptors. - - @param Private Private context for Legacy BIOS - - @retval EFI_SUCCESS Should only pass. - -**/ -EFI_STATUS -LegacyBiosInitializeThunk ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - Fill in the standard BDA and EBDA stuff before Legacy16 load - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosInitBda ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - Collect IDE Inquiry data from the IDE disks - - @param Private Legacy BIOS Instance data - @param HddInfo Hdd Information - @param Flag Reconnect IdeController or not - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosBuildIdeData ( - IN LEGACY_BIOS_INSTANCE *Private, - IN HDD_INFO **HddInfo, - IN UINT16 Flag - ); - - -/** - Enable ide controller. This gets disabled when LegacyBoot.c is about - to run the Option ROMs. - - @param Private Legacy BIOS Instance data - - -**/ -VOID -EnableIdeController ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - If the IDE channel is in compatibility (legacy) mode, remove all - PCI I/O BAR addresses from the controller. - - @param IdeController The handle of target IDE controller - - -**/ -VOID -InitLegacyIdeController ( - IN EFI_HANDLE IdeController - ); - - -/** - Program the interrupt routing register in all the PCI devices. On a PC AT system - this register contains the 8259 IRQ vector that matches it's PCI interrupt. - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS Succeed. - @retval EFI_ALREADY_STARTED All PCI devices have been processed. - -**/ -EFI_STATUS -PciProgramAllInterruptLineRegisters ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - Collect EFI Info about legacy devices. - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosBuildSioData ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol - to chose the order. Skip any devices that have already have legacy - BIOS run. - - @param Private Protocol instance pointer. - - @retval EFI_SUCCESS Succeed. - @retval EFI_UNSUPPORTED Cannot get VGA device handle. - -**/ -EFI_STATUS -PciShadowRoms ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - Fill in the standard BDA and EBDA stuff prior to legacy Boot - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosCompleteBdaBeforeBoot ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - Fill in the standard CMOS stuff before Legacy16 load - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosInitCmos ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - Fill in the standard CMOS stuff prior to legacy Boot - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosCompleteStandardCmosBeforeBoot ( - IN LEGACY_BIOS_INSTANCE *Private - ); - - -/** - Contains the code that is copied into low memory (below 640K). - This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. - This template must be copied into low memory, and the IDT entries - 0x68-0x6F must be point to the low memory copy of this code. Each - entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily - computed. - -**/ -VOID -InterruptRedirectionTemplate ( - VOID - ); - - -/** - Build the E820 table. - - @param Private Legacy BIOS Instance data - @param Size Size of E820 Table - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosBuildE820 ( - IN LEGACY_BIOS_INSTANCE *Private, - OUT UINTN *Size - ); - -/** - This function is to put all AP in halt state. - - @param Private Legacy BIOS Instance data - -**/ -VOID -ShutdownAPs ( - IN LEGACY_BIOS_INSTANCE *Private - ); - -/** - Worker function for LegacyBiosGetFlatDescs, retrieving content of - specific registers. - - @param IntThunk Pointer to IntThunk of Legacy BIOS context. - -**/ -VOID -GetRegisters ( - LOW_MEMORY_THUNK *IntThunk - ); - -/** - Routine for calling real thunk code. - - @param RealCode The address of thunk code. - @param BiosInt The Bios interrupt vector number. - @param CallAddress The address of 16-bit mode call. - - @return Status returned by real thunk code - -**/ -UINTN -CallRealThunkCode ( - UINT8 *RealCode, - UINT8 BiosInt, - UINT32 CallAddress - ); - -/** - Routine for generating soft interrupt. - - @param Vector The interrupt vector number. - -**/ -VOID -GenerateSoftInit ( - UINT8 Vector - ); - -/** - Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode - memory. - - @param AllocateType Allocated Legacy Memory Type - @param StartPageAddress Start address of range - @param Pages Number of pages to allocate - @param Result Result of allocation - - @retval EFI_SUCCESS Legacy16 code loaded - @retval Other No protocol installed, unload driver. - -**/ -EFI_STATUS -AllocateLegacyMemory ( - IN EFI_ALLOCATE_TYPE AllocateType, - IN EFI_PHYSICAL_ADDRESS StartPageAddress, - IN UINTN Pages, - OUT EFI_PHYSICAL_ADDRESS *Result - ); - -/** - Get a region from the LegacyBios for Tiano usage. Can only be invoked once. - - @param This Protocol instance pointer. - @param LegacyMemorySize Size of required region - @param Region Region to use. 00 = Either 0xE0000 or 0xF0000 - block Bit0 = 1 0xF0000 block Bit1 = 1 0xE0000 - block - @param Alignment Address alignment. Bit mapped. First non-zero - bit from right is alignment. - @param LegacyMemoryAddress Region Assigned - - @retval EFI_SUCCESS Region assigned - @retval EFI_ACCESS_DENIED Procedure previously invoked - @retval Other Region not assigned - -**/ -EFI_STATUS -EFIAPI -LegacyBiosGetLegacyRegion ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINTN LegacyMemorySize, - IN UINTN Region, - IN UINTN Alignment, - OUT VOID **LegacyMemoryAddress - ); - -/** - Get a region from the LegacyBios for Tiano usage. Can only be invoked once. - - @param This Protocol instance pointer. - @param LegacyMemorySize Size of data to copy - @param LegacyMemoryAddress Legacy Region destination address Note: must - be in region assigned by - LegacyBiosGetLegacyRegion - @param LegacyMemorySourceAddress Source of data - - @retval EFI_SUCCESS Region assigned - @retval EFI_ACCESS_DENIED Destination outside assigned region - -**/ -EFI_STATUS -EFIAPI -LegacyBiosCopyLegacyRegion ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINTN LegacyMemorySize, - IN VOID *LegacyMemoryAddress, - IN VOID *LegacyMemorySourceAddress - ); - -/** - Find Legacy16 BIOS image in the FLASH device and shadow it into memory. Find - the $EFI table in the shadow area. Thunk into the Legacy16 code after it had - been shadowed. - - @param Private Legacy BIOS context data - - @retval EFI_SUCCESS Legacy16 code loaded - @retval Other No protocol installed, unload driver. - -**/ -EFI_STATUS -ShadowAndStartLegacy16 ( - IN LEGACY_BIOS_INSTANCE *Private - ); - -/** - Checks the state of the floppy and if media is inserted. - - This routine checks the state of the floppy and if media is inserted. - There are 3 cases: - No floppy present - Set BBS entry to ignore - Floppy present & no media - Set BBS entry to lowest priority. We cannot - set it to ignore since 16-bit CSM will - indicate no floppy and thus drive A: is - unusable. CSM-16 will not try floppy since - lowest priority and thus not incur boot - time penality. - Floppy present & media - Set BBS entry to some priority. - - @return State of floppy media - -**/ -UINT8 -HasMediaInFloppy ( - VOID - ); - -/** - Identify drive data must be updated to actual parameters before boot. - This requires updating the checksum, if it exists. - - @param IdentifyDriveData ATA Identify Data - @param Checksum checksum of the ATA Identify Data - - @retval EFI_SUCCESS checksum calculated - @retval EFI_SECURITY_VIOLATION IdentifyData invalid - -**/ -EFI_STATUS -CalculateIdentifyDriveChecksum ( - IN UINT8 *IdentifyDriveData, - OUT UINT8 *Checksum - ); - -/** - Identify drive data must be updated to actual parameters before boot. - - @param IdentifyDriveData ATA Identify Data - -**/ -VOID -UpdateIdentifyDriveData ( - IN UINT8 *IdentifyDriveData - ); - -/** - Complete build of BBS TABLE. - - @param Private Legacy BIOS Instance data - @param BbsTable BBS Table passed to 16-bit code - - @retval EFI_SUCCESS Removable media not present - -**/ -EFI_STATUS -LegacyBiosBuildBbs ( - IN LEGACY_BIOS_INSTANCE *Private, - IN BBS_TABLE *BbsTable - ); - -/** - Read CMOS register through index/data port. - - @param[in] Index The index of the CMOS register to read. - - @return The data value from the CMOS register specified by Index. - -**/ -UINT8 -LegacyReadStandardCmos ( - IN UINT8 Index - ); - -/** - Write CMOS register through index/data port. - - @param[in] Index The index of the CMOS register to write. - @param[in] Value The value of CMOS register to write. - - @return The value written to the CMOS register specified by Index. - -**/ -UINT8 -LegacyWriteStandardCmos ( - IN UINT8 Index, - IN UINT8 Value - ); - -/** - Calculate the new standard CMOS checksum and write it. - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS Calculate 16-bit checksum successfully - -**/ -EFI_STATUS -LegacyCalculateWriteStandardCmosChecksum ( - VOID - ); - -/** - Test to see if a legacy PCI ROM exists for this device. Optionally return - the Legacy ROM instance for this PCI device. - - @param[in] This Protocol instance pointer. - @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded - @param[out] RomImage Return the legacy PCI ROM for this device - @param[out] RomSize Size of ROM Image - @param[out] RuntimeImageLength Runtime size of ROM Image - @param[out] Flags Indicates if ROM found and if PC-AT. - @param[out] OpromRevision Revision of the PCI Rom - @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header - - @return EFI_SUCCESS Legacy Option ROM availible for this device - @return EFI_ALREADY_STARTED This device is already managed by its Oprom - @return EFI_UNSUPPORTED Legacy Option ROM not supported. - -**/ -EFI_STATUS -LegacyBiosCheckPciRomEx ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN EFI_HANDLE PciHandle, - OUT VOID **RomImage, OPTIONAL - OUT UINTN *RomSize, OPTIONAL - OUT UINTN *RuntimeImageLength, OPTIONAL - OUT UINTN *Flags, OPTIONAL - OUT UINT8 *OpromRevision, OPTIONAL - OUT VOID **ConfigUtilityCodeHeader OPTIONAL - ); - -/** - Relocate this image under 4G memory for IPF. - - @param ImageHandle Handle of driver image. - @param SystemTable Pointer to system table. - - @retval EFI_SUCCESS Image successfully relocated. - @retval EFI_ABORTED Failed to relocate image. - -**/ -EFI_STATUS -RelocateImageUnder4GIfNeeded ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); - -/** - Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the - 16-bit register context on entry and exit. Arguments can be passed on - the Stack argument - - @param This Protocol instance pointer. - @param Segment Segemnt of 16-bit mode call - @param Offset Offset of 16-bit mdoe call - @param Regs Register contexted passed into (and returned) from thunk to - 16-bit mode - @param Stack Caller allocated stack used to pass arguments - @param StackSize Size of Stack in bytes - - @retval FALSE Thunk completed, and there were no BIOS errors in the target code. - See Regs for status. - @retval TRUE There was a BIOS erro in the target code. - -**/ -BOOLEAN -EFIAPI -InternalLegacyBiosFarCall ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT16 Segment, - IN UINT16 Offset, - IN EFI_IA32_REGISTER_SET *Regs, - IN VOID *Stack, - IN UINTN StackSize - ); - -/** - Load a legacy PC-AT OpROM for VGA controller. - - @param Private Driver private data. - - @retval EFI_SUCCESS Legacy ROM successfully installed for this device. - @retval EFI_DEVICE_ERROR No VGA device handle found, or native EFI video - driver cannot be successfully disconnected, or VGA - thunk driver cannot be successfully connected. - -**/ -EFI_STATUS -LegacyBiosInstallVgaRom ( - IN LEGACY_BIOS_INSTANCE *Private - ); - -#endif diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c deleted file mode 100644 index 52bcae2d13..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c +++ /dev/null @@ -1,2165 +0,0 @@ -/** @file - -Copyright (c) 2006 - 2015, Intel 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 "LegacyBiosInterface.h" -#include - -#define BOOT_LEGACY_OS 0 -#define BOOT_EFI_OS 1 -#define BOOT_UNCONVENTIONAL_DEVICE 2 - -UINT32 mLoadOptionsSize = 0; -UINTN mBootMode = BOOT_LEGACY_OS; -VOID *mLoadOptions = NULL; -BBS_BBS_DEVICE_PATH *mBbsDevicePathPtr = NULL; -BBS_BBS_DEVICE_PATH mBbsDevicePathNode; -UDC_ATTRIBUTES mAttributes = { 0, 0, 0, 0 }; -UINTN mBbsEntry = 0; -VOID *mBeerData = NULL; -VOID *mServiceAreaData = NULL; -UINT64 mLowWater = 0xffffffffffffffffULL; - -extern BBS_TABLE *mBbsTable; - -extern VOID *mRuntimeSmbiosEntryPoint; -extern EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint; -extern EFI_PHYSICAL_ADDRESS mStructureTableAddress; - -/** - Print the BBS Table. - - @param BbsTable The BBS table. - - -**/ -VOID -PrintBbsTable ( - IN BBS_TABLE *BbsTable - ) -{ - UINT16 Index; - UINT16 SubIndex; - CHAR8 *String; - - DEBUG ((EFI_D_INFO, "\n")); - DEBUG ((EFI_D_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs mfgs:mfgo dess:deso\n")); - DEBUG ((EFI_D_INFO, "=================================================================\n")); - for (Index = 0; Index < MAX_BBS_ENTRIES; Index++) { - // - // Filter - // - if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) { - continue; - } - - DEBUG (( - EFI_D_INFO, - " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x", - (UINTN) Index, - (UINTN) BbsTable[Index].BootPriority, - (UINTN) BbsTable[Index].Bus, - (UINTN) BbsTable[Index].Device, - (UINTN) BbsTable[Index].Function, - (UINTN) BbsTable[Index].Class, - (UINTN) BbsTable[Index].SubClass, - (UINTN) BbsTable[Index].DeviceType, - (UINTN) * (UINT16 *) &BbsTable[Index].StatusFlags - )); - DEBUG (( - EFI_D_INFO, - " %04x:%04x %04x:%04x %04x:%04x", - (UINTN) BbsTable[Index].BootHandlerSegment, - (UINTN) BbsTable[Index].BootHandlerOffset, - (UINTN) BbsTable[Index].MfgStringSegment, - (UINTN) BbsTable[Index].MfgStringOffset, - (UINTN) BbsTable[Index].DescStringSegment, - (UINTN) BbsTable[Index].DescStringOffset - )); - - // - // Print DescString - // - String = (CHAR8 *)(UINTN)((BbsTable[Index].DescStringSegment << 4) + BbsTable[Index].DescStringOffset); - if (String != NULL) { - DEBUG ((EFI_D_INFO," (")); - for (SubIndex = 0; String[SubIndex] != 0; SubIndex++) { - DEBUG ((EFI_D_INFO, "%c", String[SubIndex])); - } - DEBUG ((EFI_D_INFO,")")); - } - DEBUG ((EFI_D_INFO,"\n")); - } - - DEBUG ((EFI_D_INFO, "\n")); - - return ; -} - -/** - Print the BBS Table. - - @param HddInfo The HddInfo table. - - -**/ -VOID -PrintHddInfo ( - IN HDD_INFO *HddInfo - ) -{ - UINTN Index; - - DEBUG ((EFI_D_INFO, "\n")); - for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) { - DEBUG ((EFI_D_INFO, "Index - %04x\n", Index)); - DEBUG ((EFI_D_INFO, " Status - %04x\n", (UINTN)HddInfo[Index].Status)); - DEBUG ((EFI_D_INFO, " B/D/F - %02x/%02x/%02x\n", (UINTN)HddInfo[Index].Bus, (UINTN)HddInfo[Index].Device, (UINTN)HddInfo[Index].Function)); - DEBUG ((EFI_D_INFO, " Command - %04x\n", HddInfo[Index].CommandBaseAddress)); - DEBUG ((EFI_D_INFO, " Control - %04x\n", HddInfo[Index].ControlBaseAddress)); - DEBUG ((EFI_D_INFO, " BusMaster - %04x\n", HddInfo[Index].BusMasterAddress)); - DEBUG ((EFI_D_INFO, " HddIrq - %02x\n", HddInfo[Index].HddIrq)); - DEBUG ((EFI_D_INFO, " IdentifyDrive[0].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[0].Raw[0])); - DEBUG ((EFI_D_INFO, " IdentifyDrive[1].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[1].Raw[0])); - } - - DEBUG ((EFI_D_INFO, "\n")); - - return ; -} - -/** - Print the PCI Interrupt Line and Interrupt Pin registers. -**/ -VOID -PrintPciInterruptRegister ( - VOID - ) -{ - EFI_STATUS Status; - UINTN Index; - EFI_HANDLE *Handles; - UINTN HandleNum; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT8 Interrupt[2]; - UINTN Segment; - UINTN Bus; - UINTN Device; - UINTN Function; - - gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleNum, - &Handles - ); - - Bus = 0; - Device = 0; - Function = 0; - - DEBUG ((EFI_D_INFO, "\n")); - DEBUG ((EFI_D_INFO, " bb/dd/ff interrupt line interrupt pin\n")); - DEBUG ((EFI_D_INFO, "======================================\n")); - for (Index = 0; Index < HandleNum; Index++) { - Status = gBS->HandleProtocol (Handles[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo); - if (!EFI_ERROR (Status)) { - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint8, - PCI_INT_LINE_OFFSET, - 2, - Interrupt - ); - } - if (!EFI_ERROR (Status)) { - Status = PciIo->GetLocation ( - PciIo, - &Segment, - &Bus, - &Device, - &Function - ); - } - if (!EFI_ERROR (Status)) { - DEBUG ((EFI_D_INFO, " %02x/%02x/%02x 0x%02x 0x%02x\n", - Bus, Device, Function, Interrupt[0], Interrupt[1])); - } - } - DEBUG ((EFI_D_INFO, "\n")); - - if (Handles != NULL) { - FreePool (Handles); - } -} - -/** - Identify drive data must be updated to actual parameters before boot. - - @param IdentifyDriveData ATA Identify Data - -**/ -VOID -UpdateIdentifyDriveData ( - IN UINT8 *IdentifyDriveData - ); - -/** - Update SIO data. - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS Removable media not present - -**/ -EFI_STATUS -UpdateSioData ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN Index1; - UINT8 LegacyInterrupts[16]; - EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable; - UINTN RoutingTableEntries; - EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY *IrqPriorityTable; - UINTN NumberPriorityEntries; - EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; - UINT8 HddIrq; - UINT16 LegacyInt; - UINT16 LegMask; - UINT32 Register; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - EFI_ISA_IO_PROTOCOL *IsaIo; - - LegacyInt = 0; - HandleBuffer = NULL; - - EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; - LegacyBiosBuildSioData (Private); - SetMem (LegacyInterrupts, sizeof (LegacyInterrupts), 0); - - // - // Create list of legacy interrupts. - // - for (Index = 0; Index < 4; Index++) { - LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Serial[Index].Irq; - } - - for (Index = 4; Index < 7; Index++) { - LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Parallel[Index - 4].Irq; - } - - LegacyInterrupts[7] = EfiToLegacy16BootTable->SioData.Floppy.Irq; - - // - // Get Legacy Hdd IRQs. If native mode treat as PCI - // - for (Index = 0; Index < 2; Index++) { - HddIrq = EfiToLegacy16BootTable->HddInfo[Index].HddIrq; - if ((HddIrq != 0) && ((HddIrq == 15) || (HddIrq == 14))) { - LegacyInterrupts[Index + 8] = HddIrq; - } - } - - Private->LegacyBiosPlatform->GetRoutingTable ( - Private->LegacyBiosPlatform, - (VOID *) &RoutingTable, - &RoutingTableEntries, - NULL, - NULL, - (VOID **) &IrqPriorityTable, - &NumberPriorityEntries - ); - // - // Remove legacy interrupts from the list of PCI interrupts available. - // - for (Index = 0; Index <= 0x0b; Index++) { - for (Index1 = 0; Index1 <= NumberPriorityEntries; Index1++) { - if (LegacyInterrupts[Index] != 0) { - LegacyInt = (UINT16) (LegacyInt | (1 << LegacyInterrupts[Index])); - if (LegacyInterrupts[Index] == IrqPriorityTable[Index1].Irq) { - IrqPriorityTable[Index1].Used = LEGACY_USED; - } - } - } - } - - Private->Legacy8259->GetMask ( - Private->Legacy8259, - &LegMask, - NULL, - NULL, - NULL - ); - - // - // Set SIO interrupts and disable mouse. Let mouse driver - // re-enable it. - // - LegMask = (UINT16) ((LegMask &~LegacyInt) | 0x1000); - Private->Legacy8259->SetMask ( - Private->Legacy8259, - &LegMask, - NULL, - NULL, - NULL - ); - - // - // Disable mouse in keyboard controller - // - Register = 0xA7; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiIsaIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - if (EFI_ERROR (Status)) { - return Status; - } - - for (Index = 0; Index < HandleCount; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo - ); - ASSERT_EFI_ERROR (Status); - IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, 0x64, 1, &Register); - - } - - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - } - - return EFI_SUCCESS; - -} - -/** - Identify drive data must be updated to actual parameters before boot. - This requires updating the checksum, if it exists. - - @param IdentifyDriveData ATA Identify Data - @param Checksum checksum of the ATA Identify Data - - @retval EFI_SUCCESS checksum calculated - @retval EFI_SECURITY_VIOLATION IdentifyData invalid - -**/ -EFI_STATUS -CalculateIdentifyDriveChecksum ( - IN UINT8 *IdentifyDriveData, - OUT UINT8 *Checksum - ) -{ - UINTN Index; - UINT8 LocalChecksum; - LocalChecksum = 0; - *Checksum = 0; - if (IdentifyDriveData[510] != 0xA5) { - return EFI_SECURITY_VIOLATION; - } - - for (Index = 0; Index < 512; Index++) { - LocalChecksum = (UINT8) (LocalChecksum + IdentifyDriveData[Index]); - } - - *Checksum = LocalChecksum; - return EFI_SUCCESS; -} - - -/** - Identify drive data must be updated to actual parameters before boot. - - @param IdentifyDriveData ATA Identify Data - - -**/ -VOID -UpdateIdentifyDriveData ( - IN UINT8 *IdentifyDriveData - ) -{ - UINT16 NumberCylinders; - UINT16 NumberHeads; - UINT16 NumberSectorsTrack; - UINT32 CapacityInSectors; - UINT8 OriginalChecksum; - UINT8 FinalChecksum; - EFI_STATUS Status; - ATAPI_IDENTIFY *ReadInfo; - - // - // Status indicates if Integrity byte is correct. Checksum should be - // 0 if valid. - // - ReadInfo = (ATAPI_IDENTIFY *) IdentifyDriveData; - Status = CalculateIdentifyDriveChecksum (IdentifyDriveData, &OriginalChecksum); - if (OriginalChecksum != 0) { - Status = EFI_SECURITY_VIOLATION; - } - // - // If NumberCylinders = 0 then do data(Controller present but don drive attached). - // - NumberCylinders = ReadInfo->Raw[1]; - if (NumberCylinders != 0) { - ReadInfo->Raw[54] = NumberCylinders; - - NumberHeads = ReadInfo->Raw[3]; - ReadInfo->Raw[55] = NumberHeads; - - NumberSectorsTrack = ReadInfo->Raw[6]; - ReadInfo->Raw[56] = NumberSectorsTrack; - - // - // Copy Multisector info and set valid bit. - // - ReadInfo->Raw[59] = (UINT16) (ReadInfo->Raw[47] + 0x100); - CapacityInSectors = (UINT32) ((UINT32) (NumberCylinders) * (UINT32) (NumberHeads) * (UINT32) (NumberSectorsTrack)); - ReadInfo->Raw[57] = (UINT16) (CapacityInSectors >> 16); - ReadInfo->Raw[58] = (UINT16) (CapacityInSectors & 0xffff); - if (Status == EFI_SUCCESS) { - // - // Forece checksum byte to 0 and get new checksum. - // - ReadInfo->Raw[255] &= 0xff; - CalculateIdentifyDriveChecksum (IdentifyDriveData, &FinalChecksum); - - // - // Force new checksum such that sum is 0. - // - FinalChecksum = (UINT8) ((UINT8)0 - FinalChecksum); - ReadInfo->Raw[255] = (UINT16) (ReadInfo->Raw[255] | (FinalChecksum << 8)); - } - } -} - -/** - Identify drive data must be updated to actual parameters before boot. - Do for all drives. - - @param Private Legacy BIOS Instance data - - -**/ -VOID -UpdateAllIdentifyDriveData ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - UINTN Index; - HDD_INFO *HddInfo; - - HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; - - for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) { - // - // Each controller can have 2 devices. Update for each device - // - if ((HddInfo[Index].Status & HDD_MASTER_IDE) != 0) { - UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[0].Raw[0])); - } - - if ((HddInfo[Index].Status & HDD_SLAVE_IDE) != 0) { - UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[1].Raw[0])); - } - } -} - -/** - Enable ide controller. This gets disabled when LegacyBoot.c is about - to run the Option ROMs. - - @param Private Legacy BIOS Instance data - - -**/ -VOID -EnableIdeController ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - EFI_HANDLE IdeController; - UINT8 ByteBuffer; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - - Status = Private->LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformIdeHandle, - 0, - &HandleBuffer, - &HandleCount, - NULL - ); - if (!EFI_ERROR (Status)) { - IdeController = HandleBuffer[0]; - Status = gBS->HandleProtocol ( - IdeController, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - ByteBuffer = 0x1f; - if (!EFI_ERROR (Status)) { - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x04, 1, &ByteBuffer); - } - } -} - - -/** - Enable ide controller. This gets disabled when LegacyBoot.c is about - to run the Option ROMs. - - @param Private Legacy BIOS Instance data - - -**/ -VOID -EnableAllControllers ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINTN Index; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE01 PciConfigHeader; - EFI_STATUS Status; - - // - // - // - EnableIdeController (Private); - - // - // Assumption is table is built from low bus to high bus numbers. - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - ASSERT_EFI_ERROR (Status); - - for (Index = 0; Index < HandleCount; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - ASSERT_EFI_ERROR (Status); - - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (PciConfigHeader) / sizeof (UINT32), - &PciConfigHeader - ); - - // - // We do not enable PPB here. This is for HotPlug Consideration. - // The Platform HotPlug Driver is responsible for Padding enough hot plug - // resources. It is also responsible for enable this bridge. If it - // does not pad it. It will cause some early Windows fail to installation. - // If the platform driver does not pad resource for PPB, PPB should be in - // un-enabled state to let Windows know that this PPB is not configured by - // BIOS. So Windows will allocate default resource for PPB. - // - // The reason for why we enable the command register is: - // The CSM will use the IO bar to detect some IRQ status, if the command - // is disabled, the IO resource will be out of scope. - // For example: - // We installed a legacy IRQ handle for a PCI IDE controller. When IRQ - // comes up, the handle will check the IO space to identify is the - // controller generated the IRQ source. - // If the IO command is not enabled, the IRQ handler will has wrong - // information. It will cause IRQ storm when the correctly IRQ handler fails - // to run. - // - if (!(IS_PCI_VGA (&PciConfigHeader) || - IS_PCI_OLD_VGA (&PciConfigHeader) || - IS_PCI_IDE (&PciConfigHeader) || - IS_PCI_P2P (&PciConfigHeader) || - IS_PCI_P2P_SUB (&PciConfigHeader) || - IS_PCI_LPC (&PciConfigHeader) )) { - - PciConfigHeader.Hdr.Command |= 0x1f; - - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 4, 1, &PciConfigHeader.Hdr.Command); - } - } -} - -/** - The following routines are identical in operation, so combine - for code compaction: - EfiGetPlatformBinaryGetMpTable - EfiGetPlatformBinaryGetOemIntData - EfiGetPlatformBinaryGetOem32Data - EfiGetPlatformBinaryGetOem16Data - - @param This Protocol instance pointer. - @param Id Table/Data identifier - - @retval EFI_SUCCESS Success - @retval EFI_INVALID_PARAMETER Invalid ID - @retval EFI_OUT_OF_RESOURCES no resource to get data or table - -**/ -EFI_STATUS -LegacyGetDataOrTable ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN EFI_GET_PLATFORM_INFO_MODE Id - ) -{ - VOID *Table; - UINT32 TablePtr; - UINTN TableSize; - UINTN Alignment; - UINTN Location; - EFI_STATUS Status; - EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; - EFI_COMPATIBILITY16_TABLE *Legacy16Table; - EFI_IA32_REGISTER_SET Regs; - LEGACY_BIOS_INSTANCE *Private; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - - LegacyBiosPlatform = Private->LegacyBiosPlatform; - Legacy16Table = Private->Legacy16Table; - - // - // Phase 1 - get an address allocated in 16-bit code - // - while (TRUE) { - switch (Id) { - case EfiGetPlatformBinaryMpTable: - case EfiGetPlatformBinaryOemIntData: - case EfiGetPlatformBinaryOem32Data: - case EfiGetPlatformBinaryOem16Data: - { - Status = LegacyBiosPlatform->GetPlatformInfo ( - LegacyBiosPlatform, - Id, - (VOID *) &Table, - &TableSize, - &Location, - &Alignment, - 0, - 0 - ); - DEBUG ((EFI_D_INFO, "LegacyGetDataOrTable - ID: %x, %r\n", (UINTN)Id, Status)); - DEBUG ((EFI_D_INFO, " Table - %x, Size - %x, Location - %x, Alignment - %x\n", (UINTN)Table, (UINTN)TableSize, (UINTN)Location, (UINTN)Alignment)); - break; - } - - default: - { - return EFI_INVALID_PARAMETER; - } - } - - if (EFI_ERROR (Status)) { - return Status; - } - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16GetTableAddress; - Regs.X.CX = (UINT16) TableSize; - Regs.X.BX = (UINT16) Location; - Regs.X.DX = (UINT16) Alignment; - Private->LegacyBios.FarCall86 ( - This, - Private->Legacy16CallSegment, - Private->Legacy16CallOffset, - &Regs, - NULL, - 0 - ); - - if (Regs.X.AX != 0) { - DEBUG ((EFI_D_ERROR, "Table ID %x length insufficient\n", Id)); - return EFI_OUT_OF_RESOURCES; - } else { - break; - } - } - // - // Phase 2 Call routine second time with address to allow address adjustment - // - Status = LegacyBiosPlatform->GetPlatformInfo ( - LegacyBiosPlatform, - Id, - (VOID *) &Table, - &TableSize, - &Location, - &Alignment, - Regs.X.DS, - Regs.X.BX - ); - switch (Id) { - case EfiGetPlatformBinaryMpTable: - { - Legacy16Table->MpTablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); - Legacy16Table->MpTableLength = (UINT32)TableSize; - DEBUG ((EFI_D_INFO, "MP table in legacy region - %x\n", (UINTN)Legacy16Table->MpTablePtr)); - break; - } - - case EfiGetPlatformBinaryOemIntData: - { - - Legacy16Table->OemIntSegment = Regs.X.DS; - Legacy16Table->OemIntOffset = Regs.X.BX; - DEBUG ((EFI_D_INFO, "OemInt table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->OemIntSegment, (UINTN)Legacy16Table->OemIntOffset)); - break; - } - - case EfiGetPlatformBinaryOem32Data: - { - Legacy16Table->Oem32Segment = Regs.X.DS; - Legacy16Table->Oem32Offset = Regs.X.BX; - DEBUG ((EFI_D_INFO, "Oem32 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem32Segment, (UINTN)Legacy16Table->Oem32Offset)); - break; - } - - case EfiGetPlatformBinaryOem16Data: - { - // - // Legacy16Table->Oem16Segment = Regs.X.DS; - // Legacy16Table->Oem16Offset = Regs.X.BX; - DEBUG ((EFI_D_INFO, "Oem16 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem16Segment, (UINTN)Legacy16Table->Oem16Offset)); - break; - } - - default: - { - return EFI_INVALID_PARAMETER; - } - } - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Phase 3 Copy table to final location - // - TablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); - - CopyMem ( - (VOID *) (UINTN)TablePtr, - Table, - TableSize - ); - - return EFI_SUCCESS; -} - -/** - Copy SMBIOS table to EfiReservedMemoryType of memory for legacy boot. - -**/ -VOID -CreateSmbiosTableInReservedMemory ( - VOID - ) -{ - SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; - - if ((mRuntimeSmbiosEntryPoint == NULL) || - (mReserveSmbiosEntryPoint == 0) || - (mStructureTableAddress == 0)) { - return; - } - - EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint; - - // - // Copy SMBIOS Entry Point Structure - // - CopyMem ( - (VOID *)(UINTN) mReserveSmbiosEntryPoint, - EntryPointStructure, - EntryPointStructure->EntryPointLength - ); - - // - // Copy SMBIOS Structure Table into EfiReservedMemoryType memory - // - CopyMem ( - (VOID *)(UINTN) mStructureTableAddress, - (VOID *)(UINTN) EntryPointStructure->TableAddress, - EntryPointStructure->TableLength - ); - - // - // Update TableAddress in Entry Point Structure - // - EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN) mReserveSmbiosEntryPoint; - EntryPointStructure->TableAddress = (UINT32)(UINTN) mStructureTableAddress; - - // - // Fixup checksums in the Entry Point Structure - // - EntryPointStructure->IntermediateChecksum = 0; - EntryPointStructure->EntryPointStructureChecksum = 0; - - EntryPointStructure->IntermediateChecksum = - CalculateCheckSum8 ( - (UINT8 *) EntryPointStructure + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString), - EntryPointStructure->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString) - ); - EntryPointStructure->EntryPointStructureChecksum = - CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure->EntryPointLength); -} - -/** - Assign drive number to legacy HDD drives prior to booting an EFI - aware OS so the OS can access drives without an EFI driver. - Note: BBS compliant drives ARE NOT available until this call by - either shell or EFI. - - @param This Protocol instance pointer. - - @retval EFI_SUCCESS Drive numbers assigned - -**/ -EFI_STATUS -GenericLegacyBoot ( - IN EFI_LEGACY_BIOS_PROTOCOL *This - ) -{ - EFI_STATUS Status; - LEGACY_BIOS_INSTANCE *Private; - EFI_IA32_REGISTER_SET Regs; - EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; - EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; - UINTN CopySize; - VOID *AcpiPtr; - HDD_INFO *HddInfo; - HDD_INFO *LocalHddInfo; - UINTN Index; - EFI_COMPATIBILITY16_TABLE *Legacy16Table; - UINT32 *BdaPtr; - UINT16 HddCount; - UINT16 BbsCount; - BBS_TABLE *LocalBbsTable; - UINT32 *BaseVectorMaster; - EFI_TIME BootTime; - UINT32 LocalTime; - EFI_HANDLE IdeController; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - VOID *AcpiTable; - UINTN ShadowAddress; - UINT32 Granularity; - - LocalHddInfo = NULL; - HddCount = 0; - BbsCount = 0; - LocalBbsTable = NULL; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - DEBUG_CODE ( - DEBUG ((EFI_D_ERROR, "Start of legacy boot\n")); - ); - - Legacy16Table = Private->Legacy16Table; - EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; - HddInfo = &EfiToLegacy16BootTable->HddInfo[0]; - - LegacyBiosPlatform = Private->LegacyBiosPlatform; - - EfiToLegacy16BootTable->MajorVersion = EFI_TO_LEGACY_MAJOR_VERSION; - EfiToLegacy16BootTable->MinorVersion = EFI_TO_LEGACY_MINOR_VERSION; - - // - // If booting to a legacy OS then force HDD drives to the appropriate - // boot mode by calling GetIdeHandle. - // A reconnect -r can force all HDDs back to native mode. - // - IdeController = NULL; - if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { - Status = LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformIdeHandle, - 0, - &HandleBuffer, - &HandleCount, - NULL - ); - if (!EFI_ERROR (Status)) { - IdeController = HandleBuffer[0]; - } - } - // - // Unlock the Legacy BIOS region - // - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - 0xE0000, - 0x20000, - &Granularity - ); - - // - // Reconstruct the Legacy16 boot memory map - // - LegacyBiosBuildE820 (Private, &CopySize); - if (CopySize > Private->Legacy16Table->E820Length) { - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16GetTableAddress; - Regs.X.CX = (UINT16) CopySize; - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Private->Legacy16Table->Compatibility16CallSegment, - Private->Legacy16Table->Compatibility16CallOffset, - &Regs, - NULL, - 0 - ); - - Private->Legacy16Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); - Private->Legacy16Table->E820Length = (UINT32) CopySize; - if (Regs.X.AX != 0) { - DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n")); - } else { - CopyMem ( - (VOID *)(UINTN) Private->Legacy16Table->E820Pointer, - Private->E820Table, - CopySize - ); - } - } else { - CopyMem ( - (VOID *)(UINTN) Private->Legacy16Table->E820Pointer, - Private->E820Table, - CopySize - ); - Private->Legacy16Table->E820Length = (UINT32) CopySize; - } - - // - // We do not ASSERT if SmbiosTable not found. It is possbile that a platform does not produce SmbiosTable. - // - if (mReserveSmbiosEntryPoint == 0) { - DEBUG ((EFI_D_INFO, "Smbios table is not found!\n")); - } - CreateSmbiosTableInReservedMemory (); - EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)mReserveSmbiosEntryPoint; - - AcpiTable = NULL; - Status = EfiGetSystemConfigurationTable ( - &gEfiAcpi20TableGuid, - &AcpiTable - ); - if (EFI_ERROR (Status)) { - Status = EfiGetSystemConfigurationTable ( - &gEfiAcpi10TableGuid, - &AcpiTable - ); - } - // - // We do not ASSERT if AcpiTable not found. It is possbile that a platform does not produce AcpiTable. - // - if (AcpiTable == NULL) { - DEBUG ((EFI_D_INFO, "ACPI table is not found!\n")); - } - EfiToLegacy16BootTable->AcpiTable = (UINT32)(UINTN)AcpiTable; - - // - // Get RSD Ptr table rev at offset 15 decimal - // Rev = 0 Length is 20 decimal - // Rev != 0 Length is UINT32 at offset 20 decimal - // - if (AcpiTable != NULL) { - - AcpiPtr = AcpiTable; - if (*((UINT8 *) AcpiPtr + 15) == 0) { - CopySize = 20; - } else { - AcpiPtr = ((UINT8 *) AcpiPtr + 20); - CopySize = (*(UINT32 *) AcpiPtr); - } - - CopyMem ( - (VOID *)(UINTN) Private->Legacy16Table->AcpiRsdPtrPointer, - AcpiTable, - CopySize - ); - } - // - // Make sure all PCI Interrupt Line register are programmed to match 8259 - // - PciProgramAllInterruptLineRegisters (Private); - - // - // Unlock the Legacy BIOS region as PciProgramAllInterruptLineRegisters - // can lock it. - // - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - Private->BiosStart, - Private->LegacyBiosImageSize, - &Granularity - ); - - // - // Configure Legacy Device Magic - // - // Only do this code if booting legacy OS - // - if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { - UpdateSioData (Private); - } - // - // Setup BDA and EBDA standard areas before Legacy Boot - // - LegacyBiosCompleteBdaBeforeBoot (Private); - LegacyBiosCompleteStandardCmosBeforeBoot (Private); - - // - // We must build IDE data, if it hasn't been done, before PciShadowRoms - // to insure EFI drivers are connected. - // - LegacyBiosBuildIdeData (Private, &HddInfo, 1); - UpdateAllIdentifyDriveData (Private); - - // - // Clear IO BAR, if IDE controller in legacy mode. - // - InitLegacyIdeController (IdeController); - - // - // Generate number of ticks since midnight for BDA. DOS requires this - // for its time. We have to make assumptions as to how long following - // code takes since after PciShadowRoms PciIo is gone. Place result in - // 40:6C-6F - // - // Adjust value by 1 second. - // - gRT->GetTime (&BootTime, NULL); - LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second; - LocalTime += 1; - - // - // Multiply result by 18.2 for number of ticks since midnight. - // Use 182/10 to avoid floating point math. - // - LocalTime = (LocalTime * 182) / 10; - BdaPtr = (UINT32 *) (UINTN)0x46C; - *BdaPtr = LocalTime; - - // - // Shadow PCI ROMs. We must do this near the end since this will kick - // of Native EFI drivers that may be needed to collect info for Legacy16 - // - // WARNING: PciIo is gone after this call. - // - PciShadowRoms (Private); - - // - // Shadow PXE base code, BIS etc. - // - Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity); - ShadowAddress = Private->OptionRom; - Private->LegacyBiosPlatform->PlatformHooks ( - Private->LegacyBiosPlatform, - EfiPlatformHookShadowServiceRoms, - 0, - 0, - &ShadowAddress, - Legacy16Table, - NULL - ); - Private->OptionRom = (UINT32)ShadowAddress; - // - // Register Legacy SMI Handler - // - LegacyBiosPlatform->SmmInit ( - LegacyBiosPlatform, - EfiToLegacy16BootTable - ); - - // - // Let platform code know the boot options - // - LegacyBiosGetBbsInfo ( - This, - &HddCount, - &LocalHddInfo, - &BbsCount, - &LocalBbsTable - ); - - DEBUG_CODE ( - PrintPciInterruptRegister (); - PrintBbsTable (LocalBbsTable); - PrintHddInfo (LocalHddInfo); - ); - // - // If drive wasn't spun up then BuildIdeData may have found new drives. - // Need to update BBS boot priority. - // - for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) { - if ((LocalHddInfo[Index].IdentifyDrive[0].Raw[0] != 0) && - (LocalBbsTable[2 * Index + 1].BootPriority == BBS_IGNORE_ENTRY) - ) { - LocalBbsTable[2 * Index + 1].BootPriority = BBS_UNPRIORITIZED_ENTRY; - } - - if ((LocalHddInfo[Index].IdentifyDrive[1].Raw[0] != 0) && - (LocalBbsTable[2 * Index + 2].BootPriority == BBS_IGNORE_ENTRY) - ) { - LocalBbsTable[2 * Index + 2].BootPriority = BBS_UNPRIORITIZED_ENTRY; - } - } - - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - 0xc0000, - 0x40000, - &Granularity - ); - - LegacyBiosPlatform->PrepareToBoot ( - LegacyBiosPlatform, - mBbsDevicePathPtr, - mBbsTable, - mLoadOptionsSize, - mLoadOptions, - (VOID *) &Private->IntThunk->EfiToLegacy16BootTable - ); - - // - // If no boot device return to BDS - // - if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { - for (Index = 0; Index < BbsCount; Index++){ - if ((LocalBbsTable[Index].BootPriority != BBS_DO_NOT_BOOT_FROM) && - (LocalBbsTable[Index].BootPriority != BBS_UNPRIORITIZED_ENTRY) && - (LocalBbsTable[Index].BootPriority != BBS_IGNORE_ENTRY)) { - break; - } - } - if (Index == BbsCount) { - return EFI_DEVICE_ERROR; - } - } - // - // Let the Legacy16 code know the device path type for legacy boot - // - EfiToLegacy16BootTable->DevicePathType = mBbsDevicePathPtr->DeviceType; - - // - // Copy MP table, if it exists. - // - LegacyGetDataOrTable (This, EfiGetPlatformBinaryMpTable); - - if (!Private->LegacyBootEntered) { - // - // Copy OEM INT Data, if it exists. Note: This code treats any data - // as a bag of bits and knows nothing of the contents nor cares. - // Contents are IBV specific. - // - LegacyGetDataOrTable (This, EfiGetPlatformBinaryOemIntData); - - // - // Copy OEM16 Data, if it exists.Note: This code treats any data - // as a bag of bits and knows nothing of the contents nor cares. - // Contents are IBV specific. - // - LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem16Data); - - // - // Copy OEM32 Data, if it exists.Note: This code treats any data - // as a bag of bits and knows nothing of the contents nor cares. - // Contents are IBV specific. - // - LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem32Data); - } - - // - // Call into Legacy16 code to prepare for INT 19h - // - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16PrepareToBoot; - - // - // Pass in handoff data - // - Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINTN)EfiToLegacy16BootTable); - Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINTN)EfiToLegacy16BootTable); - - Private->LegacyBios.FarCall86 ( - This, - Private->Legacy16CallSegment, - Private->Legacy16CallOffset, - &Regs, - NULL, - 0 - ); - - if (Regs.X.AX != 0) { - return EFI_DEVICE_ERROR; - } - // - // Lock the Legacy BIOS region - // - Private->LegacyRegion->Lock ( - Private->LegacyRegion, - 0xc0000, - 0x40000, - &Granularity - ); - - if ((Private->Legacy16Table->TableLength >= OFFSET_OF (EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) && - ((Private->Legacy16Table->UmaAddress != 0) && (Private->Legacy16Table->UmaSize != 0))) { - // - // Here we could reduce UmaAddress down as far as Private->OptionRom, taking into - // account the granularity of the access control. - // - DEBUG((EFI_D_INFO, "Unlocking UMB RAM region 0x%x-0x%x\n", Private->Legacy16Table->UmaAddress, - Private->Legacy16Table->UmaAddress + Private->Legacy16Table->UmaSize)); - - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - Private->Legacy16Table->UmaAddress, - Private->Legacy16Table->UmaSize, - &Granularity - ); - } - - // - // Lock attributes of the Legacy Region if chipset supports - // - Private->LegacyRegion->BootLock ( - Private->LegacyRegion, - 0xc0000, - 0x40000, - &Granularity - ); - - // - // Call into Legacy16 code to do the INT 19h - // - EnableAllControllers (Private); - if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { - - // - // Signal all the events that are waiting on EVT_SIGNAL_LEGACY_BOOT - // - EfiSignalEventLegacyBoot (); - - // - // Report Status Code to indicate legacy boot event was signalled - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT) - ); - - DEBUG ((EFI_D_INFO, "Legacy INT19 Boot...\n")); - - // - // Disable DXE Timer while executing in real mode - // - Private->Timer->SetTimerPeriod (Private->Timer, 0); - - // - // Save and disable interrupt of debug timer - // - SaveAndSetDebugTimerInterrupt (FALSE); - - - // - // Put the 8259 into its legacy mode by reprogramming the vector bases - // - Private->Legacy8259->SetVectorBase (Private->Legacy8259, LEGACY_MODE_BASE_VECTOR_MASTER, LEGACY_MODE_BASE_VECTOR_SLAVE); - // - // PC History - // The original PC used INT8-F for master PIC. Since these mapped over - // processor exceptions TIANO moved the master PIC to INT68-6F. - // We need to set these back to the Legacy16 unexpected interrupt(saved - // in LegacyBios.c) since some OS see that these have values different from - // what is expected and invoke them. Since the legacy OS corrupts EFI - // memory, there is no handler for these interrupts and OS blows up. - // - // We need to save the TIANO values for the rare case that the Legacy16 - // code cannot boot but knows memory hasn't been destroyed. - // - // To compound the problem, video takes over one of these INTS and must be - // be left. - // @bug - determine if video hooks INT(in which case we must find new - // set of TIANO vectors) or takes it over. - // - // - BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER); - for (Index = 0; Index < 8; Index++) { - Private->ThunkSavedInt[Index] = BaseVectorMaster[Index]; - if (Private->ThunkSeg == (UINT16) (BaseVectorMaster[Index] >> 16)) { - BaseVectorMaster[Index] = (UINT32) (Private->BiosUnexpectedInt); - } - } - - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16Boot; - - Private->LegacyBios.FarCall86 ( - This, - Private->Legacy16CallSegment, - Private->Legacy16CallOffset, - &Regs, - NULL, - 0 - ); - - BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER); - for (Index = 0; Index < 8; Index++) { - BaseVectorMaster[Index] = Private->ThunkSavedInt[Index]; - } - } - Private->LegacyBootEntered = TRUE; - if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) { - // - // Should never return unless never passed control to 0:7c00(first stage - // OS loader) and only then if no bootable device found. - // - return EFI_DEVICE_ERROR; - } else { - // - // If boot to EFI then expect to return to caller - // - return EFI_SUCCESS; - } -} - - -/** - Assign drive number to legacy HDD drives prior to booting an EFI - aware OS so the OS can access drives without an EFI driver. - Note: BBS compliant drives ARE NOT available until this call by - either shell or EFI. - - @param This Protocol instance pointer. - @param BbsCount Number of BBS_TABLE structures - @param BbsTable List BBS entries - - @retval EFI_SUCCESS Drive numbers assigned - -**/ -EFI_STATUS -EFIAPI -LegacyBiosPrepareToBootEfi ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - OUT UINT16 *BbsCount, - OUT BBS_TABLE **BbsTable - ) -{ - EFI_STATUS Status; - EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; - LEGACY_BIOS_INSTANCE *Private; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; - mBootMode = BOOT_EFI_OS; - mBbsDevicePathPtr = NULL; - Status = GenericLegacyBoot (This); - *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; - *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); - return Status; -} - -/** - To boot from an unconventional device like parties and/or execute HDD diagnostics. - - @param This Protocol instance pointer. - @param Attributes How to interpret the other input parameters - @param BbsEntry The 0-based index into the BbsTable for the parent - device. - @param BeerData Pointer to the 128 bytes of ram BEER data. - @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. The - caller must provide a pointer to the specific Service - Area and not the start all Service Areas. - - @retval EFI_INVALID_PARAMETER if error. Does NOT return if no error. - -***/ -EFI_STATUS -EFIAPI -LegacyBiosBootUnconventionalDevice ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UDC_ATTRIBUTES Attributes, - IN UINTN BbsEntry, - IN VOID *BeerData, - IN VOID *ServiceAreaData - ) -{ - EFI_STATUS Status; - EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; - LEGACY_BIOS_INSTANCE *Private; - UD_TABLE *UcdTable; - UINTN Index; - UINT16 BootPriority; - BBS_TABLE *BbsTable; - - BootPriority = 0; - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - mBootMode = BOOT_UNCONVENTIONAL_DEVICE; - mBbsDevicePathPtr = &mBbsDevicePathNode; - mAttributes = Attributes; - mBbsEntry = BbsEntry; - mBeerData = BeerData, mServiceAreaData = ServiceAreaData; - - EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable; - - // - // Do input parameter checking - // - if ((Attributes.DirectoryServiceValidity == 0) && - (Attributes.RabcaUsedFlag == 0) && - (Attributes.ExecuteHddDiagnosticsFlag == 0) - ) { - return EFI_INVALID_PARAMETER; - } - - if (((Attributes.DirectoryServiceValidity != 0) && (ServiceAreaData == NULL)) || - (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag) != 0) && (BeerData == NULL)) - ) { - return EFI_INVALID_PARAMETER; - } - - UcdTable = (UD_TABLE *) AllocatePool ( - sizeof (UD_TABLE) - ); - if (NULL == UcdTable) { - return EFI_OUT_OF_RESOURCES; - } - - EfiToLegacy16BootTable->UnconventionalDeviceTable = (UINT32)(UINTN)UcdTable; - UcdTable->Attributes = Attributes; - UcdTable->BbsTableEntryNumberForParentDevice = (UINT8) BbsEntry; - // - // Force all existing BBS entries to DoNotBoot. This allows 16-bit CSM - // to assign drive numbers but bot boot from. Only newly created entries - // will be valid. - // - BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; - for (Index = 0; Index < EfiToLegacy16BootTable->NumberBbsEntries; Index++) { - BbsTable[Index].BootPriority = BBS_DO_NOT_BOOT_FROM; - } - // - // If parent is onboard IDE then assign controller & device number - // else they are 0. - // - if (BbsEntry < MAX_IDE_CONTROLLER * 2) { - UcdTable->DeviceNumber = (UINT8) ((BbsEntry - 1) % 2); - } - - if (BeerData != NULL) { - CopyMem ( - (VOID *) UcdTable->BeerData, - BeerData, - (UINTN) 128 - ); - } - - if (ServiceAreaData != NULL) { - CopyMem ( - (VOID *) UcdTable->ServiceAreaData, - ServiceAreaData, - (UINTN) 64 - ); - } - // - // For each new entry do the following: - // 1. Increment current number of BBS entries - // 2. Copy parent entry to new entry. - // 3. Zero out BootHandler Offset & segment - // 4. Set appropriate device type. BEV(0x80) for HDD diagnostics - // and Floppy(0x01) for PARTIES boot. - // 5. Assign new priority. - // - if ((Attributes.ExecuteHddDiagnosticsFlag) != 0) { - EfiToLegacy16BootTable->NumberBbsEntries += 1; - - CopyMem ( - (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority, - (VOID *) &BbsTable[BbsEntry].BootPriority, - sizeof (BBS_TABLE) - ); - - BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = 0; - BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0; - BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = 0x80; - - UcdTable->BbsTableEntryNumberForHddDiag = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1); - - BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority; - BootPriority += 1; - - // - // Set device type as BBS_TYPE_DEV for PARTIES diagnostic - // - mBbsDevicePathNode.DeviceType = BBS_TYPE_BEV; - } - - if (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag)) != 0) { - EfiToLegacy16BootTable->NumberBbsEntries += 1; - CopyMem ( - (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority, - (VOID *) &BbsTable[BbsEntry].BootPriority, - sizeof (BBS_TABLE) - ); - - BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = 0; - BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0; - BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = 0x01; - UcdTable->BbsTableEntryNumberForBoot = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1); - BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority; - - // - // Set device type as BBS_TYPE_FLOPPY for PARTIES boot as floppy - // - mBbsDevicePathNode.DeviceType = BBS_TYPE_FLOPPY; - } - // - // Build the BBS Device Path for this boot selection - // - mBbsDevicePathNode.Header.Type = BBS_DEVICE_PATH; - mBbsDevicePathNode.Header.SubType = BBS_BBS_DP; - SetDevicePathNodeLength (&mBbsDevicePathNode.Header, sizeof (BBS_BBS_DEVICE_PATH)); - mBbsDevicePathNode.StatusFlag = 0; - mBbsDevicePathNode.String[0] = 0; - - Status = GenericLegacyBoot (This); - return Status; -} - -/** - Attempt to legacy boot the BootOption. If the EFI contexted has been - compromised this function will not return. - - @param This Protocol instance pointer. - @param BbsDevicePath EFI Device Path from BootXXXX variable. - @param LoadOptionsSize Size of LoadOption in size. - @param LoadOptions LoadOption from BootXXXX variable - - @retval EFI_SUCCESS Removable media not present - -**/ -EFI_STATUS -EFIAPI -LegacyBiosLegacyBoot ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN BBS_BBS_DEVICE_PATH *BbsDevicePath, - IN UINT32 LoadOptionsSize, - IN VOID *LoadOptions - ) -{ - EFI_STATUS Status; - - mBbsDevicePathPtr = BbsDevicePath; - mLoadOptionsSize = LoadOptionsSize; - mLoadOptions = LoadOptions; - mBootMode = BOOT_LEGACY_OS; - Status = GenericLegacyBoot (This); - - return Status; -} - -/** - Convert EFI Memory Type to E820 Memory Type. - - @param Type EFI Memory Type - - @return ACPI Memory Type for EFI Memory Type - -**/ -EFI_ACPI_MEMORY_TYPE -EfiMemoryTypeToE820Type ( - IN UINT32 Type - ) -{ - switch (Type) { - case EfiLoaderCode: - case EfiLoaderData: - case EfiBootServicesCode: - case EfiBootServicesData: - case EfiConventionalMemory: - // - // The memory of EfiRuntimeServicesCode and EfiRuntimeServicesData are - // usable memory for legacy OS, because legacy OS is not aware of EFI runtime concept. - // In ACPI specification, EfiRuntimeServiceCode and EfiRuntimeServiceData - // should be mapped to AddressRangeReserved. This statement is for UEFI OS, not for legacy OS. - // - case EfiRuntimeServicesCode: - case EfiRuntimeServicesData: - return EfiAcpiAddressRangeMemory; - - case EfiPersistentMemory: - return EfiAddressRangePersistentMemory; - - case EfiACPIReclaimMemory: - return EfiAcpiAddressRangeACPI; - - case EfiACPIMemoryNVS: - return EfiAcpiAddressRangeNVS; - - // - // All other types map to reserved. - // Adding the code just waists FLASH space. - // - // case EfiReservedMemoryType: - // case EfiUnusableMemory: - // case EfiMemoryMappedIO: - // case EfiMemoryMappedIOPortSpace: - // case EfiPalCode: - // - default: - return EfiAcpiAddressRangeReserved; - } -} - -/** - Build the E820 table. - - @param Private Legacy BIOS Instance data - @param Size Size of E820 Table - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosBuildE820 ( - IN LEGACY_BIOS_INSTANCE *Private, - OUT UINTN *Size - ) -{ - EFI_STATUS Status; - EFI_E820_ENTRY64 *E820Table; - EFI_MEMORY_DESCRIPTOR *EfiMemoryMap; - EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd; - EFI_MEMORY_DESCRIPTOR *EfiEntry; - EFI_MEMORY_DESCRIPTOR *NextEfiEntry; - EFI_MEMORY_DESCRIPTOR TempEfiEntry; - UINTN EfiMemoryMapSize; - UINTN EfiMapKey; - UINTN EfiDescriptorSize; - UINT32 EfiDescriptorVersion; - UINTN Index; - EFI_PEI_HOB_POINTERS Hob; - EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; - UINTN TempIndex; - UINTN IndexSort; - UINTN TempNextIndex; - EFI_E820_ENTRY64 TempE820; - EFI_ACPI_MEMORY_TYPE TempType; - BOOLEAN ChangedFlag; - UINTN Above1MIndex; - UINT64 MemoryBlockLength; - - E820Table = (EFI_E820_ENTRY64 *) Private->E820Table; - - // - // Get the EFI memory map. - // - EfiMemoryMapSize = 0; - EfiMemoryMap = NULL; - Status = gBS->GetMemoryMap ( - &EfiMemoryMapSize, - EfiMemoryMap, - &EfiMapKey, - &EfiDescriptorSize, - &EfiDescriptorVersion - ); - ASSERT (Status == EFI_BUFFER_TOO_SMALL); - - do { - // - // Use size returned back plus 1 descriptor for the AllocatePool. - // We don't just multiply by 2 since the "for" loop below terminates on - // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize - // we process bogus entries and create bogus E820 entries. - // - EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapSize); - ASSERT (EfiMemoryMap != NULL); - Status = gBS->GetMemoryMap ( - &EfiMemoryMapSize, - EfiMemoryMap, - &EfiMapKey, - &EfiDescriptorSize, - &EfiDescriptorVersion - ); - if (EFI_ERROR (Status)) { - FreePool (EfiMemoryMap); - } - } while (Status == EFI_BUFFER_TOO_SMALL); - - ASSERT_EFI_ERROR (Status); - - // - // Punch in the E820 table for memory less than 1 MB. - // Assume ZeroMem () has been done on data structure. - // - // - // First entry is 0 to (640k - EBDA) - // - E820Table[0].BaseAddr = 0; - E820Table[0].Length = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4); - E820Table[0].Type = EfiAcpiAddressRangeMemory; - - // - // Second entry is (640k - EBDA) to 640k - // - E820Table[1].BaseAddr = E820Table[0].Length; - E820Table[1].Length = (UINT64) ((640 * 1024) - E820Table[0].Length); - E820Table[1].Type = EfiAcpiAddressRangeReserved; - - // - // Third Entry is legacy BIOS - // DO NOT CLAIM region from 0xA0000-0xDFFFF. OS can use free areas - // to page in memory under 1MB. - // Omit region from 0xE0000 to start of BIOS, if any. This can be - // used for a multiple reasons including OPROMS. - // - - // - // The CSM binary image size is not the actually size that CSM binary used, - // to avoid memory corrupt, we declare the 0E0000 - 0FFFFF is used by CSM binary. - // - E820Table[2].BaseAddr = 0xE0000; - E820Table[2].Length = 0x20000; - E820Table[2].Type = EfiAcpiAddressRangeReserved; - - Above1MIndex = 2; - - // - // Process the EFI map to produce E820 map; - // - - // - // Sort memory map from low to high - // - EfiEntry = EfiMemoryMap; - NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); - EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize); - while (EfiEntry < EfiMemoryMapEnd) { - while (NextEfiEntry < EfiMemoryMapEnd) { - if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) { - CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); - CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); - CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); - } - - NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptorSize); - } - - EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); - NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); - } - - EfiEntry = EfiMemoryMap; - EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize); - for (Index = Above1MIndex; (EfiEntry < EfiMemoryMapEnd) && (Index < EFI_MAX_E820_ENTRY - 1); ) { - MemoryBlockLength = (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12)); - if ((EfiEntry->PhysicalStart + MemoryBlockLength) < 0x100000) { - // - // Skip the memory block is under 1MB - // - } else { - if (EfiEntry->PhysicalStart < 0x100000) { - // - // When the memory block spans below 1MB, ensure the memory block start address is at least 1MB - // - MemoryBlockLength -= 0x100000 - EfiEntry->PhysicalStart; - EfiEntry->PhysicalStart = 0x100000; - } - - // - // Convert memory type to E820 type - // - TempType = EfiMemoryTypeToE820Type (EfiEntry->Type); - - if ((E820Table[Index].Type == TempType) && (EfiEntry->PhysicalStart == (E820Table[Index].BaseAddr + E820Table[Index].Length))) { - // - // Grow an existing entry - // - E820Table[Index].Length += MemoryBlockLength; - } else { - // - // Make a new entry - // - ++Index; - E820Table[Index].BaseAddr = EfiEntry->PhysicalStart; - E820Table[Index].Length = MemoryBlockLength; - E820Table[Index].Type = TempType; - } - } - EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); - } - - FreePool (EfiMemoryMap); - - // - // Process the reserved memory map to produce E820 map ; - // - for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { - if (Hob.Raw != NULL && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { - ResourceHob = Hob.ResourceDescriptor; - if (((ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_MAPPED_IO) || - (ResourceHob->ResourceType == EFI_RESOURCE_FIRMWARE_DEVICE) || - (ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) ) && - (ResourceHob->PhysicalStart > 0x100000) && - (Index < EFI_MAX_E820_ENTRY - 1)) { - ++Index; - E820Table[Index].BaseAddr = ResourceHob->PhysicalStart; - E820Table[Index].Length = ResourceHob->ResourceLength; - E820Table[Index].Type = EfiAcpiAddressRangeReserved; - } - } - } - - Index ++; - Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index; - Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index; - Private->NumberE820Entries = (UINT32)Index; - *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64)); - - // - // Sort E820Table from low to high - // - for (TempIndex = 0; TempIndex < Index; TempIndex++) { - ChangedFlag = FALSE; - for (TempNextIndex = 1; TempNextIndex < Index - TempIndex; TempNextIndex++) { - if (E820Table[TempNextIndex - 1].BaseAddr > E820Table[TempNextIndex].BaseAddr) { - ChangedFlag = TRUE; - TempE820.BaseAddr = E820Table[TempNextIndex - 1].BaseAddr; - TempE820.Length = E820Table[TempNextIndex - 1].Length; - TempE820.Type = E820Table[TempNextIndex - 1].Type; - - E820Table[TempNextIndex - 1].BaseAddr = E820Table[TempNextIndex].BaseAddr; - E820Table[TempNextIndex - 1].Length = E820Table[TempNextIndex].Length; - E820Table[TempNextIndex - 1].Type = E820Table[TempNextIndex].Type; - - E820Table[TempNextIndex].BaseAddr = TempE820.BaseAddr; - E820Table[TempNextIndex].Length = TempE820.Length; - E820Table[TempNextIndex].Type = TempE820.Type; - } - } - - if (!ChangedFlag) { - break; - } - } - - // - // Remove the overlap range - // - for (TempIndex = 1; TempIndex < Index; TempIndex++) { - if (E820Table[TempIndex - 1].BaseAddr <= E820Table[TempIndex].BaseAddr && - ((E820Table[TempIndex - 1].BaseAddr + E820Table[TempIndex - 1].Length) >= - (E820Table[TempIndex].BaseAddr +E820Table[TempIndex].Length))) { - // - //Overlap range is found - // - ASSERT (E820Table[TempIndex - 1].Type == E820Table[TempIndex].Type); - - if (TempIndex == Index - 1) { - E820Table[TempIndex].BaseAddr = 0; - E820Table[TempIndex].Length = 0; - E820Table[TempIndex].Type = (EFI_ACPI_MEMORY_TYPE) 0; - Index--; - break; - } else { - for (IndexSort = TempIndex; IndexSort < Index - 1; IndexSort ++) { - E820Table[IndexSort].BaseAddr = E820Table[IndexSort + 1].BaseAddr; - E820Table[IndexSort].Length = E820Table[IndexSort + 1].Length; - E820Table[IndexSort].Type = E820Table[IndexSort + 1].Type; - } - Index--; - } - } - } - - - - Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index; - Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index; - Private->NumberE820Entries = (UINT32)Index; - *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64)); - - // - // Determine OS usable memory above 1Mb - // - Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb = 0x0000; - for (TempIndex = Above1MIndex; TempIndex < Index; TempIndex++) { - if (E820Table[TempIndex].BaseAddr >= 0x100000 && E820Table[TempIndex].BaseAddr < 0x100000000ULL) { // not include above 4G memory - // - // ACPIReclaimMemory is also usable memory for ACPI OS, after OS dumps all ACPI tables. - // - if ((E820Table[TempIndex].Type == EfiAcpiAddressRangeMemory) || (E820Table[TempIndex].Type == EfiAcpiAddressRangeACPI)) { - Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb += (UINT32) (E820Table[TempIndex].Length); - } else { - break; // break at first not normal memory, because SMM may use reserved memory. - } - } - } - - Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb = Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb; - - // - // Print DEBUG information - // - for (TempIndex = 0; TempIndex < Index; TempIndex++) { - DEBUG((EFI_D_INFO, "E820[%2d]: 0x%16lx ---- 0x%16lx, Type = 0x%x \n", - TempIndex, - E820Table[TempIndex].BaseAddr, - (E820Table[TempIndex].BaseAddr + E820Table[TempIndex].Length), - E820Table[TempIndex].Type - )); - } - - return EFI_SUCCESS; -} - - -/** - Fill in the standard BDA and EBDA stuff prior to legacy Boot - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosCompleteBdaBeforeBoot ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - BDA_STRUC *Bda; - UINT16 MachineConfig; - DEVICE_PRODUCER_DATA_HEADER *SioPtr; - - Bda = (BDA_STRUC *) ((UINTN) 0x400); - MachineConfig = 0; - - SioPtr = &(Private->IntThunk->EfiToLegacy16BootTable.SioData); - Bda->Com1 = SioPtr->Serial[0].Address; - Bda->Com2 = SioPtr->Serial[1].Address; - Bda->Com3 = SioPtr->Serial[2].Address; - Bda->Com4 = SioPtr->Serial[3].Address; - - if (SioPtr->Serial[0].Address != 0x00) { - MachineConfig += 0x200; - } - - if (SioPtr->Serial[1].Address != 0x00) { - MachineConfig += 0x200; - } - - if (SioPtr->Serial[2].Address != 0x00) { - MachineConfig += 0x200; - } - - if (SioPtr->Serial[3].Address != 0x00) { - MachineConfig += 0x200; - } - - Bda->Lpt1 = SioPtr->Parallel[0].Address; - Bda->Lpt2 = SioPtr->Parallel[1].Address; - Bda->Lpt3 = SioPtr->Parallel[2].Address; - - if (SioPtr->Parallel[0].Address != 0x00) { - MachineConfig += 0x4000; - } - - if (SioPtr->Parallel[1].Address != 0x00) { - MachineConfig += 0x4000; - } - - if (SioPtr->Parallel[2].Address != 0x00) { - MachineConfig += 0x4000; - } - - Bda->NumberOfDrives = (UINT8) (Bda->NumberOfDrives + Private->IdeDriveCount); - if (SioPtr->Floppy.NumberOfFloppy != 0x00) { - MachineConfig = (UINT16) (MachineConfig + 0x01 + (SioPtr->Floppy.NumberOfFloppy - 1) * 0x40); - Bda->FloppyXRate = 0x07; - } - - Bda->Lpt1_2Timeout = 0x1414; - Bda->Lpt3_4Timeout = 0x1414; - Bda->Com1_2Timeout = 0x0101; - Bda->Com3_4Timeout = 0x0101; - - // - // Force VGA and Coprocessor, indicate 101/102 keyboard - // - MachineConfig = (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr->MousePresent * 0x04)); - Bda->MachineConfig = MachineConfig; - - return EFI_SUCCESS; -} - -/** - Fill in the standard BDA for Keyboard LEDs - - @param This Protocol instance pointer. - @param Leds Current LED status - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -EFIAPI -LegacyBiosUpdateKeyboardLedStatus ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT8 Leds - ) -{ - LEGACY_BIOS_INSTANCE *Private; - BDA_STRUC *Bda; - UINT8 LocalLeds; - EFI_IA32_REGISTER_SET Regs; - - Bda = (BDA_STRUC *) ((UINTN) 0x400); - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - LocalLeds = Leds; - Bda->LedStatus = (UINT8) ((Bda->LedStatus &~0x07) | LocalLeds); - LocalLeds = (UINT8) (LocalLeds << 4); - Bda->ShiftStatus = (UINT8) ((Bda->ShiftStatus &~0x70) | LocalLeds); - LocalLeds = (UINT8) (Leds & 0x20); - Bda->KeyboardStatus = (UINT8) ((Bda->KeyboardStatus &~0x20) | LocalLeds); - // - // Call into Legacy16 code to allow it to do any processing - // - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - Regs.X.AX = Legacy16SetKeyboardLeds; - Regs.H.CL = Leds; - - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Private->Legacy16Table->Compatibility16CallSegment, - Private->Legacy16Table->Compatibility16CallOffset, - &Regs, - NULL, - 0 - ); - - return EFI_SUCCESS; -} - - -/** - Fill in the standard CMOS stuff prior to legacy Boot - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosCompleteStandardCmosBeforeBoot ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - UINT8 Bda; - UINT8 Floppy; - UINT32 Size; - - // - // Update CMOS locations - // 10 floppy - // 12,19,1A - ignore as OS don't use them and there is no standard due - // to large capacity drives - // CMOS 14 = BDA 40:10 plus bit 3(display enabled) - // - Bda = (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3); - - // - // Force display enabled - // - Floppy = 0x00; - if ((Bda & BIT0) != 0) { - Floppy = BIT6; - } - - // - // Check if 2.88MB floppy set - // - if ((Bda & (BIT7 | BIT6)) != 0) { - Floppy = (UINT8)(Floppy | BIT1); - } - - LegacyWriteStandardCmos (CMOS_10, Floppy); - LegacyWriteStandardCmos (CMOS_14, Bda); - - // - // Force Status Register A to set rate selection bits and divider - // - LegacyWriteStandardCmos (CMOS_0A, 0x26); - - // - // redo memory size since it can change - // - Size = (15 * SIZE_1MB) >> 10; - if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) { - Size = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10; - } - - LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF)); - LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF)); - LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8)); - LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8)); - - LegacyCalculateWriteStandardCmosChecksum (); - - return EFI_SUCCESS; -} - -/** - Relocate this image under 4G memory for IPF. - - @param ImageHandle Handle of driver image. - @param SystemTable Pointer to system table. - - @retval EFI_SUCCESS Image successfully relocated. - @retval EFI_ABORTED Failed to relocate image. - -**/ -EFI_STATUS -RelocateImageUnder4GIfNeeded ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c deleted file mode 100644 index 0fbf902813..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c +++ /dev/null @@ -1,124 +0,0 @@ -/** @file - This code fills in standard CMOS values and updates the standard CMOS - checksum. The Legacy16 code or LegacyBiosPlatform.c is responsible for - non-standard CMOS locations and non-standard checksums. - -Copyright (c) 2006 - 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 "LegacyBiosInterface.h" - -/** - Read CMOS register through index/data port. - - @param[in] Index The index of the CMOS register to read. - - @return The data value from the CMOS register specified by Index. - -**/ -UINT8 -LegacyReadStandardCmos ( - IN UINT8 Index - ) -{ - IoWrite8 (PORT_70, Index); - return IoRead8 (PORT_71); -} - -/** - Write CMOS register through index/data port. - - @param[in] Index The index of the CMOS register to write. - @param[in] Value The value of CMOS register to write. - - @return The value written to the CMOS register specified by Index. - -**/ -UINT8 -LegacyWriteStandardCmos ( - IN UINT8 Index, - IN UINT8 Value - ) -{ - IoWrite8 (PORT_70, Index); - return IoWrite8 (PORT_71, Value); -} - -/** - Calculate the new standard CMOS checksum and write it. - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS Calculate 16-bit checksum successfully - -**/ -EFI_STATUS -LegacyCalculateWriteStandardCmosChecksum ( - VOID - ) -{ - UINT8 Register; - UINT16 Checksum; - - for (Checksum = 0, Register = 0x10; Register < 0x2e; Register++) { - Checksum = (UINT16)(Checksum + LegacyReadStandardCmos (Register)); - } - LegacyWriteStandardCmos (CMOS_2E, (UINT8)(Checksum >> 8)); - LegacyWriteStandardCmos (CMOS_2F, (UINT8)(Checksum & 0xff)); - return EFI_SUCCESS; -} - - -/** - Fill in the standard CMOS stuff before Legacy16 load - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosInitCmos ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - UINT32 Size; - - // - // Clear all errors except RTC lost power - // - LegacyWriteStandardCmos (CMOS_0E, (UINT8)(LegacyReadStandardCmos (CMOS_0E) & BIT7)); - - // - // Update CMOS locations 15,16,17,18,30,31 and 32 - // CMOS 16,15 = 640Kb = 0x280 - // CMOS 18,17 = 31,30 = 15Mb max in 1Kb increments =0x3C00 max - // CMOS 32 = 0x20 - // - LegacyWriteStandardCmos (CMOS_15, 0x80); - LegacyWriteStandardCmos (CMOS_16, 0x02); - - Size = 15 * SIZE_1MB; - if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) { - Size = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10; - } - - LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF)); - LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF)); - LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8)); - LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8)); - - LegacyCalculateWriteStandardCmosChecksum (); - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c deleted file mode 100644 index 4d520f8a32..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c +++ /dev/null @@ -1,317 +0,0 @@ -/** @file - Collect IDE information from Native EFI Driver - -Copyright (c) 2006 - 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 "LegacyBiosInterface.h" - -BOOLEAN mIdeDataBuiltFlag = FALSE; - -/** - Collect IDE Inquiry data from the IDE disks - - @param Private Legacy BIOS Instance data - @param HddInfo Hdd Information - @param Flag Reconnect IdeController or not - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosBuildIdeData ( - IN LEGACY_BIOS_INSTANCE *Private, - IN HDD_INFO **HddInfo, - IN UINT16 Flag - ) -{ - EFI_STATUS Status; - EFI_HANDLE IdeController; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINTN Index; - EFI_DISK_INFO_PROTOCOL *DiskInfo; - UINT32 IdeChannel; - UINT32 IdeDevice; - UINT32 Size; - UINT8 *InquiryData; - UINT32 InquiryDataSize; - HDD_INFO *LocalHddInfo; - UINT32 PciIndex; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; - EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode; - PCI_DEVICE_PATH *PciDevicePath; - - // - // Only build data once - // We have a problem with GetBbsInfo in that it can be invoked two - // places. Once in BDS, when all EFI drivers are connected and once in - // LegacyBoot after all EFI drivers are disconnected causing this routine - // to hang. In LegacyBoot this function is also called before EFI drivers - // are disconnected. - // Cases covered - // GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored. - // GetBbsInfo not invoked in BDS. First invocation of this function - // proceeds normally and second via GetBbsInfo ignored. - // - PciDevicePath = NULL; - LocalHddInfo = *HddInfo; - Status = Private->LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformIdeHandle, - 0, - &HandleBuffer, - &HandleCount, - (VOID *) &LocalHddInfo - ); - if (!EFI_ERROR (Status)) { - IdeController = HandleBuffer[0]; - // - // Force IDE drive spin up! - // - if (Flag != 0) { - gBS->DisconnectController ( - IdeController, - NULL, - NULL - ); - } - - gBS->ConnectController (IdeController, NULL, NULL, FALSE); - - // - // Do GetIdeHandle twice since disconnect/reconnect will switch to native mode - // And GetIdeHandle will switch to Legacy mode, if required. - // - Private->LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformIdeHandle, - 0, - &HandleBuffer, - &HandleCount, - (VOID *) &LocalHddInfo - ); - } - - mIdeDataBuiltFlag = TRUE; - - // - // Get Identity command from all drives - // - gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiDiskInfoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - - Private->IdeDriveCount = (UINT8) HandleCount; - for (Index = 0; Index < HandleCount; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiDiskInfoProtocolGuid, - (VOID **) &DiskInfo - ); - ASSERT_EFI_ERROR (Status); - - if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) { - // - // Locate which PCI device - // - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiDevicePathProtocolGuid, - (VOID *) &DevicePath - ); - ASSERT_EFI_ERROR (Status); - - DevicePathNode = DevicePath; - while (!IsDevicePathEnd (DevicePathNode)) { - TempDevicePathNode = NextDevicePathNode (DevicePathNode); - if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) && - ( DevicePathSubType (DevicePathNode) == HW_PCI_DP) && - ( DevicePathType(TempDevicePathNode) == MESSAGING_DEVICE_PATH) && - ( DevicePathSubType(TempDevicePathNode) == MSG_ATAPI_DP) ) { - PciDevicePath = (PCI_DEVICE_PATH *) DevicePathNode; - break; - } - DevicePathNode = NextDevicePathNode (DevicePathNode); - } - - if (PciDevicePath == NULL) { - continue; - } - - // - // Find start of PCI device in HddInfo. The assumption of the data - // structure is 2 controllers(channels) per PCI device and each - // controller can have 2 drives(devices). - // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master - // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave - // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master - // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave - // @bug eventually need to pass in max number of entries - // for end of for loop - // - for (PciIndex = 0; PciIndex < 8; PciIndex++) { - if ((PciDevicePath->Device == LocalHddInfo[PciIndex].Device) && - (PciDevicePath->Function == LocalHddInfo[PciIndex].Function) - ) { - break; - } - } - - if (PciIndex == 8) { - continue; - } - - Status = DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice); - if (!EFI_ERROR (Status)) { - Size = sizeof (ATAPI_IDENTIFY); - DiskInfo->Identify ( - DiskInfo, - &LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[IdeDevice], - &Size - ); - if (IdeChannel == 0) { - LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_PRIMARY; - } else if (IdeChannel == 1) { - LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SECONDARY; - } - - InquiryData = NULL; - InquiryDataSize = 0; - Status = DiskInfo->Inquiry ( - DiskInfo, - NULL, - &InquiryDataSize - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - InquiryData = (UINT8 *) AllocatePool ( - InquiryDataSize - ); - if (InquiryData != NULL) { - Status = DiskInfo->Inquiry ( - DiskInfo, - InquiryData, - &InquiryDataSize - ); - } - } else { - Status = EFI_DEVICE_ERROR; - } - - // - // If ATAPI device then Inquiry will pass and ATA fail. - // - if (!EFI_ERROR (Status)) { - ASSERT (InquiryData != NULL); - // - // If IdeDevice = 0 then set master bit, else slave bit - // - if (IdeDevice == 0) { - if ((InquiryData[0] & 0x1f) == 0x05) { - LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_CDROM; - } else if ((InquiryData[0] & 0x1f) == 0x00) { - LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_ZIPDISK; - } - } else { - if ((InquiryData[0] & 0x1f) == 0x05) { - LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_CDROM; - } else if ((InquiryData[0] & 0x1f) == 0x00) { - LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_ZIPDISK; - } - } - FreePool (InquiryData); - } else { - if (IdeDevice == 0) { - LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_IDE; - } else { - LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_IDE; - } - } - } - } - } - - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - } - - return EFI_SUCCESS; -} - - -/** - If the IDE channel is in compatibility (legacy) mode, remove all - PCI I/O BAR addresses from the controller. - - @param IdeController The handle of target IDE controller - - -**/ -VOID -InitLegacyIdeController ( - IN EFI_HANDLE IdeController - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - UINT32 IOBarClear; - EFI_STATUS Status; - PCI_TYPE00 PciData; - - // - // If the IDE channel is in compatibility (legacy) mode, remove all - // PCI I/O BAR addresses from the controller. Some software gets - // confused if an IDE controller is in compatibility (legacy) mode - // and has PCI I/O resources allocated - // - Status = gBS->HandleProtocol ( - IdeController, - &gEfiPciIoProtocolGuid, - (VOID **)&PciIo - ); - if (EFI_ERROR (Status)) { - return ; - } - - Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (PciData), &PciData); - if (EFI_ERROR (Status)) { - return ; - } - - // - // Check whether this is IDE - // - if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) || - (PciData.Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) { - return ; - } - - // - // Clear bar for legacy IDE - // - IOBarClear = 0x00; - if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_PNE) == 0) { - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear); - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear); - } - if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_SNE) == 0) { - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear); - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear); - } - - return ; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c deleted file mode 100644 index 9d84ab0000..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c +++ /dev/null @@ -1,3007 +0,0 @@ -/** @file - -Copyright (c) 2006 - 2015, Intel 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 "LegacyBiosInterface.h" -#include - -#define PCI_START_ADDRESS(x) (((x) + 0x7ff) & ~0x7ff) - -#define MAX_BRIDGE_INDEX 0x20 -typedef struct { - UINTN PciSegment; - UINTN PciBus; - UINTN PciDevice; - UINTN PciFunction; - UINT8 PrimaryBus; - UINT8 SecondaryBus; - UINT8 SubordinateBus; -} BRIDGE_TABLE; - -#define ROM_MAX_ENTRIES 24 -BRIDGE_TABLE Bridges[MAX_BRIDGE_INDEX]; -UINTN SortedBridgeIndex[MAX_BRIDGE_INDEX]; -UINTN NumberOfBridges; -LEGACY_PNP_EXPANSION_HEADER *mBasePnpPtr; -UINT16 mBbsRomSegment; -UINTN mHandleCount; -EFI_HANDLE mVgaHandle; -BOOLEAN mIgnoreBbsUpdateFlag; -BOOLEAN mVgaInstallationInProgress = FALSE; -UINT32 mRomCount = 0x00; -ROM_INSTANCE_ENTRY mRomEntry[ROM_MAX_ENTRIES]; - - -/** - Query shadowed legacy ROM parameters registered by RomShadow() previously. - - @param PciHandle PCI device whos ROM has been shadowed - @param DiskStart DiskStart value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom - @param DiskEnd DiskEnd value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom - @param RomShadowAddress Address where ROM was shadowed - @param ShadowedSize Runtime size of ROM - - @retval EFI_SUCCESS Query Logging successful. - @retval EFI_NOT_FOUND No logged data found about PciHandle. - -**/ -EFI_STATUS -GetShadowedRomParameters ( - IN EFI_HANDLE PciHandle, - OUT UINT8 *DiskStart, OPTIONAL - OUT UINT8 *DiskEnd, OPTIONAL - OUT VOID **RomShadowAddress, OPTIONAL - OUT UINTN *ShadowedSize OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - UINTN Index; - UINTN PciSegment; - UINTN PciBus; - UINTN PciDevice; - UINTN PciFunction; - - // - // Get the PCI I/O Protocol on PciHandle - // - Status = gBS->HandleProtocol ( - PciHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the location of the PCI device - // - PciIo->GetLocation ( - PciIo, - &PciSegment, - &PciBus, - &PciDevice, - &PciFunction - ); - - for(Index = 0; Index < mRomCount; Index++) { - if ((mRomEntry[Index].PciSegment == PciSegment) && - (mRomEntry[Index].PciBus == PciBus) && - (mRomEntry[Index].PciDevice == PciDevice) && - (mRomEntry[Index].PciFunction == PciFunction)) { - break; - } - } - - if (Index == mRomCount) { - return EFI_NOT_FOUND; - } - - if (DiskStart != NULL) { - *DiskStart = mRomEntry[Index].DiskStart; - } - - if (DiskEnd != NULL) { - *DiskEnd = mRomEntry[Index].DiskEnd; - } - - if (RomShadowAddress != NULL) { - *RomShadowAddress = (VOID *)(UINTN)mRomEntry[Index].ShadowAddress; - } - - if (ShadowedSize != NULL) { - *ShadowedSize = mRomEntry[Index].ShadowedSize; - } - - return EFI_SUCCESS; -} - -/** - Every legacy ROM that is shadowed by the Legacy BIOS driver will be - registered into this API so that the policy code can know what has - happend - - @param PciHandle PCI device whos ROM is being shadowed - @param ShadowAddress Address that ROM was shadowed - @param ShadowedSize Runtime size of ROM - @param DiskStart DiskStart value from - EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom - @param DiskEnd DiskEnd value from - EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom - - @retval EFI_SUCCESS Logging successful. - @retval EFI_OUT_OF_RESOURCES No remaining room for registering another option - ROM. - -**/ -EFI_STATUS -RomShadow ( - IN EFI_HANDLE PciHandle, - IN UINT32 ShadowAddress, - IN UINT32 ShadowedSize, - IN UINT8 DiskStart, - IN UINT8 DiskEnd - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - - // - // See if there is room to register another option ROM - // - if (mRomCount >= ROM_MAX_ENTRIES) { - return EFI_OUT_OF_RESOURCES; - } - // - // Get the PCI I/O Protocol on PciHandle - // - Status = gBS->HandleProtocol ( - PciHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Get the location of the PCI device - // - PciIo->GetLocation ( - PciIo, - &mRomEntry[mRomCount].PciSegment, - &mRomEntry[mRomCount].PciBus, - &mRomEntry[mRomCount].PciDevice, - &mRomEntry[mRomCount].PciFunction - ); - mRomEntry[mRomCount].ShadowAddress = ShadowAddress; - mRomEntry[mRomCount].ShadowedSize = ShadowedSize; - mRomEntry[mRomCount].DiskStart = DiskStart; - mRomEntry[mRomCount].DiskEnd = DiskEnd; - - mRomCount++; - - return EFI_SUCCESS; -} - - -/** - Return EFI_SUCCESS if PciHandle has had a legacy BIOS ROM shadowed. This - information represents every call to RomShadow () - - @param PciHandle PCI device to get status for - - @retval EFI_SUCCESS Legacy ROM loaded for this device - @retval EFI_NOT_FOUND No Legacy ROM loaded for this device - -**/ -EFI_STATUS -IsLegacyRom ( - IN EFI_HANDLE PciHandle - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - UINTN Index; - UINTN Segment; - UINTN Bus; - UINTN Device; - UINTN Function; - - // - // Get the PCI I/O Protocol on PciHandle - // - Status = gBS->HandleProtocol ( - PciHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Get the location of the PCI device - // - PciIo->GetLocation ( - PciIo, - &Segment, - &Bus, - &Device, - &Function - ); - - // - // See if the option ROM from PciHandle has been previously posted - // - for (Index = 0; Index < mRomCount; Index++) { - if (mRomEntry[Index].PciSegment == Segment && - mRomEntry[Index].PciBus == Bus && - mRomEntry[Index].PciDevice == Device && - mRomEntry[Index].PciFunction == Function - ) { - return EFI_SUCCESS; - } - } - - return EFI_NOT_FOUND; -} - -/** - Find the PC-AT ROM Image in the raw PCI Option ROM. Also return the - related information from the header. - - @param Csm16Revision The PCI interface version of underlying CSM16 - @param VendorId Vendor ID of the PCI device - @param DeviceId Device ID of the PCI device - @param Rom On input pointing to beginning of the raw PCI OpROM - On output pointing to the first legacy PCI OpROM - @param ImageSize On input is the size of Raw PCI Rom - On output is the size of the first legacy PCI ROM - @param MaxRuntimeImageLength The max runtime image length only valid if OpRomRevision >= 3 - @param OpRomRevision Revision of the PCI Rom - @param ConfigUtilityCodeHeader Pointer to Configuration Utility Code Header - - @retval EFI_SUCCESS Successfully find the legacy PCI ROM - @retval EFI_NOT_FOUND Failed to find the legacy PCI ROM - -**/ -EFI_STATUS -GetPciLegacyRom ( - IN UINT16 Csm16Revision, - IN UINT16 VendorId, - IN UINT16 DeviceId, - IN OUT VOID **Rom, - IN OUT UINTN *ImageSize, - OUT UINTN *MaxRuntimeImageLength, OPTIONAL - OUT UINT8 *OpRomRevision, OPTIONAL - OUT VOID **ConfigUtilityCodeHeader OPTIONAL - ) -{ - BOOLEAN Match; - UINT16 *DeviceIdList; - EFI_PCI_ROM_HEADER RomHeader; - PCI_3_0_DATA_STRUCTURE *Pcir; - VOID *BackupImage; - VOID *BestImage; - - - if (*ImageSize < sizeof (EFI_PCI_ROM_HEADER)) { - return EFI_NOT_FOUND; - } - - BestImage = NULL; - BackupImage = NULL; - RomHeader.Raw = *Rom; - while (RomHeader.Generic->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE) { - if (RomHeader.Generic->PcirOffset == 0 || - (RomHeader.Generic->PcirOffset & 3) !=0 || - *ImageSize < RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->PcirOffset + sizeof (PCI_DATA_STRUCTURE)) { - break; - } - - Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset); - // - // Check signature in the PCI Data Structure. - // - if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { - break; - } - - if ((UINTN)(RomHeader.Raw - (UINT8 *) *Rom) + Pcir->ImageLength * 512 > *ImageSize) { - break; - } - - if (Pcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) { - Match = FALSE; - if (Pcir->VendorId == VendorId) { - if (Pcir->DeviceId == DeviceId) { - Match = TRUE; - } else if ((Pcir->Revision >= 3) && (Pcir->DeviceListOffset != 0)) { - DeviceIdList = (UINT16 *)(((UINT8 *) Pcir) + Pcir->DeviceListOffset); - // - // Checking the device list - // - while (*DeviceIdList != 0) { - if (*DeviceIdList == DeviceId) { - Match = TRUE; - break; - } - DeviceIdList ++; - } - } - } - - if (Match) { - if (Csm16Revision >= 0x0300) { - // - // Case 1: CSM16 3.0 - // - if (Pcir->Revision >= 3) { - // - // case 1.1: meets OpRom 3.0 - // Perfect!!! - // - BestImage = RomHeader.Raw; - break; - } else { - // - // case 1.2: meets OpRom 2.x - // Store it and try to find the OpRom 3.0 - // - BackupImage = RomHeader.Raw; - } - } else { - // - // Case 2: CSM16 2.x - // - if (Pcir->Revision >= 3) { - // - // case 2.1: meets OpRom 3.0 - // Store it and try to find the OpRom 2.x - // - BackupImage = RomHeader.Raw; - } else { - // - // case 2.2: meets OpRom 2.x - // Perfect!!! - // - BestImage = RomHeader.Raw; - break; - } - } - } else { - DEBUG ((EFI_D_ERROR, "GetPciLegacyRom - OpRom not match (%04x-%04x)\n", (UINTN)VendorId, (UINTN)DeviceId)); - } - } - - if ((Pcir->Indicator & 0x80) == 0x80) { - break; - } else { - RomHeader.Raw += 512 * Pcir->ImageLength; - } - } - - if (BestImage == NULL) { - if (BackupImage == NULL) { - return EFI_NOT_FOUND; - } - // - // The versions of CSM16 and OpRom don't match exactly - // - BestImage = BackupImage; - } - RomHeader.Raw = BestImage; - Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset); - *Rom = BestImage; - *ImageSize = Pcir->ImageLength * 512; - - if (MaxRuntimeImageLength != NULL) { - if (Pcir->Revision < 3) { - *MaxRuntimeImageLength = 0; - } else { - *MaxRuntimeImageLength = Pcir->MaxRuntimeImageLength * 512; - } - } - - if (OpRomRevision != NULL) { - // - // Optional return PCI Data Structure revision - // - if (Pcir->Length >= 0x1C) { - *OpRomRevision = Pcir->Revision; - } else { - *OpRomRevision = 0; - } - } - - if (ConfigUtilityCodeHeader != NULL) { - // - // Optional return ConfigUtilityCodeHeaderOffset supported by the PC-AT ROM - // - if ((Pcir->Revision < 3) || (Pcir->ConfigUtilityCodeHeaderOffset == 0)) { - *ConfigUtilityCodeHeader = NULL; - } else { - *ConfigUtilityCodeHeader = RomHeader.Raw + Pcir->ConfigUtilityCodeHeaderOffset; - } - } - - return EFI_SUCCESS; -} - -/** - Build a table of bridge info for PIRQ translation. - - @param RoutingTable RoutingTable obtained from Platform. - @param RoutingTableEntries Number of RoutingTable entries. - - @retval EFI_SUCCESS New Subordinate bus. - @retval EFI_NOT_FOUND No more Subordinate busses. - -**/ -EFI_STATUS -CreateBridgeTable ( - IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, - IN UINTN RoutingTableEntries - ) -{ - EFI_STATUS Status; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINTN BridgeIndex; - UINTN Index; - UINTN Index1; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE01 PciConfigHeader; - BRIDGE_TABLE SlotBridges[MAX_BRIDGE_INDEX]; - UINTN SlotBridgeIndex; - - BridgeIndex = 0x00; - SlotBridgeIndex = 0x00; - - // - // Assumption is table is built from low bus to high bus numbers. - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - for (Index = 0; Index < HandleCount; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - if (EFI_ERROR (Status)) { - continue; - } - - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (PciConfigHeader) / sizeof (UINT32), - &PciConfigHeader - ); - - if (IS_PCI_P2P (&PciConfigHeader) && (BridgeIndex < MAX_BRIDGE_INDEX)) { - PciIo->GetLocation ( - PciIo, - &Bridges[BridgeIndex].PciSegment, - &Bridges[BridgeIndex].PciBus, - &Bridges[BridgeIndex].PciDevice, - &Bridges[BridgeIndex].PciFunction - ); - - Bridges[BridgeIndex].PrimaryBus = PciConfigHeader.Bridge.PrimaryBus; - - Bridges[BridgeIndex].SecondaryBus = PciConfigHeader.Bridge.SecondaryBus; - - Bridges[BridgeIndex].SubordinateBus = PciConfigHeader.Bridge.SubordinateBus; - - for (Index1 = 0; Index1 < RoutingTableEntries; Index1++){ - // - // Test whether we have found the Bridge in the slot, must be the one that directly interfaced to the board - // Once we find one, store it in the SlotBridges[] - // - if ((RoutingTable[Index1].Slot != 0) && (Bridges[BridgeIndex].PrimaryBus == RoutingTable[Index1].Bus) - && ((Bridges[BridgeIndex].PciDevice << 3) == RoutingTable[Index1].Device)) { - CopyMem (&SlotBridges[SlotBridgeIndex], &Bridges[BridgeIndex], sizeof (BRIDGE_TABLE)); - SlotBridgeIndex++; - - break; - } - } - - ++BridgeIndex; - } - } - - // - // Pack up Bridges by removing those useless ones - // - for (Index = 0; Index < BridgeIndex;){ - for (Index1 = 0; Index1 < SlotBridgeIndex; Index1++) { - if (((Bridges[Index].PciBus == SlotBridges[Index1].PrimaryBus) && (Bridges[Index].PciDevice == SlotBridges[Index1].PciDevice)) || - ((Bridges[Index].PciBus >= SlotBridges[Index1].SecondaryBus) && (Bridges[Index].PciBus <= SlotBridges[Index1].SubordinateBus))) { - // - // We have found one that meets our criteria - // - Index++; - break; - } - } - - // - // This one doesn't meet criteria, pack it - // - if (Index1 >= SlotBridgeIndex) { - for (Index1 = Index; BridgeIndex > 1 && Index1 < BridgeIndex - 1 ; Index1++) { - CopyMem (&Bridges[Index1], &Bridges[Index1 + 1], sizeof (BRIDGE_TABLE)); - } - - BridgeIndex--; - } - } - - NumberOfBridges = BridgeIndex; - - // - // Sort bridges low to high by Secondary bus followed by subordinate bus - // - if (NumberOfBridges > 1) { - Index = 0; - do { - SortedBridgeIndex[Index] = Index; - ++Index; - } while (Index < NumberOfBridges); - - for (Index = 0; Index < NumberOfBridges - 1; Index++) { - for (Index1 = Index + 1; Index1 < NumberOfBridges; Index1++) { - if (Bridges[Index].SecondaryBus > Bridges[Index1].SecondaryBus) { - SortedBridgeIndex[Index] = Index1; - SortedBridgeIndex[Index1] = Index; - } - - if ((Bridges[Index].SecondaryBus == Bridges[Index1].SecondaryBus) && - (Bridges[Index].SubordinateBus > Bridges[Index1].SubordinateBus) - ) { - SortedBridgeIndex[Index] = Index1; - SortedBridgeIndex[Index1] = Index; - } - } - } - } - FreePool (HandleBuffer); - return EFI_SUCCESS; -} - - -/** - Find base Bridge for device. - - @param Private Legacy BIOS Instance data - @param PciBus Input = Bus of device. - @param PciDevice Input = Device. - @param RoutingTable The platform specific routing table - @param RoutingTableEntries Number of entries in table - - @retval EFI_SUCCESS At base bus. - @retval EFI_NOT_FOUND Behind a bridge. - -**/ -EFI_STATUS -GetBaseBus ( - IN LEGACY_BIOS_INSTANCE *Private, - IN UINTN PciBus, - IN UINTN PciDevice, - IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, - IN UINTN RoutingTableEntries - ) -{ - UINTN Index; - for (Index = 0; Index < RoutingTableEntries; Index++) { - if ((RoutingTable[Index].Bus == PciBus) && (RoutingTable[Index].Device == (PciDevice << 3))) { - return EFI_SUCCESS; - } - } - - return EFI_NOT_FOUND; -} - -/** - Translate PIRQ through busses - - @param Private Legacy BIOS Instance data - @param PciBus Input = Bus of device. Output = Translated Bus - @param PciDevice Input = Device. Output = Translated Device - @param PciFunction Input = Function. Output = Translated Function - @param PirqIndex Input = Original PIRQ index. If single function - device then 0, otherwise 0-3. - Output = Translated Index - - @retval EFI_SUCCESS Pirq successfully translated. - @retval EFI_NOT_FOUND The device is not behind any known bridge. - -**/ -EFI_STATUS -TranslateBusPirq ( - IN LEGACY_BIOS_INSTANCE *Private, - IN OUT UINTN *PciBus, - IN OUT UINTN *PciDevice, - IN OUT UINTN *PciFunction, - IN OUT UINT8 *PirqIndex - ) -{ - /* - This routine traverses the PCI busses from base slot - and translates the PIRQ register to the appropriate one. - - Example: - - Bus 0, Device 1 is PCI-PCI bridge that all PCI slots reside on. - Primary bus# = 0 - Secondary bus # = 1 - Subordinate bus # is highest bus # behind this bus - Bus 1, Device 0 is Slot 0 and is not a bridge. - Bus 1, Device 1 is Slot 1 and is a bridge. - Slot PIRQ routing is A,B,C,D. - Primary bus # = 1 - Secondary bus # = 2 - Subordinate bus # = 5 - Bus 2, Device 6 is a bridge. It has no bridges behind it. - Primary bus # = 2 - Secondary bus # = 3 - Subordinate bus # = 3 - Bridge PIRQ routing is C,D,A,B - Bus 2, Device 7 is a bridge. It has 1 bridge behind it. - Primary bus # = 2 - Secondary bus = 4 Device 6 takes bus 2. - Subordinate bus = 5. - Bridge PIRQ routing is D,A,B,C - Bus 4, Device 2 is a bridge. It has no bridges behind it. - Primary bus # = 4 - Secondary bus # = 5 - Subordinate bus = 5 - Bridge PIRQ routing is B,C,D,A - Bus 5, Device 1 is to be programmed. - Device PIRQ routing is C,D,A,B - - -Search busses starting from slot bus for final bus >= Secondary bus and -final bus <= Suborninate bus. Assumption is bus entries increase in bus -number. -Starting PIRQ is A,B,C,D. -Bus 2, Device 7 satisfies search criteria. Rotate (A,B,C,D) left by device - 7 modulo 4 giving (D,A,B,C). -Bus 4, Device 2 satisfies search criteria. Rotate (D,A,B,C) left by 2 giving - (B,C,D,A). -No other busses match criteria. Device to be programmed is Bus 5, Device 1. -Rotate (B,C,D,A) by 1 giving C,D,A,B. Translated PIRQ is C. - -*/ - UINTN LocalBus; - UINTN LocalDevice; - UINTN BaseBus; - UINTN BaseDevice; - UINTN BaseFunction; - UINT8 LocalPirqIndex; - BOOLEAN BaseIndexFlag; - UINTN BridgeIndex; - UINTN SBridgeIndex; - BaseIndexFlag = FALSE; - BridgeIndex = 0x00; - - LocalPirqIndex = *PirqIndex; - LocalBus = *PciBus; - LocalDevice = *PciDevice; - BaseBus = *PciBus; - BaseDevice = *PciDevice; - BaseFunction = *PciFunction; - - // - // LocalPirqIndex list PIRQs in rotated fashion - // = 0 A,B,C,D - // = 1 B,C,D,A - // = 2 C,D,A,B - // = 3 D,A,B,C - // - - for (BridgeIndex = 0; BridgeIndex < NumberOfBridges; BridgeIndex++) { - SBridgeIndex = SortedBridgeIndex[BridgeIndex]; - // - // Check if device behind this bridge - // - if ((LocalBus >= Bridges[SBridgeIndex].SecondaryBus) && (LocalBus <= Bridges[SBridgeIndex].SubordinateBus)) { - // - // If BaseIndexFlag = FALSE then have found base bridge, i.e - // bridge in slot. Save info for use by IRQ routing table. - // - if (!BaseIndexFlag) { - BaseBus = Bridges[SBridgeIndex].PciBus; - BaseDevice = Bridges[SBridgeIndex].PciDevice; - BaseFunction = Bridges[SBridgeIndex].PciFunction; - BaseIndexFlag = TRUE; - } else { - LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8)Bridges[SBridgeIndex].PciDevice)%4); - } - - // - // Check if at device. If not get new PCI location & PIRQ - // - if (Bridges[SBridgeIndex].SecondaryBus == (UINT8) LocalBus) { - // - // Translate PIRQ - // - LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8) (LocalDevice)) % 4); - break; - } - } - } - - // - // In case we fail to find the Bridge just above us, this is some potential error and we want to warn the user - // - if(BridgeIndex >= NumberOfBridges){ - DEBUG ((EFI_D_ERROR, "Cannot Find IRQ Routing for Bus %d, Device %d, Function %d\n", *PciBus, *PciDevice, *PciFunction)); - } - - *PirqIndex = LocalPirqIndex; - *PciBus = BaseBus; - *PciDevice = BaseDevice; - *PciFunction = BaseFunction; - - return EFI_SUCCESS; -} - - -/** - Copy the $PIR table as required. - - @param Private Legacy BIOS Instance data - @param RoutingTable Pointer to IRQ routing table - @param RoutingTableEntries IRQ routing table entries - @param PirqTable Pointer to $PIR table - @param PirqTableSize Length of table - -**/ -VOID -CopyPirqTable ( - IN LEGACY_BIOS_INSTANCE *Private, - IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, - IN UINTN RoutingTableEntries, - IN EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable, - IN UINTN PirqTableSize - ) -{ - EFI_IA32_REGISTER_SET Regs; - UINT32 Granularity; - - // - // Copy $PIR table, if it exists. - // - if (PirqTable != NULL) { - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - 0xE0000, - 0x20000, - &Granularity - ); - - Private->InternalIrqRoutingTable = RoutingTable; - Private->NumberIrqRoutingEntries = (UINT16) (RoutingTableEntries); - ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); - - Regs.X.AX = Legacy16GetTableAddress; - Regs.X.CX = (UINT16) PirqTableSize; - // - // Allocate at F segment according to PCI IRQ Routing Table Specification - // - Regs.X.BX = (UINT16) 0x1; - // - // 16-byte boundary alignment requirement according to - // PCI IRQ Routing Table Specification - // - Regs.X.DX = 0x10; - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Private->Legacy16CallSegment, - Private->Legacy16CallOffset, - &Regs, - NULL, - 0 - ); - - Private->Legacy16Table->IrqRoutingTablePointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX); - if (Regs.X.AX != 0) { - DEBUG ((EFI_D_ERROR, "PIRQ table length insufficient - %x\n", PirqTableSize)); - } else { - DEBUG ((EFI_D_INFO, "PIRQ table in legacy region - %x\n", Private->Legacy16Table->IrqRoutingTablePointer)); - Private->Legacy16Table->IrqRoutingTableLength = (UINT32)PirqTableSize; - CopyMem ( - (VOID *) (UINTN)Private->Legacy16Table->IrqRoutingTablePointer, - PirqTable, - PirqTableSize - ); - } - - Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); - Private->LegacyRegion->Lock ( - Private->LegacyRegion, - 0xE0000, - 0x20000, - &Granularity - ); - } - - Private->PciInterruptLine = TRUE; - mHandleCount = 0; -} - -/** - Dump EFI_LEGACY_INSTALL_PCI_HANDLER structure information. - - @param PciHandle The pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure - -**/ -VOID -DumpPciHandle ( - IN EFI_LEGACY_INSTALL_PCI_HANDLER *PciHandle - ) -{ - DEBUG ((EFI_D_INFO, "PciBus - %02x\n", (UINTN)PciHandle->PciBus)); - DEBUG ((EFI_D_INFO, "PciDeviceFun - %02x\n", (UINTN)PciHandle->PciDeviceFun)); - DEBUG ((EFI_D_INFO, "PciSegment - %02x\n", (UINTN)PciHandle->PciSegment)); - DEBUG ((EFI_D_INFO, "PciClass - %02x\n", (UINTN)PciHandle->PciClass)); - DEBUG ((EFI_D_INFO, "PciSubclass - %02x\n", (UINTN)PciHandle->PciSubclass)); - DEBUG ((EFI_D_INFO, "PciInterface - %02x\n", (UINTN)PciHandle->PciInterface)); - - DEBUG ((EFI_D_INFO, "PrimaryIrq - %02x\n", (UINTN)PciHandle->PrimaryIrq)); - DEBUG ((EFI_D_INFO, "PrimaryReserved - %02x\n", (UINTN)PciHandle->PrimaryReserved)); - DEBUG ((EFI_D_INFO, "PrimaryControl - %04x\n", (UINTN)PciHandle->PrimaryControl)); - DEBUG ((EFI_D_INFO, "PrimaryBase - %04x\n", (UINTN)PciHandle->PrimaryBase)); - DEBUG ((EFI_D_INFO, "PrimaryBusMaster - %04x\n", (UINTN)PciHandle->PrimaryBusMaster)); - - DEBUG ((EFI_D_INFO, "SecondaryIrq - %02x\n", (UINTN)PciHandle->SecondaryIrq)); - DEBUG ((EFI_D_INFO, "SecondaryReserved - %02x\n", (UINTN)PciHandle->SecondaryReserved)); - DEBUG ((EFI_D_INFO, "SecondaryControl - %04x\n", (UINTN)PciHandle->SecondaryControl)); - DEBUG ((EFI_D_INFO, "SecondaryBase - %04x\n", (UINTN)PciHandle->SecondaryBase)); - DEBUG ((EFI_D_INFO, "SecondaryBusMaster - %04x\n", (UINTN)PciHandle->SecondaryBusMaster)); - return; -} - -/** - Copy the $PIR table as required. - - @param Private Legacy BIOS Instance data - @param PciIo Pointer to PCI_IO protocol - @param PciIrq Pci IRQ number - @param PciConfigHeader Type00 Pci configuration header - -**/ -VOID -InstallLegacyIrqHandler ( - IN LEGACY_BIOS_INSTANCE *Private, - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT8 PciIrq, - IN PCI_TYPE00 *PciConfigHeader - ) -{ - EFI_IA32_REGISTER_SET Regs; - UINT16 LegMask; - UINTN PciSegment; - UINTN PciBus; - UINTN PciDevice; - UINTN PciFunction; - EFI_LEGACY_8259_PROTOCOL *Legacy8259; - UINT16 PrimaryMaster; - UINT16 SecondaryMaster; - UINTN TempData; - UINTN RegisterAddress; - UINT32 Granularity; - - PrimaryMaster = 0; - SecondaryMaster = 0; - Legacy8259 = Private->Legacy8259; - // - // Disable interrupt in PIC, in case shared, to prevent an - // interrupt from occuring. - // - Legacy8259->GetMask ( - Legacy8259, - &LegMask, - NULL, - NULL, - NULL - ); - - LegMask = (UINT16) (LegMask | (UINT16) (1 << PciIrq)); - - Legacy8259->SetMask ( - Legacy8259, - &LegMask, - NULL, - NULL, - NULL - ); - - PciIo->GetLocation ( - PciIo, - &PciSegment, - &PciBus, - &PciDevice, - &PciFunction - ); - Private->IntThunk->PciHandler.PciBus = (UINT8) PciBus; - Private->IntThunk->PciHandler.PciDeviceFun = (UINT8) ((PciDevice << 3) + PciFunction); - Private->IntThunk->PciHandler.PciSegment = (UINT8) PciSegment; - Private->IntThunk->PciHandler.PciClass = PciConfigHeader->Hdr.ClassCode[2]; - Private->IntThunk->PciHandler.PciSubclass = PciConfigHeader->Hdr.ClassCode[1]; - Private->IntThunk->PciHandler.PciInterface = PciConfigHeader->Hdr.ClassCode[0]; - - // - // Use native mode base address registers in two cases: - // 1. Programming Interface (PI) register indicates Primary Controller is - // in native mode OR - // 2. PCI device Sub Class Code is not IDE - // - Private->IntThunk->PciHandler.PrimaryBusMaster = (UINT16)(PciConfigHeader->Device.Bar[4] & 0xfffc); - if (((PciConfigHeader->Hdr.ClassCode[0] & 0x01) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) { - Private->IntThunk->PciHandler.PrimaryIrq = PciIrq; - Private->IntThunk->PciHandler.PrimaryBase = (UINT16) (PciConfigHeader->Device.Bar[0] & 0xfffc); - Private->IntThunk->PciHandler.PrimaryControl = (UINT16) ((PciConfigHeader->Device.Bar[1] & 0xfffc) + 2); - } else { - Private->IntThunk->PciHandler.PrimaryIrq = 14; - Private->IntThunk->PciHandler.PrimaryBase = 0x1f0; - Private->IntThunk->PciHandler.PrimaryControl = 0x3f6; - } - // - // Secondary controller data - // - if (Private->IntThunk->PciHandler.PrimaryBusMaster != 0) { - Private->IntThunk->PciHandler.SecondaryBusMaster = (UINT16) ((PciConfigHeader->Device.Bar[4] & 0xfffc) + 8); - PrimaryMaster = (UINT16) (Private->IntThunk->PciHandler.PrimaryBusMaster + 2); - SecondaryMaster = (UINT16) (Private->IntThunk->PciHandler.SecondaryBusMaster + 2); - - // - // Clear pending interrupts in Bus Master registers - // - IoWrite16 (PrimaryMaster, 0x04); - IoWrite16 (SecondaryMaster, 0x04); - - } - - // - // Use native mode base address registers in two cases: - // 1. Programming Interface (PI) register indicates Secondary Controller is - // in native mode OR - // 2. PCI device Sub Class Code is not IDE - // - if (((PciConfigHeader->Hdr.ClassCode[0] & 0x04) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) { - Private->IntThunk->PciHandler.SecondaryIrq = PciIrq; - Private->IntThunk->PciHandler.SecondaryBase = (UINT16) (PciConfigHeader->Device.Bar[2] & 0xfffc); - Private->IntThunk->PciHandler.SecondaryControl = (UINT16) ((PciConfigHeader->Device.Bar[3] & 0xfffc) + 2); - } else { - - Private->IntThunk->PciHandler.SecondaryIrq = 15; - Private->IntThunk->PciHandler.SecondaryBase = 0x170; - Private->IntThunk->PciHandler.SecondaryControl = 0x376; - } - - // - // Clear pending interrupts in IDE Command Block Status reg before we - // Thunk to CSM16 below. Don't want a pending Interrupt before we - // install the handlers as wierd corruption would occur and hang system. - // - // - // Read IDE CMD blk status reg to clear out any pending interrupts. - // Do here for Primary and Secondary IDE channels - // - RegisterAddress = (UINT16)Private->IntThunk->PciHandler.PrimaryBase + 0x07; - IoRead8 (RegisterAddress); - RegisterAddress = (UINT16)Private->IntThunk->PciHandler.SecondaryBase + 0x07; - IoRead8 (RegisterAddress); - - Private->IntThunk->PciHandler.PrimaryReserved = 0; - Private->IntThunk->PciHandler.SecondaryReserved = 0; - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - 0xE0000, - 0x20000, - &Granularity - ); - - Regs.X.AX = Legacy16InstallPciHandler; - TempData = (UINTN) &Private->IntThunk->PciHandler; - Regs.X.ES = EFI_SEGMENT ((UINT32) TempData); - Regs.X.BX = EFI_OFFSET ((UINT32) TempData); - - DumpPciHandle (&Private->IntThunk->PciHandler); - - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Private->Legacy16CallSegment, - Private->Legacy16CallOffset, - &Regs, - NULL, - 0 - ); - - Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate); - Private->LegacyRegion->Lock ( - Private->LegacyRegion, - 0xE0000, - 0x20000, - &Granularity - ); - -} - - -/** - Program the interrupt routing register in all the PCI devices. On a PC AT system - this register contains the 8259 IRQ vector that matches it's PCI interrupt. - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS Succeed. - @retval EFI_ALREADY_STARTED All PCI devices have been processed. - -**/ -EFI_STATUS -PciProgramAllInterruptLineRegisters ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_LEGACY_8259_PROTOCOL *Legacy8259; - EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt; - EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; - UINT8 InterruptPin; - UINTN Index; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINTN MassStorageHandleCount; - EFI_HANDLE *MassStorageHandleBuffer; - UINTN MassStorageHandleIndex; - UINT8 PciIrq; - UINT16 Command; - UINTN PciSegment; - UINTN PciBus; - UINTN PciDevice; - UINTN PciFunction; - EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable; - UINTN RoutingTableEntries; - UINT16 LegMask; - UINT16 LegEdgeLevel; - PCI_TYPE00 PciConfigHeader; - EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable; - UINTN PirqTableSize; - UINTN Flags; - HDD_INFO *HddInfo; - UINT64 Supports; - - // - // Note - This routine use to return immediately if Private->PciInterruptLine - // was true. Routine changed since resets etc can cause not all - // PciIo protocols to be registered the first time through. - // New algorithm is to do the copy $PIR table on first pass and save - // HandleCount on first pass. If subsequent passes LocateHandleBuffer gives - // a larger handle count then proceed with body of function else return - // EFI_ALREADY_STARTED. In addition check if PCI device InterruptLine != 0. - // If zero then function unprogrammed else skip function. - // - Legacy8259 = Private->Legacy8259; - LegacyInterrupt = Private->LegacyInterrupt; - LegacyBiosPlatform = Private->LegacyBiosPlatform; - - LegacyBiosPlatform->GetRoutingTable ( - Private->LegacyBiosPlatform, - (VOID *) &RoutingTable, - &RoutingTableEntries, - (VOID *) &PirqTable, - &PirqTableSize, - NULL, - NULL - ); - CreateBridgeTable (RoutingTable, RoutingTableEntries); - - if (!Private->PciInterruptLine) { - CopyPirqTable ( - Private, - RoutingTable, - RoutingTableEntries, - PirqTable, - PirqTableSize - ); - } - - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - if (HandleCount == mHandleCount) { - FreePool (HandleBuffer); - return EFI_ALREADY_STARTED; - } - - if (mHandleCount == 0x00) { - mHandleCount = HandleCount; - } - - for (Index = 0; Index < HandleCount; Index++) { - // - // If VGA then only do VGA to allow drives fore time to spin up - // otherwise assign PCI IRQs to all potential devices. - // - if ((mVgaInstallationInProgress) && (HandleBuffer[Index] != mVgaHandle)) { - continue; - } else { - // - // Force code to go through all handles next time called if video. - // This will catch case where HandleCount doesn't change but want - // to get drive info etc. - // - mHandleCount = 0x00; - } - - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - ASSERT_EFI_ERROR (Status); - - // - // Test whether the device can be enabled or not. - // If it can't be enabled, then just skip it to avoid further operation. - // - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (PciConfigHeader) / sizeof (UINT32), - &PciConfigHeader - ); - Command = PciConfigHeader.Hdr.Command; - - // - // Note PciIo->Attributes does not program the PCI command register - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - } - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x04, 1, &Command); - - if (EFI_ERROR (Status)) { - continue; - } - - InterruptPin = PciConfigHeader.Device.InterruptPin; - - if ((InterruptPin != 0) && (PciConfigHeader.Device.InterruptLine == PCI_INT_LINE_UNKNOWN)) { - PciIo->GetLocation ( - PciIo, - &PciSegment, - &PciBus, - &PciDevice, - &PciFunction - ); - // - // Translate PIRQ index back thru busses to slot bus with InterruptPin - // zero based - // - InterruptPin -= 1; - - Status = GetBaseBus ( - Private, - PciBus, - PciDevice, - RoutingTable, - RoutingTableEntries - ); - - if (Status == EFI_NOT_FOUND) { - TranslateBusPirq ( - Private, - &PciBus, - &PciDevice, - &PciFunction, - &InterruptPin - ); - } - // - // Translate InterruptPin(0-3) into PIRQ - // - Status = LegacyBiosPlatform->TranslatePirq ( - LegacyBiosPlatform, - PciBus, - (PciDevice << 3), - PciFunction, - &InterruptPin, - &PciIrq - ); - // - // TranslatePirq() should never fail or we are in trouble - // If it does return failure status, check your PIRQ routing table to see if some item is missing or incorrect - // - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Translate Pirq Failed - Status = %r\n ", Status)); - continue; - } - - LegacyInterrupt->WritePirq ( - LegacyInterrupt, - InterruptPin, - PciIrq - ); - - // - // Check if device has an OPROM associated with it. - // If not invoke special 16-bit function, to allow 16-bit - // code to install an interrupt handler. - // - Status = LegacyBiosCheckPciRom ( - &Private->LegacyBios, - HandleBuffer[Index], - NULL, - NULL, - &Flags - ); - if ((EFI_ERROR (Status)) && (PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE)) { - // - // Device has no OPROM associated with it and is a mass storage - // device. It needs to have an PCI IRQ handler installed. To - // correctly install the handler we need to insure device is - // connected. The device may just have register itself but not - // been connected. Re-read PCI config space after as it can - // change - // - // - // Get IDE Handle. If matches handle then skip ConnectController - // since ConnectController may force native mode and we don't - // want that for primary IDE controller - // - MassStorageHandleCount = 0; - MassStorageHandleBuffer = NULL; - LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformIdeHandle, - 0, - &MassStorageHandleBuffer, - &MassStorageHandleCount, - NULL - ); - - HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; - - LegacyBiosBuildIdeData (Private, &HddInfo, 0); - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (PciConfigHeader) / sizeof (UINT32), - &PciConfigHeader - ); - - for (MassStorageHandleIndex = 0; MassStorageHandleIndex < MassStorageHandleCount; MassStorageHandleIndex++) { - if (MassStorageHandleBuffer[MassStorageHandleIndex] == HandleBuffer[Index]) { - // - // InstallLegacyIrqHandler according to Platform requirement - // - InstallLegacyIrqHandler ( - Private, - PciIo, - PciIrq, - &PciConfigHeader - ); - break; - } - } - } - // - // Write InterruptPin and enable 8259. - // - PciIo->Pci.Write ( - PciIo, - EfiPciIoWidthUint8, - 0x3c, - 1, - &PciIrq - ); - Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask = (UINT16) (Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask | (UINT16) (1 << PciIrq)); - - Legacy8259->GetMask ( - Legacy8259, - &LegMask, - &LegEdgeLevel, - NULL, - NULL - ); - - LegMask = (UINT16) (LegMask & (UINT16)~(1 << PciIrq)); - LegEdgeLevel = (UINT16) (LegEdgeLevel | (UINT16) (1 << PciIrq)); - Legacy8259->SetMask ( - Legacy8259, - &LegMask, - &LegEdgeLevel, - NULL, - NULL - ); - } - } - FreePool (HandleBuffer); - return EFI_SUCCESS; -} - - -/** - Find & verify PnP Expansion header in ROM image - - @param Private Protocol instance pointer. - @param FirstHeader 1 = Find first header, 0 = Find successive headers - @param PnpPtr Input Rom start if FirstHeader =1, Current Header - otherwise Output Next header, if it exists - - @retval EFI_SUCCESS Next Header found at BasePnpPtr - @retval EFI_NOT_FOUND No more headers - -**/ -EFI_STATUS -FindNextPnpExpansionHeader ( - IN LEGACY_BIOS_INSTANCE *Private, - IN BOOLEAN FirstHeader, - IN OUT LEGACY_PNP_EXPANSION_HEADER **PnpPtr - - ) -{ - UINTN TempData; - LEGACY_PNP_EXPANSION_HEADER *LocalPnpPtr; - LocalPnpPtr = *PnpPtr; - if (FirstHeader == FIRST_INSTANCE) { - mBasePnpPtr = LocalPnpPtr; - mBbsRomSegment = (UINT16) ((UINTN) mBasePnpPtr >> 4); - // - // Offset 0x1a gives offset to PnP expansion header for the first - // instance, there after the structure gives the offset to the next - // structure - // - LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) ((UINT8 *) LocalPnpPtr + 0x1a); - TempData = (*((UINT16 *) LocalPnpPtr)); - } else { - TempData = (UINT16) LocalPnpPtr->NextHeader; - } - - LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) (((UINT8 *) mBasePnpPtr + TempData)); - - // - // Search for PnP table in Shadowed ROM - // - *PnpPtr = LocalPnpPtr; - if (*(UINT32 *) LocalPnpPtr == SIGNATURE_32 ('$', 'P', 'n', 'P')) { - return EFI_SUCCESS; - } else { - return EFI_NOT_FOUND; - } -} - - -/** - Update list of Bev or BCV table entries. - - @param Private Protocol instance pointer. - @param RomStart Table of ROM start address in RAM/ROM. PciIo _ - Handle to PCI IO for this device - @param PciIo Instance of PCI I/O Protocol - - @retval EFI_SUCCESS Always should succeed. - -**/ -EFI_STATUS -UpdateBevBcvTable ( - IN LEGACY_BIOS_INSTANCE *Private, - IN EFI_LEGACY_EXPANSION_ROM_HEADER *RomStart, - IN EFI_PCI_IO_PROTOCOL *PciIo - ) -{ - VOID *RomEnd; - BBS_TABLE *BbsTable; - UINTN BbsIndex; - EFI_LEGACY_EXPANSION_ROM_HEADER *PciPtr; - LEGACY_PNP_EXPANSION_HEADER *PnpPtr; - BOOLEAN Instance; - EFI_STATUS Status; - UINTN Segment; - UINTN Bus; - UINTN Device; - UINTN Function; - UINT8 Class; - UINT16 DeviceType; - Segment = 0; - Bus = 0; - Device = 0; - Function = 0; - Class = 0; - DeviceType = BBS_UNKNOWN; - - // - // Skip floppy and 2*onboard IDE controller entries(Master/Slave per - // controller). - // - BbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; - - BbsTable = (BBS_TABLE*)(UINTN) Private->IntThunk->EfiToLegacy16BootTable.BbsTable; - PnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) RomStart; - PciPtr = (EFI_LEGACY_EXPANSION_ROM_HEADER *) RomStart; - - RomEnd = (VOID *) (PciPtr->Size512 * 512 + (UINTN) PciPtr); - Instance = FIRST_INSTANCE; - // - // OPROMs like PXE may not be tied to a piece of hardware and thus - // don't have a PciIo associated with them - // - if (PciIo != NULL) { - PciIo->GetLocation ( - PciIo, - &Segment, - &Bus, - &Device, - &Function - ); - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint8, - 0x0b, - 1, - &Class - ); - - if (Class == PCI_CLASS_MASS_STORAGE) { - DeviceType = BBS_HARDDISK; - } else { - if (Class == PCI_CLASS_NETWORK) { - DeviceType = BBS_EMBED_NETWORK; - } - } - } - - while (TRUE) { - Status = FindNextPnpExpansionHeader (Private, Instance, &PnpPtr); - Instance = NOT_FIRST_INSTANCE; - if (EFI_ERROR (Status)) { - break; - } - // - // There can be additional $PnP headers within the OPROM. - // Example: SCSI can have one per drive. - // - BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY; - BbsTable[BbsIndex].DeviceType = DeviceType; - BbsTable[BbsIndex].Bus = (UINT32) Bus; - BbsTable[BbsIndex].Device = (UINT32) Device; - BbsTable[BbsIndex].Function = (UINT32) Function; - BbsTable[BbsIndex].StatusFlags.OldPosition = 0; - BbsTable[BbsIndex].StatusFlags.Reserved1 = 0; - BbsTable[BbsIndex].StatusFlags.Enabled = 0; - BbsTable[BbsIndex].StatusFlags.Failed = 0; - BbsTable[BbsIndex].StatusFlags.MediaPresent = 0; - BbsTable[BbsIndex].StatusFlags.Reserved2 = 0; - BbsTable[BbsIndex].Class = PnpPtr->Class; - BbsTable[BbsIndex].SubClass = PnpPtr->SubClass; - BbsTable[BbsIndex].DescStringOffset = PnpPtr->ProductNamePointer; - BbsTable[BbsIndex].DescStringSegment = mBbsRomSegment; - BbsTable[BbsIndex].MfgStringOffset = PnpPtr->MfgPointer; - BbsTable[BbsIndex].MfgStringSegment = mBbsRomSegment; - BbsTable[BbsIndex].BootHandlerSegment = mBbsRomSegment; - - // - // Have seen case where PXE base code have PnP expansion ROM - // header but no Bcv or Bev vectors. - // - if (PnpPtr->Bcv != 0) { - BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bcv; - ++BbsIndex; - } - - if (PnpPtr->Bev != 0) { - BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bev; - BbsTable[BbsIndex].DeviceType = BBS_BEV_DEVICE; - ++BbsIndex; - } - - if ((PnpPtr == (LEGACY_PNP_EXPANSION_HEADER *) PciPtr) || (PnpPtr > (LEGACY_PNP_EXPANSION_HEADER *) RomEnd)) { - break; - } - } - - BbsTable[BbsIndex].BootPriority = BBS_IGNORE_ENTRY; - Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT32) BbsIndex; - return EFI_SUCCESS; -} - - -/** - Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol - to chose the order. Skip any devices that have already have legacy - BIOS run. - - @param Private Protocol instance pointer. - - @retval EFI_SUCCESS Succeed. - @retval EFI_UNSUPPORTED Cannot get VGA device handle. - -**/ -EFI_STATUS -PciShadowRoms ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; - UINTN Index; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - EFI_HANDLE VgaHandle; - EFI_HANDLE FirstHandle; - VOID **RomStart; - UINTN Flags; - PCI_TYPE00 PciConfigHeader; - UINT16 *Command; - UINT64 Supports; - - // - // Make the VGA device first - // - Status = Private->LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformVgaHandle, - 0, - &HandleBuffer, - &HandleCount, - NULL - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - VgaHandle = HandleBuffer[0]; - - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Place the VGA handle as first. - // - for (Index = 0; Index < HandleCount; Index++) { - if (HandleBuffer[Index] == VgaHandle) { - FirstHandle = HandleBuffer[0]; - HandleBuffer[0] = HandleBuffer[Index]; - HandleBuffer[Index] = FirstHandle; - break; - } - } - // - // Allocate memory to save Command WORD from each device. We do this - // to restore devices to same state as EFI after switching to legacy. - // - Command = (UINT16 *) AllocatePool ( - sizeof (UINT16) * (HandleCount + 1) - ); - if (NULL == Command) { - FreePool (HandleBuffer); - return EFI_OUT_OF_RESOURCES; - } - // - // Disconnect all EFI devices first. This covers cases where alegacy BIOS - // may control multiple PCI devices. - // - for (Index = 0; Index < HandleCount; Index++) { - - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - ASSERT_EFI_ERROR (Status); - - // - // Save command register for "connect" loop - // - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (PciConfigHeader) / sizeof (UINT32), - &PciConfigHeader - ); - Command[Index] = PciConfigHeader.Hdr.Command; - // - // Skip any device that already has a legacy ROM run - // - Status = IsLegacyRom (HandleBuffer[Index]); - if (!EFI_ERROR (Status)) { - continue; - } - // - // Stop EFI Drivers with oprom. - // - gBS->DisconnectController ( - HandleBuffer[Index], - NULL, - NULL - ); - } - // - // For every device that has not had a legacy ROM started. Start a legacy ROM. - // - for (Index = 0; Index < HandleCount; Index++) { - - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - - ASSERT_EFI_ERROR (Status); - - // - // Here make sure if one VGA have been shadowed, - // then wil not shadowed another one. - // - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (Pci) / sizeof (UINT32), - &Pci - ); - - // - // Only one Video OPROM can be given control in BIOS phase. If there are multiple Video devices, - // one will work in legacy mode (OPROM will be given control) and - // other Video devices will work in native mode (OS driver will handle these devices). - // - if (IS_PCI_DISPLAY (&Pci) && Index != 0) { - continue; - } - // - // Skip any device that already has a legacy ROM run - // - Status = IsLegacyRom (HandleBuffer[Index]); - if (!EFI_ERROR (Status)) { - continue; - } - - // - // If legacy VBIOS Oprom has not been dispatched before, install legacy VBIOS here. - // - if (IS_PCI_DISPLAY (&Pci) && Index == 0) { - Status = LegacyBiosInstallVgaRom (Private); - // - // A return status of EFI_NOT_FOUND is considered valid (No EFI - // driver is controlling video). - // - ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)); - continue; - } - - // - // Install legacy ROM - // - Status = LegacyBiosInstallPciRom ( - &Private->LegacyBios, - HandleBuffer[Index], - NULL, - &Flags, - NULL, - NULL, - (VOID **) &RomStart, - NULL - ); - if (EFI_ERROR (Status)) { - if (!((Status == EFI_UNSUPPORTED) && (Flags == NO_ROM))) { - continue; - } - } - // - // Restore Command register so legacy has same devices enabled or disabled - // as EFI. - // If Flags = NO_ROM use command register as is. This covers the - // following cases: - // Device has no ROMs associated with it. - // Device has ROM associated with it but was already - // installed. - // = ROM_FOUND but not VALID_LEGACY_ROM, disable it. - // = ROM_FOUND and VALID_LEGACY_ROM, enable it. - // - if ((Flags & ROM_FOUND) == ROM_FOUND) { - if ((Flags & VALID_LEGACY_ROM) == 0) { - Command[Index] = 0; - } else { - // - // For several VGAs, only one of them can be enabled. - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - } - if (!EFI_ERROR (Status)) { - Command[Index] = 0x1f; - } - } - } - - PciIo->Pci.Write ( - PciIo, - EfiPciIoWidthUint16, - 0x04, - 1, - &Command[Index] - ); - } - - FreePool (Command); - FreePool (HandleBuffer); - return EFI_SUCCESS; -} - - -/** - Test to see if a legacy PCI ROM exists for this device. Optionally return - the Legacy ROM instance for this PCI device. - - @param This Protocol instance pointer. - @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will - be loaded - @param RomImage Return the legacy PCI ROM for this device - @param RomSize Size of ROM Image - @param Flags Indicates if ROM found and if PC-AT. - - @retval EFI_SUCCESS Legacy Option ROM availible for this device - @retval EFI_UNSUPPORTED Legacy Option ROM not supported. - -**/ -EFI_STATUS -EFIAPI -LegacyBiosCheckPciRom ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN EFI_HANDLE PciHandle, - OUT VOID **RomImage, OPTIONAL - OUT UINTN *RomSize, OPTIONAL - OUT UINTN *Flags - ) -{ - return LegacyBiosCheckPciRomEx ( - This, - PciHandle, - RomImage, - RomSize, - NULL, - Flags, - NULL, - NULL - ); - -} - -/** - - Routine Description: - Test to see if a legacy PCI ROM exists for this device. Optionally return - the Legacy ROM instance for this PCI device. - - @param[in] This Protocol instance pointer. - @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded - @param[out] RomImage Return the legacy PCI ROM for this device - @param[out] RomSize Size of ROM Image - @param[out] RuntimeImageLength Runtime size of ROM Image - @param[out] Flags Indicates if ROM found and if PC-AT. - @param[out] OpromRevision Revision of the PCI Rom - @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header - - @return EFI_SUCCESS Legacy Option ROM availible for this device - @return EFI_ALREADY_STARTED This device is already managed by its Oprom - @return EFI_UNSUPPORTED Legacy Option ROM not supported. - -**/ -EFI_STATUS -LegacyBiosCheckPciRomEx ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN EFI_HANDLE PciHandle, - OUT VOID **RomImage, OPTIONAL - OUT UINTN *RomSize, OPTIONAL - OUT UINTN *RuntimeImageLength, OPTIONAL - OUT UINTN *Flags, OPTIONAL - OUT UINT8 *OpromRevision, OPTIONAL - OUT VOID **ConfigUtilityCodeHeader OPTIONAL - ) -{ - EFI_STATUS Status; - LEGACY_BIOS_INSTANCE *Private; - EFI_PCI_IO_PROTOCOL *PciIo; - UINTN LocalRomSize; - VOID *LocalRomImage; - PCI_TYPE00 PciConfigHeader; - VOID *LocalConfigUtilityCodeHeader; - - LocalConfigUtilityCodeHeader = NULL; - *Flags = NO_ROM; - Status = gBS->HandleProtocol ( - PciHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - // - // See if the option ROM for PciHandle has already been executed - // - Status = IsLegacyRom (PciHandle); - if (!EFI_ERROR (Status)) { - *Flags |= (UINTN)(ROM_FOUND | VALID_LEGACY_ROM); - return EFI_SUCCESS; - } - // - // Check for PCI ROM Bar - // - LocalRomSize = (UINTN) PciIo->RomSize; - LocalRomImage = PciIo->RomImage; - if (LocalRomSize != 0) { - *Flags |= ROM_FOUND; - } - - // - // PCI specification states you should check VendorId and Device Id. - // - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (PciConfigHeader) / sizeof (UINT32), - &PciConfigHeader - ); - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - Status = GetPciLegacyRom ( - Private->Csm16PciInterfaceVersion, - PciConfigHeader.Hdr.VendorId, - PciConfigHeader.Hdr.DeviceId, - &LocalRomImage, - &LocalRomSize, - RuntimeImageLength, - OpromRevision, - &LocalConfigUtilityCodeHeader - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - *Flags |= VALID_LEGACY_ROM; - - // - // See if Configuration Utility Code Header valid - // - if (LocalConfigUtilityCodeHeader != NULL) { - *Flags |= ROM_WITH_CONFIG; - } - - if (ConfigUtilityCodeHeader != NULL) { - *ConfigUtilityCodeHeader = LocalConfigUtilityCodeHeader; - } - - if (RomImage != NULL) { - *RomImage = LocalRomImage; - } - - if (RomSize != NULL) { - *RomSize = LocalRomSize; - } - - return EFI_SUCCESS; -} - -/** - Load a legacy PC-AT OPROM on the PciHandle device. Return information - about how many disks were added by the OPROM and the shadow address and - size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: - - @retval EFI_SUCCESS Legacy ROM loaded for this device - @retval EFI_NOT_FOUND No PS2 Keyboard found - -**/ -EFI_STATUS -EnablePs2Keyboard ( - VOID - ) -{ - EFI_STATUS Status; - EFI_HANDLE *HandleBuffer; - UINTN HandleCount; - EFI_ISA_IO_PROTOCOL *IsaIo; - UINTN Index; - - // - // Get SimpleTextIn and find PS2 controller - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiSimpleTextInProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - for (Index = 0; Index < HandleCount; Index++) { - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - HandleBuffer[Index], - &gEfiIsaIoProtocolGuid, - (VOID **) &IsaIo, - NULL, - HandleBuffer[Index], - EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL - ); - - if (!EFI_ERROR (Status)) { - // - // Use the ISA I/O Protocol to see if Controller is the Keyboard - // controller - // - if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) { - Status = EFI_UNSUPPORTED; - } - - gBS->CloseProtocol ( - HandleBuffer[Index], - &gEfiIsaIoProtocolGuid, - NULL, - HandleBuffer[Index] - ); - } - - if (!EFI_ERROR (Status)) { - gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); - } - } - FreePool (HandleBuffer); - return EFI_SUCCESS; -} - - -/** - Load a legacy PC-AT OpROM for VGA controller. - - @param Private Driver private data. - - @retval EFI_SUCCESS Legacy ROM successfully installed for this device. - @retval EFI_DEVICE_ERROR No VGA device handle found, or native EFI video - driver cannot be successfully disconnected, or VGA - thunk driver cannot be successfully connected. - -**/ -EFI_STATUS -LegacyBiosInstallVgaRom ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_STATUS Status; - EFI_HANDLE VgaHandle; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - EFI_HANDLE *ConnectHandleBuffer; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 PciConfigHeader; - UINT64 Supports; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; - UINTN EntryCount; - UINTN Index; - VOID *Interface; - - // - // EfiLegacyBiosGuild attached to a device implies that there is a legacy - // BIOS associated with that device. - // - // There are 3 cases to consider. - // Case 1: No EFI driver is controlling the video. - // Action: Return EFI_SUCCESS from DisconnectController, search - // video thunk driver, and connect it. - // Case 2: EFI driver is controlling the video and EfiLegacyBiosGuid is - // not on the image handle. - // Action: Disconnect EFI driver. - // ConnectController for video thunk - // Case 3: EFI driver is controlling the video and EfiLegacyBiosGuid is - // on the image handle. - // Action: Do nothing and set Private->VgaInstalled = TRUE. - // Then this routine is not called any more. - // - // - // Get the VGA device. - // - Status = Private->LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformVgaHandle, - 0, - &HandleBuffer, - &HandleCount, - NULL - ); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - VgaHandle = HandleBuffer[0]; - - // - // Check whether video thunk driver already starts. - // - Status = gBS->OpenProtocolInformation ( - VgaHandle, - &gEfiPciIoProtocolGuid, - &OpenInfoBuffer, - &EntryCount - ); - if (EFI_ERROR (Status)) { - return Status; - } - - for (Index = 0; Index < EntryCount; Index++) { - if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { - Status = gBS->HandleProtocol ( - OpenInfoBuffer[Index].AgentHandle, - &gEfiLegacyBiosGuid, - (VOID **) &Interface - ); - if (!EFI_ERROR (Status)) { - // - // This should be video thunk driver which is managing video device - // So it need not start again - // - DEBUG ((EFI_D_INFO, "Video thunk driver already start! Return!\n")); - Private->VgaInstalled = TRUE; - return EFI_SUCCESS; - } - } - } - - // - // Kick off the native EFI driver - // - Status = gBS->DisconnectController ( - VgaHandle, - NULL, - NULL - ); - if (EFI_ERROR (Status)) { - if (Status != EFI_NOT_FOUND) { - return EFI_DEVICE_ERROR; - } else { - return Status; - } - } - // - // Find all the Thunk Driver - // - HandleBuffer = NULL; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiLegacyBiosGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - ASSERT_EFI_ERROR (Status); - ConnectHandleBuffer = (EFI_HANDLE *) AllocatePool (sizeof (EFI_HANDLE) * (HandleCount + 1)); - ASSERT (ConnectHandleBuffer != NULL); - - CopyMem ( - ConnectHandleBuffer, - HandleBuffer, - sizeof (EFI_HANDLE) * HandleCount - ); - ConnectHandleBuffer[HandleCount] = NULL; - - FreePool (HandleBuffer); - - // - // Enable the device and make sure VGA cycles are being forwarded to this VGA device - // - Status = gBS->HandleProtocol ( - VgaHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - ASSERT_EFI_ERROR (Status); - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (PciConfigHeader) / sizeof (UINT32), - &PciConfigHeader - ); - - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)(EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \ - EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16); - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - } - - if (Status == EFI_SUCCESS) { - Private->VgaInstalled = TRUE; - - // - // Attach the VGA thunk driver. - // Assume the video is installed. This prevents potential of infinite recursion. - // - Status = gBS->ConnectController ( - VgaHandle, - ConnectHandleBuffer, - NULL, - TRUE - ); - } - - FreePool (ConnectHandleBuffer); - - if (EFI_ERROR (Status)) { - - Private->VgaInstalled = FALSE; - - // - // Reconnect the EFI VGA driver. - // - gBS->ConnectController (VgaHandle, NULL, NULL, TRUE); - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - - -/** - Load a legacy PC-AT OpROM. - - @param This Protocol instance pointer. - @param Private Driver's private data. - @param PciHandle The EFI handle for the PCI device. It could be - NULL if the OpROM image is not associated with - any device. - @param OpromRevision The revision of PCI PC-AT ROM image. - @param RomImage Pointer to PCI PC-AT ROM image header. It must not - be NULL. - @param ImageSize Size of the PCI PC-AT ROM image. - @param RuntimeImageLength On input is the max runtime image length indicated by the PCIR structure - On output is the actual runtime image length - @param DiskStart Disk number of first device hooked by the ROM. If - DiskStart is the same as DiskEnd no disked were - hooked. - @param DiskEnd Disk number of the last device hooked by the ROM. - @param RomShadowAddress Shadow address of PC-AT ROM - - @retval EFI_SUCCESS Legacy ROM loaded for this device - @retval EFI_OUT_OF_RESOURCES No more space for this ROM - -**/ -EFI_STATUS -EFIAPI -LegacyBiosInstallRom ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN LEGACY_BIOS_INSTANCE *Private, - IN EFI_HANDLE PciHandle, - IN UINT8 OpromRevision, - IN VOID *RomImage, - IN UINTN ImageSize, - IN OUT UINTN *RuntimeImageLength, - OUT UINT8 *DiskStart, OPTIONAL - OUT UINT8 *DiskEnd, OPTIONAL - OUT VOID **RomShadowAddress OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_STATUS PciEnableStatus; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT8 LocalDiskStart; - UINT8 LocalDiskEnd; - UINTN Segment; - UINTN Bus; - UINTN Device; - UINTN Function; - EFI_IA32_REGISTER_SET Regs; - UINT8 VideoMode; - EFI_TIME BootTime; - UINT32 *BdaPtr; - UINT32 LocalTime; - UINT32 StartBbsIndex; - UINT32 EndBbsIndex; - UINT32 MaxRomAddr; - UINTN TempData; - UINTN InitAddress; - UINTN RuntimeAddress; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - UINT32 Granularity; - - PciIo = NULL; - LocalDiskStart = 0; - LocalDiskEnd = 0; - Segment = 0; - Bus = 0; - Device = 0; - Function = 0; - VideoMode = 0; - PhysicalAddress = 0; - MaxRomAddr = PcdGet32 (PcdEndOpromShadowAddress); - - if ((Private->Legacy16Table->TableLength >= OFFSET_OF(EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) && - (Private->Legacy16Table->UmaAddress != 0) && - (Private->Legacy16Table->UmaSize != 0) && - (MaxRomAddr > (Private->Legacy16Table->UmaAddress))) { - MaxRomAddr = Private->Legacy16Table->UmaAddress; - } - - - PciProgramAllInterruptLineRegisters (Private); - - if ((OpromRevision >= 3) && (Private->Csm16PciInterfaceVersion >= 0x0300)) { - // - // CSM16 3.0 meets PCI 3.0 OpROM - // first test if there is enough space for its INIT code - // - PhysicalAddress = CONVENTIONAL_MEMORY_TOP; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiBootServicesCode, - EFI_SIZE_TO_PAGES (ImageSize), - &PhysicalAddress - ); - - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__)); - // - // Report Status Code to indicate that there is no enough space for OpROM - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE) - ); - return EFI_OUT_OF_RESOURCES; - } - InitAddress = (UINTN) PhysicalAddress; - // - // then test if there is enough space for its RT code - // - RuntimeAddress = Private->OptionRom; - if (RuntimeAddress + *RuntimeImageLength > MaxRomAddr) { - DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__)); - gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize)); - // - // Report Status Code to indicate that there is no enough space for OpROM - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE) - ); - return EFI_OUT_OF_RESOURCES; - } - } else { - // CSM16 3.0 meets PCI 2.x OpROM - // CSM16 2.x meets PCI 2.x/3.0 OpROM - // test if there is enough space for its INIT code - // - InitAddress = PCI_START_ADDRESS (Private->OptionRom); - if (InitAddress + ImageSize > MaxRomAddr) { - DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__)); - // - // Report Status Code to indicate that there is no enough space for OpROM - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE) - ); - return EFI_OUT_OF_RESOURCES; - } - - RuntimeAddress = InitAddress; - } - - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - 0xE0000, - 0x20000, - &Granularity - ); - - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - (UINT32) RuntimeAddress, - (UINT32) ImageSize, - &Granularity - ); - - DEBUG ((EFI_D_INFO, " Shadowing OpROM init/runtime/isize = %x/%x/%x\n", InitAddress, RuntimeAddress, ImageSize)); - - CopyMem ((VOID *) InitAddress, RomImage, ImageSize); - - // - // Read the highest disk number "installed: and assume a new disk will - // show up on the first drive past the current value. - // There are several considerations here: - // 1. Non-BBS compliant drives will change 40:75 but 16-bit CSM will undo - // the change until boot selection time frame. - // 2. BBS compliants drives will not change 40:75 until boot time. - // 3. Onboard IDE controllers will change 40:75 - // - LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80); - if ((Private->Disk4075 + 0x80) < LocalDiskStart) { - // - // Update table since onboard IDE drives found - // - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = 0xff; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = 0xff; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = 0xff; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = 0xff; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = (UINT8) (Private->Disk4075 + 0x80); - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = LocalDiskStart; - Private->LegacyEfiHddTableIndex ++; - Private->Disk4075 = (UINT8) (LocalDiskStart & 0x7f); - Private->DiskEnd = LocalDiskStart; - } - - if (PciHandle != mVgaHandle) { - - EnablePs2Keyboard (); - - // - // Store current mode settings since PrepareToScanRom may change mode. - // - VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE)); - } - // - // Notify the platform that we are about to scan the ROM - // - Status = Private->LegacyBiosPlatform->PlatformHooks ( - Private->LegacyBiosPlatform, - EfiPlatformHookPrepareToScanRom, - 0, - PciHandle, - &InitAddress, - NULL, - NULL - ); - - // - // If Status returned is EFI_UNSUPPORTED then abort due to platform - // policy. - // - if (Status == EFI_UNSUPPORTED) { - goto Done; - } - - // - // Report corresponding status code - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_CSM_LEGACY_ROM_INIT) - ); - - // - // Generate number of ticks since midnight for BDA. Some OPROMs require - // this. Place result in 40:6C-6F - // - gRT->GetTime (&BootTime, NULL); - LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second; - - // - // Multiply result by 18.2 for number of ticks since midnight. - // Use 182/10 to avoid floating point math. - // - LocalTime = (LocalTime * 182) / 10; - BdaPtr = (UINT32 *) ((UINTN) 0x46C); - *BdaPtr = LocalTime; - - // - // Pass in handoff data - // - PciEnableStatus = EFI_UNSUPPORTED; - ZeroMem (&Regs, sizeof (Regs)); - if (PciHandle != NULL) { - - Status = gBS->HandleProtocol ( - PciHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - ASSERT_EFI_ERROR (Status); - - // - // Enable command register. - // - PciEnableStatus = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_DEVICE_ENABLE, - NULL - ); - - PciIo->GetLocation ( - PciIo, - &Segment, - &Bus, - &Device, - &Function - ); - DEBUG ((EFI_D_INFO, "Shadowing OpROM on the PCI device %x/%x/%x\n", Bus, Device, Function)); - } - - mIgnoreBbsUpdateFlag = FALSE; - Regs.X.AX = Legacy16DispatchOprom; - - // - // Generate DispatchOpRomTable data - // - Private->IntThunk->DispatchOpromTable.PnPInstallationCheckSegment = Private->Legacy16Table->PnPInstallationCheckSegment; - Private->IntThunk->DispatchOpromTable.PnPInstallationCheckOffset = Private->Legacy16Table->PnPInstallationCheckOffset; - Private->IntThunk->DispatchOpromTable.OpromSegment = (UINT16) (InitAddress >> 4); - Private->IntThunk->DispatchOpromTable.PciBus = (UINT8) Bus; - Private->IntThunk->DispatchOpromTable.PciDeviceFunction = (UINT8) ((Device << 3) | Function); - Private->IntThunk->DispatchOpromTable.NumberBbsEntries = (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; - Private->IntThunk->DispatchOpromTable.BbsTablePointer = (UINT32) (UINTN) Private->BbsTablePtr; - Private->IntThunk->DispatchOpromTable.RuntimeSegment = (UINT16)((OpromRevision < 3) ? 0xffff : (RuntimeAddress >> 4)); - TempData = (UINTN) &Private->IntThunk->DispatchOpromTable; - Regs.X.ES = EFI_SEGMENT ((UINT32) TempData); - Regs.X.BX = EFI_OFFSET ((UINT32) TempData); - // - // Skip dispatching ROM for those PCI devices that can not be enabled by PciIo->Attributes - // Otherwise, it may cause the system to hang in some cases - // - if (!EFI_ERROR (PciEnableStatus)) { - DEBUG ((EFI_D_INFO, " Legacy16DispatchOprom - %02x/%02x/%02x\n", Bus, Device, Function)); - Private->LegacyBios.FarCall86 ( - &Private->LegacyBios, - Private->Legacy16CallSegment, - Private->Legacy16CallOffset, - &Regs, - NULL, - 0 - ); - } else { - Regs.X.BX = 0; - } - - if (Private->IntThunk->DispatchOpromTable.NumberBbsEntries != (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries) { - Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT8) Private->IntThunk->DispatchOpromTable.NumberBbsEntries; - mIgnoreBbsUpdateFlag = TRUE; - } - // - // Check if non-BBS compliant drives found - // - if (Regs.X.BX != 0) { - LocalDiskEnd = (UINT8) (LocalDiskStart + Regs.H.BL); - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = (UINT8) Segment; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = (UINT8) Bus; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = (UINT8) Device; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = (UINT8) Function; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = Private->DiskEnd; - Private->DiskEnd = LocalDiskEnd; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd; - Private->LegacyEfiHddTableIndex += 1; - } - // - // Skip video mode set, if installing VGA - // - if (PciHandle != mVgaHandle) { - // - // Set mode settings since PrepareToScanRom may change mode - // - if (VideoMode != *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE))) { - // - // The active video mode is changed, restore it to original mode. - // - Regs.H.AH = 0x00; - Regs.H.AL = VideoMode; - Private->LegacyBios.Int86 (&Private->LegacyBios, 0x10, &Regs); - } - } - // - // Regs.X.AX from the adapter initializion is ignored since some adapters - // do not follow the standard of setting AX = 0 on success. - // - // - // The ROM could have updated it's size so we need to read again. - // - if (((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { - // - // Now we check the signature (0xaa55) to judge whether the run-time code is truly generated by INIT function. - // If signature is not valid, that means the INIT function didn't copy the run-time code to RuntimeAddress. - // - *RuntimeImageLength = 0; - } else { - *RuntimeImageLength = ((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Size512 * 512; - } - - DEBUG ((EFI_D_INFO, " fsize = %x\n", *RuntimeImageLength)); - - // - // If OpROM runs in 2.0 mode - // - if (PhysicalAddress == 0) { - if (*RuntimeImageLength < ImageSize) { - // - // Make area from end of shadowed rom to end of original rom all ffs - // - gBS->SetMem ((VOID *) (InitAddress + *RuntimeImageLength), ImageSize - *RuntimeImageLength, 0xff); - } - } - - LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80); - - // - // Allow platform to perform any required actions after the - // OPROM has been initialized. - // - Status = Private->LegacyBiosPlatform->PlatformHooks ( - Private->LegacyBiosPlatform, - EfiPlatformHookAfterRomInit, - 0, - PciHandle, - &RuntimeAddress, - NULL, - NULL - ); - if (PciHandle != NULL) { - // - // If no PCI Handle then no header or Bevs. - // - if ((*RuntimeImageLength != 0) && (!mIgnoreBbsUpdateFlag)) { - StartBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; - TempData = RuntimeAddress; - UpdateBevBcvTable ( - Private, - (EFI_LEGACY_EXPANSION_ROM_HEADER *) TempData, - PciIo - ); - EndBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; - LocalDiskEnd = (UINT8) (LocalDiskStart + (UINT8) (EndBbsIndex - StartBbsIndex)); - if (LocalDiskEnd != LocalDiskStart) { - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = (UINT8) Segment; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = (UINT8) Bus; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = (UINT8) Device; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = (UINT8) Function; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = Private->DiskEnd; - Private->DiskEnd = LocalDiskEnd; - Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd; - Private->LegacyEfiHddTableIndex += 1; - } - } - // - // Mark PCI device as having a legacy BIOS ROM loaded. - // - RomShadow ( - PciHandle, - (UINT32) RuntimeAddress, - (UINT32) *RuntimeImageLength, - LocalDiskStart, - LocalDiskEnd - ); - } - - // - // Stuff caller's OPTIONAL return parameters. - // - if (RomShadowAddress != NULL) { - *RomShadowAddress = (VOID *) RuntimeAddress; - } - - if (DiskStart != NULL) { - *DiskStart = LocalDiskStart; - } - - if (DiskEnd != NULL) { - *DiskEnd = LocalDiskEnd; - } - - Private->OptionRom = (UINT32) (RuntimeAddress + *RuntimeImageLength); - - Status = EFI_SUCCESS; - -Done: - if (PhysicalAddress != 0) { - // - // Free pages when OpROM is 3.0 - // - gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize)); - } - - // - // Insure all shadowed areas are locked - // - Private->LegacyRegion->Lock ( - Private->LegacyRegion, - 0xC0000, - 0x40000, - &Granularity - ); - - return Status; -} - -/** - Load a legacy PC-AT OPROM on the PciHandle device. Return information - about how many disks were added by the OPROM and the shadow address and - size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: - - @param This Protocol instance pointer. - @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will - be loaded. This value is NULL if RomImage is - non-NULL. This is the normal case. - @param RomImage A PCI PC-AT ROM image. This argument is non-NULL - if there is no hardware associated with the ROM - and thus no PciHandle, otherwise is must be NULL. - Example is PXE base code. - @param Flags Indicates if ROM found and if PC-AT. - @param DiskStart Disk number of first device hooked by the ROM. If - DiskStart is the same as DiskEnd no disked were - hooked. - @param DiskEnd Disk number of the last device hooked by the ROM. - @param RomShadowAddress Shadow address of PC-AT ROM - @param RomShadowedSize Size of RomShadowAddress in bytes - - @retval EFI_SUCCESS Legacy ROM loaded for this device - @retval EFI_INVALID_PARAMETER PciHandle not found - @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no onboard - ROM - -**/ -EFI_STATUS -EFIAPI -LegacyBiosInstallPciRom ( - IN EFI_LEGACY_BIOS_PROTOCOL * This, - IN EFI_HANDLE PciHandle, - IN VOID **RomImage, - OUT UINTN *Flags, - OUT UINT8 *DiskStart, OPTIONAL - OUT UINT8 *DiskEnd, OPTIONAL - OUT VOID **RomShadowAddress, OPTIONAL - OUT UINT32 *RomShadowedSize OPTIONAL - ) -{ - EFI_STATUS Status; - LEGACY_BIOS_INSTANCE *Private; - VOID *LocalRomImage; - UINTN ImageSize; - UINTN RuntimeImageLength; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE01 PciConfigHeader; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINTN PciSegment; - UINTN PciBus; - UINTN PciDevice; - UINTN PciFunction; - UINTN LastBus; - UINTN Index; - UINT8 OpromRevision; - UINT32 Granularity; - PCI_3_0_DATA_STRUCTURE *Pcir; - - OpromRevision = 0; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - if (Private->Legacy16Table->LastPciBus == 0) { - // - // Get last bus number if not already found - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - - LastBus = 0; - for (Index = 0; Index < HandleCount; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - if (EFI_ERROR (Status)) { - continue; - } - - Status = PciIo->GetLocation ( - PciIo, - &PciSegment, - &PciBus, - &PciDevice, - &PciFunction - ); - if (PciBus > LastBus) { - LastBus = PciBus; - } - } - - Private->LegacyRegion->UnLock ( - Private->LegacyRegion, - 0xE0000, - 0x20000, - &Granularity - ); - Private->Legacy16Table->LastPciBus = (UINT8) LastBus; - Private->LegacyRegion->Lock ( - Private->LegacyRegion, - 0xE0000, - 0x20000, - &Granularity - ); - } - - *Flags = 0; - if ((PciHandle != NULL) && (RomImage == NULL)) { - // - // If PciHandle has OpRom to Execute - // and OpRom are all associated with Hardware - // - Status = gBS->HandleProtocol ( - PciHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo - ); - - if (!EFI_ERROR (Status)) { - PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (PciConfigHeader) / sizeof (UINT32), - &PciConfigHeader - ); - - // - // if video installed & OPROM is video return - // - if ( - ( - ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_OLD) && - (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA)) - || - ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY) && - (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA)) - ) - && - (!Private->VgaInstalled) - ) { - mVgaInstallationInProgress = TRUE; - - // - // return EFI_UNSUPPORTED; - // - } - } - // - // To run any legacy image, the VGA needs to be installed first. - // if installing the video, then don't need the thunk as already installed. - // - Status = Private->LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformVgaHandle, - 0, - &HandleBuffer, - &HandleCount, - NULL - ); - - if (!EFI_ERROR (Status)) { - mVgaHandle = HandleBuffer[0]; - if ((!Private->VgaInstalled) && (PciHandle != mVgaHandle)) { - // - // A return status of EFI_NOT_FOUND is considered valid (No EFI - // driver is controlling video. - // - mVgaInstallationInProgress = TRUE; - Status = LegacyBiosInstallVgaRom (Private); - if (EFI_ERROR (Status)) { - if (Status != EFI_NOT_FOUND) { - mVgaInstallationInProgress = FALSE; - return Status; - } - } else { - mVgaInstallationInProgress = FALSE; - } - } - } - // - // See if the option ROM for PciHandle has already been executed - // - Status = IsLegacyRom (PciHandle); - - if (!EFI_ERROR (Status)) { - mVgaInstallationInProgress = FALSE; - GetShadowedRomParameters ( - PciHandle, - DiskStart, - DiskEnd, - RomShadowAddress, - (UINTN *) RomShadowedSize - ); - return EFI_SUCCESS; - } - - Status = LegacyBiosCheckPciRomEx ( - &Private->LegacyBios, - PciHandle, - &LocalRomImage, - &ImageSize, - &RuntimeImageLength, - Flags, - &OpromRevision, - NULL - ); - if (EFI_ERROR (Status)) { - // - // There is no PCI ROM in the ROM BAR or no onboard ROM - // - mVgaInstallationInProgress = FALSE; - return EFI_UNSUPPORTED; - } - } else { - if ((RomImage == NULL) || (*RomImage == NULL)) { - // - // If PciHandle is NULL, and no OpRom is to be associated - // - mVgaInstallationInProgress = FALSE; - return EFI_UNSUPPORTED; - } - - Status = Private->LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformVgaHandle, - 0, - &HandleBuffer, - &HandleCount, - NULL - ); - if ((!EFI_ERROR (Status)) && (!Private->VgaInstalled)) { - // - // A return status of EFI_NOT_FOUND is considered valid (No EFI - // driver is controlling video. - // - mVgaInstallationInProgress = TRUE; - Status = LegacyBiosInstallVgaRom (Private); - if (EFI_ERROR (Status)) { - if (Status != EFI_NOT_FOUND) { - mVgaInstallationInProgress = FALSE; - return Status; - } - } else { - mVgaInstallationInProgress = FALSE; - } - } - - LocalRomImage = *RomImage; - if (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE || - ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset == 0 || - (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset & 3 ) != 0) { - mVgaInstallationInProgress = FALSE; - return EFI_UNSUPPORTED; - } - - Pcir = (PCI_3_0_DATA_STRUCTURE *) - ((UINT8 *) LocalRomImage + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset); - - if ((Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) || (Pcir->CodeType != PCI_CODE_TYPE_PCAT_IMAGE)) { - mVgaInstallationInProgress = FALSE; - return EFI_UNSUPPORTED; - } - - ImageSize = Pcir->ImageLength * 512; - if (Pcir->Length >= 0x1C) { - OpromRevision = Pcir->Revision; - } else { - OpromRevision = 0; - } - if (Pcir->Revision < 3) { - RuntimeImageLength = 0; - } else { - RuntimeImageLength = Pcir->MaxRuntimeImageLength * 512; - } - } - // - // Shadow and initialize the OpROM. - // - ASSERT (Private->TraceIndex < 0x200); - Private->Trace[Private->TraceIndex] = LEGACY_PCI_TRACE_000; - Private->TraceIndex ++; - Private->TraceIndex = (UINT16) (Private->TraceIndex % 0x200); - Status = LegacyBiosInstallRom ( - This, - Private, - PciHandle, - OpromRevision, - LocalRomImage, - ImageSize, - &RuntimeImageLength, - DiskStart, - DiskEnd, - RomShadowAddress - ); - if (RomShadowedSize != NULL) { - *RomShadowedSize = (UINT32) RuntimeImageLength; - } - - mVgaInstallationInProgress = FALSE; - return Status; -} - diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c deleted file mode 100644 index f82121c607..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c +++ /dev/null @@ -1,234 +0,0 @@ -/** @file - Collect Sio information from Native EFI Drivers. - Sio is floppy, parallel, serial, ... hardware - -Copyright (c) 2006 - 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 "LegacyBiosInterface.h" - - -/** - Collect EFI Info about legacy devices. - - @param Private Legacy BIOS Instance data - - @retval EFI_SUCCESS It should always work. - -**/ -EFI_STATUS -LegacyBiosBuildSioData ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_STATUS Status; - DEVICE_PRODUCER_DATA_HEADER *SioPtr; - DEVICE_PRODUCER_SERIAL *Sio1Ptr; - DEVICE_PRODUCER_PARALLEL *Sio2Ptr; - DEVICE_PRODUCER_FLOPPY *Sio3Ptr; - EFI_HANDLE IsaBusController; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINTN Index; - UINTN ResourceIndex; - UINTN ChildIndex; - EFI_ISA_IO_PROTOCOL *IsaIo; - EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; - EFI_ISA_ACPI_RESOURCE *IoResource; - EFI_ISA_ACPI_RESOURCE *DmaResource; - EFI_ISA_ACPI_RESOURCE *InterruptResource; - UINTN EntryCount; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - - // - // Get the pointer to the SIO data structure - // - SioPtr = &Private->IntThunk->EfiToLegacy16BootTable.SioData; - - // - // Zero the data in the SIO data structure - // - gBS->SetMem (SioPtr, sizeof (DEVICE_PRODUCER_DATA_HEADER), 0); - - // - // Find the ISA Bus Controller used for legacy - // - Status = Private->LegacyBiosPlatform->GetPlatformHandle ( - Private->LegacyBiosPlatform, - EfiGetPlatformIsaBusHandle, - 0, - &HandleBuffer, - &HandleCount, - NULL - ); - IsaBusController = HandleBuffer[0]; - if (!EFI_ERROR (Status)) { - // - // Force ISA Bus Controller to produce all ISA devices - // - gBS->ConnectController (IsaBusController, NULL, NULL, TRUE); - } - // - // Get the list of ISA controllers in the system - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiIsaIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - if (EFI_ERROR (Status)) { - return EFI_SUCCESS; - } - // - // Collect legacy information from each of the ISA controllers in the system - // - for (Index = 0; Index < HandleCount; Index++) { - - Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo); - if (EFI_ERROR (Status)) { - continue; - } - - ResourceList = IsaIo->ResourceList; - - if (ResourceList == NULL) { - continue; - } - // - // Collect the resource types neededto fill in the SIO data structure - // - IoResource = NULL; - DmaResource = NULL; - InterruptResource = NULL; - for (ResourceIndex = 0; - ResourceList->ResourceItem[ResourceIndex].Type != EfiIsaAcpiResourceEndOfList; - ResourceIndex++ - ) { - switch (ResourceList->ResourceItem[ResourceIndex].Type) { - case EfiIsaAcpiResourceIo: - IoResource = &ResourceList->ResourceItem[ResourceIndex]; - break; - - case EfiIsaAcpiResourceMemory: - break; - - case EfiIsaAcpiResourceDma: - DmaResource = &ResourceList->ResourceItem[ResourceIndex]; - break; - - case EfiIsaAcpiResourceInterrupt: - InterruptResource = &ResourceList->ResourceItem[ResourceIndex]; - break; - - default: - break; - } - } - // - // See if this is an ISA serial port - // - // Ignore DMA resource since it is always returned NULL - // - if (ResourceList->Device.HID == EISA_PNP_ID (0x500) || ResourceList->Device.HID == EISA_PNP_ID (0x501)) { - - if (ResourceList->Device.UID <= 3 && - IoResource != NULL && - InterruptResource != NULL - ) { - // - // Get the handle of the child device that has opened the ISA I/O Protocol - // - Status = gBS->OpenProtocolInformation ( - HandleBuffer[Index], - &gEfiIsaIoProtocolGuid, - &OpenInfoBuffer, - &EntryCount - ); - if (EFI_ERROR (Status)) { - continue; - } - // - // We want resource for legacy even if no 32-bit driver installed - // - for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) { - Sio1Ptr = &SioPtr->Serial[ResourceList->Device.UID]; - Sio1Ptr->Address = (UINT16) IoResource->StartRange; - Sio1Ptr->Irq = (UINT8) InterruptResource->StartRange; - Sio1Ptr->Mode = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF; - } - - FreePool (OpenInfoBuffer); - } - } - // - // See if this is an ISA parallel port - // - // Ignore DMA resource since it is always returned NULL, port - // only used in output mode. - // - if (ResourceList->Device.HID == EISA_PNP_ID (0x400) || ResourceList->Device.HID == EISA_PNP_ID (0x401)) { - if (ResourceList->Device.UID <= 2 && - IoResource != NULL && - InterruptResource != NULL && - DmaResource != NULL - ) { - Sio2Ptr = &SioPtr->Parallel[ResourceList->Device.UID]; - Sio2Ptr->Address = (UINT16) IoResource->StartRange; - Sio2Ptr->Irq = (UINT8) InterruptResource->StartRange; - Sio2Ptr->Dma = (UINT8) DmaResource->StartRange; - Sio2Ptr->Mode = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY; - } - } - // - // See if this is an ISA floppy controller - // - if (ResourceList->Device.HID == EISA_PNP_ID (0x604)) { - if (IoResource != NULL && InterruptResource != NULL && DmaResource != NULL) { - Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); - if (!EFI_ERROR (Status)) { - Sio3Ptr = &SioPtr->Floppy; - Sio3Ptr->Address = (UINT16) IoResource->StartRange; - Sio3Ptr->Irq = (UINT8) InterruptResource->StartRange; - Sio3Ptr->Dma = (UINT8) DmaResource->StartRange; - Sio3Ptr->NumberOfFloppy++; - } - } - } - // - // See if this is a mouse - // Always set mouse found so USB hot plug will work - // - // Ignore lower byte of HID. Pnp0fxx is any type of mouse. - // - // Hid = ResourceList->Device.HID & 0xff00ffff; - // PnpId = EISA_PNP_ID(0x0f00); - // if (Hid == PnpId) { - // if (ResourceList->Device.UID == 1) { - // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer); - // if (!EFI_ERROR (Status)) { - // - SioPtr->MousePresent = 0x01; - // - // } - // } - // } - // - } - - FreePool (HandleBuffer); - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c deleted file mode 100644 index 3d9a8b9649..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c +++ /dev/null @@ -1,419 +0,0 @@ -/** @file - Call into 16-bit BIOS code, Use AsmThunk16 function of BaseLib. - -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 "LegacyBiosInterface.h" - -THUNK_CONTEXT mThunkContext; - -/** - Sets the counter value for Timer #0 in a legacy 8254 timer. - - @param Count - The 16-bit counter value to program into Timer #0 of the legacy 8254 timer. - -**/ -VOID -SetPitCount ( - IN UINT16 Count - ) -{ - IoWrite8 (TIMER_CONTROL_PORT, TIMER0_CONTROL_WORD); - IoWrite8 (TIMER0_COUNT_PORT, (UINT8) (Count & 0xFF)); - IoWrite8 (TIMER0_COUNT_PORT, (UINT8) ((Count>>8) & 0xFF)); -} - -/** - Thunk to 16-bit real mode and execute a software interrupt with a vector - of BiosInt. Regs will contain the 16-bit register context on entry and - exit. - - @param This Protocol instance pointer. - @param BiosInt Processor interrupt vector to invoke - @param Regs Register contexted passed into (and returned) from thunk to - 16-bit mode - - @retval FALSE Thunk completed, and there were no BIOS errors in the target code. - See Regs for status. - @retval TRUE There was a BIOS erro in the target code. - -**/ -BOOLEAN -EFIAPI -LegacyBiosInt86 ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT8 BiosInt, - IN EFI_IA32_REGISTER_SET *Regs - ) -{ - UINT32 *VectorBase; - - Regs->X.Flags.Reserved1 = 1; - Regs->X.Flags.Reserved2 = 0; - Regs->X.Flags.Reserved3 = 0; - Regs->X.Flags.Reserved4 = 0; - Regs->X.Flags.IOPL = 3; - Regs->X.Flags.NT = 0; - Regs->X.Flags.IF = 0; - Regs->X.Flags.TF = 0; - Regs->X.Flags.CF = 0; - // - // The base address of legacy interrupt vector table is 0. - // We use this base address to get the legacy interrupt handler. - // - VectorBase = 0; - - return InternalLegacyBiosFarCall ( - This, - (UINT16) ((VectorBase)[BiosInt] >> 16), - (UINT16) (VectorBase)[BiosInt], - Regs, - &Regs->X.Flags, - sizeof (Regs->X.Flags) - ); -} - -/** - Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the - 16-bit register context on entry and exit. Arguments can be passed on - the Stack argument - - @param This Protocol instance pointer. - @param Segment Segemnt of 16-bit mode call - @param Offset Offset of 16-bit mdoe call - @param Regs Register contexted passed into (and returned) from - thunk to 16-bit mode - @param Stack Caller allocated stack used to pass arguments - @param StackSize Size of Stack in bytes - - @retval FALSE Thunk completed, and there were no BIOS errors in - the target code. See Regs for status. - @retval TRUE There was a BIOS erro in the target code. - -**/ -BOOLEAN -EFIAPI -LegacyBiosFarCall86 ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT16 Segment, - IN UINT16 Offset, - IN EFI_IA32_REGISTER_SET *Regs, - IN VOID *Stack, - IN UINTN StackSize - ) -{ - Regs->X.Flags.Reserved1 = 1; - Regs->X.Flags.Reserved2 = 0; - Regs->X.Flags.Reserved3 = 0; - Regs->X.Flags.Reserved4 = 0; - Regs->X.Flags.IOPL = 3; - Regs->X.Flags.NT = 0; - Regs->X.Flags.IF = 1; - Regs->X.Flags.TF = 0; - Regs->X.Flags.CF = 0; - - return InternalLegacyBiosFarCall (This, Segment, Offset, Regs, Stack, StackSize); -} - -/** - Provide NULL interrupt handler which is used to check - if there is more than one HW interrupt registers with the CPU AP. - - @param InterruptType - The type of interrupt that occured - @param SystemContext - A pointer to the system context when the interrupt occured - -**/ -VOID -EFIAPI -LegacyBiosNullInterruptHandler ( - IN EFI_EXCEPTION_TYPE InterruptType, - IN EFI_SYSTEM_CONTEXT SystemContext - ) -{ -} - -/** - Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the - 16-bit register context on entry and exit. Arguments can be passed on - the Stack argument - - @param This Protocol instance pointer. - @param Segment Segemnt of 16-bit mode call - @param Offset Offset of 16-bit mdoe call - @param Regs Register contexted passed into (and returned) from thunk to - 16-bit mode - @param Stack Caller allocated stack used to pass arguments - @param StackSize Size of Stack in bytes - - @retval FALSE Thunk completed, and there were no BIOS errors in the target code. - See Regs for status. - @retval TRUE There was a BIOS erro in the target code. - -**/ -BOOLEAN -EFIAPI -InternalLegacyBiosFarCall ( - IN EFI_LEGACY_BIOS_PROTOCOL *This, - IN UINT16 Segment, - IN UINT16 Offset, - IN EFI_IA32_REGISTER_SET *Regs, - IN VOID *Stack, - IN UINTN StackSize - ) -{ - UINTN Status; - LEGACY_BIOS_INSTANCE *Private; - UINT16 *Stack16; - EFI_TPL OriginalTpl; - IA32_REGISTER_SET ThunkRegSet; - BOOLEAN InterruptState; - UINT64 TimerPeriod; - - Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); - - ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet)); - ThunkRegSet.X.DI = Regs->X.DI; - ThunkRegSet.X.SI = Regs->X.SI; - ThunkRegSet.X.BP = Regs->X.BP; - ThunkRegSet.X.BX = Regs->X.BX; - ThunkRegSet.X.DX = Regs->X.DX; - // - // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, AX = B10Dh is - // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to write. - // - ThunkRegSet.E.ECX = Regs->E.ECX; - ThunkRegSet.X.AX = Regs->X.AX; - ThunkRegSet.E.DS = Regs->X.DS; - ThunkRegSet.E.ES = Regs->X.ES; - - CopyMem (&(ThunkRegSet.E.EFLAGS.UintN), &(Regs->X.Flags), sizeof (Regs->X.Flags)); - - // - // Clear the error flag; thunk code may set it. Stack16 should be the high address - // Make Statk16 address the low 16 bit must be not zero. - // - Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16)); - - // - // Save current rate of DXE Timer - // - Private->Timer->GetTimerPeriod (Private->Timer, &TimerPeriod); - - // - // Disable DXE Timer while executing in real mode - // - Private->Timer->SetTimerPeriod (Private->Timer, 0); - - // - // Save and disable interrupt of debug timer - // - InterruptState = SaveAndSetDebugTimerInterrupt (FALSE); - - // - // The call to Legacy16 is a critical section to EFI - // - OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - // - // Check to see if there is more than one HW interrupt registers with the CPU AP. - // If there is, then ASSERT() since that is not compatible with the CSM because - // interupts other than the Timer interrupt that was disabled above can not be - // handled properly from real mode. - // - DEBUG_CODE ( - UINTN Vector; - UINTN Count; - - for (Vector = 0x20, Count = 0; Vector < 0x100; Vector++) { - Status = Private->Cpu->RegisterInterruptHandler (Private->Cpu, Vector, LegacyBiosNullInterruptHandler); - if (Status == EFI_ALREADY_STARTED) { - Count++; - } - if (Status == EFI_SUCCESS) { - Private->Cpu->RegisterInterruptHandler (Private->Cpu, Vector, NULL); - } - } - if (Count >= 2) { - DEBUG ((EFI_D_ERROR, "ERROR: More than one HW interrupt active with CSM enabled\n")); - } - ASSERT (Count < 2); - ); - - // - // If the Timer AP has enabled the 8254 timer IRQ and the current 8254 timer - // period is less than the CSM required rate of 54.9254, then force the 8254 - // PIT counter to 0, which is the CSM required rate of 54.9254 ms - // - if (Private->TimerUses8254 && TimerPeriod < 549254) { - SetPitCount (0); - } - - if (Stack != NULL && StackSize != 0) { - // - // Copy Stack to low memory stack - // - Stack16 -= StackSize / sizeof (UINT16); - CopyMem (Stack16, Stack, StackSize); - } - - ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12); - ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16; - ThunkRegSet.E.CS = Segment; - ThunkRegSet.E.Eip = Offset; - - mThunkContext.RealModeState = &ThunkRegSet; - - // - // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. - // - Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - AsmThunk16 (&mThunkContext); - - // - // OPROM may allocate EBDA range by itself and change EBDA base and EBDA size. - // Get the current EBDA base address, and compared with pre-allocate minimum - // EBDA base address, if the current EBDA base address is smaller, it indicates - // PcdEbdaReservedMemorySize should be adjusted to larger for more OPROMs. - // - DEBUG_CODE ( - { - UINTN EbdaBaseAddress; - UINTN ReservedEbdaBaseAddress; - - EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4; - ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize); - ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress); - } - ); - - if (Stack != NULL && StackSize != 0) { - // - // Copy low memory stack to Stack - // - CopyMem (Stack, Stack16, StackSize); - } - - // - // Restore protected mode interrupt state - // - Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - mThunkContext.RealModeState = NULL; - - // - // Enable and restore rate of DXE Timer - // - Private->Timer->SetTimerPeriod (Private->Timer, TimerPeriod); - - // - // End critical section - // - gBS->RestoreTPL (OriginalTpl); - - // - // Restore interrupt of debug timer - // - SaveAndSetDebugTimerInterrupt (InterruptState); - - Regs->E.EDI = ThunkRegSet.E.EDI; - Regs->E.ESI = ThunkRegSet.E.ESI; - Regs->E.EBP = ThunkRegSet.E.EBP; - Regs->E.EBX = ThunkRegSet.E.EBX; - Regs->E.EDX = ThunkRegSet.E.EDX; - Regs->E.ECX = ThunkRegSet.E.ECX; - Regs->E.EAX = ThunkRegSet.E.EAX; - Regs->X.SS = ThunkRegSet.E.SS; - Regs->X.CS = ThunkRegSet.E.CS; - Regs->X.DS = ThunkRegSet.E.DS; - Regs->X.ES = ThunkRegSet.E.ES; - - CopyMem (&(Regs->X.Flags), &(ThunkRegSet.E.EFLAGS.UintN), sizeof (Regs->X.Flags)); - - return (BOOLEAN) (Regs->X.Flags.CF == 1); -} - -/** - Allocate memory < 1 MB and copy the thunker code into low memory. Se up - all the descriptors. - - @param Private Private context for Legacy BIOS - - @retval EFI_SUCCESS Should only pass. - -**/ -EFI_STATUS -LegacyBiosInitializeThunk ( - IN LEGACY_BIOS_INSTANCE *Private - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS MemoryAddress; - UINT8 TimerVector; - - MemoryAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->IntThunk; - - mThunkContext.RealModeBuffer = (VOID *) (UINTN) (MemoryAddress + ((sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE); - mThunkContext.RealModeBufferSize = EFI_PAGE_SIZE; - mThunkContext.ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE | THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15; - - AsmPrepareThunk16 (&mThunkContext); - - // - // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver - // - TimerVector = 0; - Status = Private->Legacy8259->GetVector (Private->Legacy8259, Efi8259Irq0, &TimerVector); - ASSERT_EFI_ERROR (Status); - - // - // Check to see if the Timer AP has hooked the IRQ0 from the 8254 PIT - // - Status = Private->Cpu->RegisterInterruptHandler ( - Private->Cpu, - TimerVector, - LegacyBiosNullInterruptHandler - ); - if (Status == EFI_SUCCESS) { - // - // If the Timer AP has not enabled the 8254 timer IRQ, then force the 8254 PIT - // counter to 0, which is the CSM required rate of 54.9254 ms - // - Private->Cpu->RegisterInterruptHandler ( - Private->Cpu, - TimerVector, - NULL - ); - SetPitCount (0); - - // - // Save status that the Timer AP is not using the 8254 PIT - // - Private->TimerUses8254 = FALSE; - } else if (Status == EFI_ALREADY_STARTED) { - // - // Save status that the Timer AP is using the 8254 PIT - // - Private->TimerUses8254 = TRUE; - } else { - // - // Unexpected status from CPU AP RegisterInterruptHandler() - // - ASSERT (FALSE); - } - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.S b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.S deleted file mode 100644 index 0c9ce01d5b..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.S +++ /dev/null @@ -1,72 +0,0 @@ -## @file -# Interrupt Redirection Template -# -# Copyright (c) 2006, Intel 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. -# -## - -#text SEGMENT - - -#---------------------------------------------------------------------------- -# Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F -# -# Input: None -# -# Output: None -# -# Prototype: VOID -# InterruptRedirectionTemplate ( -# VOID -# ); -# -# Saves: None -# -# Modified: None -# -# Description: Contains the code that is copied into low memory (below 640K). -# This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. -# This template must be copied into low memory, and the IDT entries -# 0x68-0x6F must be point to the low memory copy of this code. Each -# entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily -# computed. -# -#---------------------------------------------------------------------------- - -ASM_GLOBAL ASM_PFX(InterruptRedirectionTemplate) -ASM_PFX(InterruptRedirectionTemplate): - int $0x08 - .byte 0x0cf # IRET - nop - int $0x09 - .byte 0x0cf # IRET - nop - int $0x0a - .byte 0x0cf # IRET - nop - int $0x0b - .byte 0x0cf # IRET - nop - int $0x0c - .byte 0x0cf # IRET - nop - int $0x0d - .byte 0x0cf # IRET - nop - int $0x0e - .byte 0x0cf # IRET - nop - int $0x0f - .byte 0x0cf # IRET - nop - -#END diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.asm b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.asm deleted file mode 100644 index 750423e5b7..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/X64/InterruptTable.asm +++ /dev/null @@ -1,71 +0,0 @@ -;; @file -; Interrupt Redirection Template -; -; Copyright (c) 2006, Intel 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. -; -;; - -text SEGMENT - -;---------------------------------------------------------------------------- -; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F -; -; Input: None -; -; Output: None -; -; Prototype: VOID -; InterruptRedirectionTemplate ( -; VOID -; ); -; -; Saves: None -; -; Modified: None -; -; Description: Contains the code that is copied into low memory (below 640K). -; This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. -; This template must be copied into low memory, and the IDT entries -; 0x68-0x6F must be point to the low memory copy of this code. Each -; entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily -; computed. -; -;---------------------------------------------------------------------------- - -InterruptRedirectionTemplate PROC - int 08h - DB 0cfh ; IRET - nop - int 09h - DB 0cfh ; IRET - nop - int 0ah - DB 0cfh ; IRET - nop - int 0bh - DB 0cfh ; IRET - nop - int 0ch - DB 0cfh ; IRET - nop - int 0dh - DB 0cfh ; IRET - nop - int 0eh - DB 0cfh ; IRET - nop - int 0fh - DB 0cfh ; IRET - nop -InterruptRedirectionTemplate ENDP - -END \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Include/Guid/AcpiVariableCompatibility.h b/IntelFrameworkModulePkg/Include/Guid/AcpiVariableCompatibility.h deleted file mode 100644 index 6c9f851543..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/AcpiVariableCompatibility.h +++ /dev/null @@ -1,69 +0,0 @@ -/** @file - Definitions for data structures used in S3 resume. - -Copyright (c) 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 _ACPI_VARIABLE_COMPATIBILITY_H_ -#define _ACPI_VARIABLE_COMPATIBILITY_H_ - -#define EFI_ACPI_VARIABLE_COMPATIBILITY_GUID \ - { \ - 0xc020489e, 0x6db2, 0x4ef2, {0x9a, 0xa5, 0xca, 0x6, 0xfc, 0x11, 0xd3, 0x6a } \ - } - -#define ACPI_GLOBAL_VARIABLE L"AcpiGlobalVariable" - -extern EFI_GUID gEfiAcpiVariableCompatiblityGuid; - -typedef struct { - BOOLEAN APState; - BOOLEAN S3BootPath; - EFI_PHYSICAL_ADDRESS WakeUpBuffer; - EFI_PHYSICAL_ADDRESS GdtrProfile; - EFI_PHYSICAL_ADDRESS IdtrProfile; - EFI_PHYSICAL_ADDRESS CpuPrivateData; - EFI_PHYSICAL_ADDRESS StackAddress; - EFI_PHYSICAL_ADDRESS MicrocodePointerBuffer; - EFI_PHYSICAL_ADDRESS SmramBase; - EFI_PHYSICAL_ADDRESS SmmStartImageBase; - UINT32 SmmStartImageSize; - UINT32 NumberOfCpus; -} ACPI_CPU_DATA_COMPATIBILITY; - -typedef struct { - // - // Acpi Related variables - // - EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase; - UINT32 AcpiReservedMemorySize; - EFI_PHYSICAL_ADDRESS S3ReservedLowMemoryBase; - EFI_PHYSICAL_ADDRESS AcpiBootScriptTable; - EFI_PHYSICAL_ADDRESS RuntimeScriptTableBase; - EFI_PHYSICAL_ADDRESS AcpiFacsTable; - UINT64 SystemMemoryLength; - ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData; - // - // VGA OPROM to support Video Re-POST for Linux S3 - // - EFI_PHYSICAL_ADDRESS VideoOpromAddress; - UINT32 VideoOpromSize; - - // - // S3 Debug extension - // - EFI_PHYSICAL_ADDRESS S3DebugBufferAddress; - EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint; -} ACPI_VARIABLE_SET_COMPATIBILITY; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/BdsHii.h b/IntelFrameworkModulePkg/Include/Guid/BdsHii.h deleted file mode 100644 index e22babc5b6..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/BdsHii.h +++ /dev/null @@ -1,55 +0,0 @@ -/** @file - GUIDs used as HII FormSet and HII Package list GUID in BdsDxe driver. - -Copyright (c) 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __BDS_HII_GUIDS_H__ -#define __BDS_HII_GUIDS_H__ - -#define FRONT_PAGE_FORMSET_GUID \ - { \ - 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe} \ - } - -#define BOOT_MANAGER_FORMSET_GUID \ - { \ - 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \ - } - -#define DEVICE_MANAGER_FORMSET_GUID \ - { \ - 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \ - } - -#define DRIVER_HEALTH_FORMSET_GUID \ - { \ - 0xf76e0a70, 0xb5ed, 0x4c38, {0xac, 0x9a, 0xe5, 0xf5, 0x4b, 0xf1, 0x6e, 0x34} \ - } - -#define BOOT_MAINT_FORMSET_GUID \ - { \ - 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \ - } - -#define FILE_EXPLORE_FORMSET_GUID \ - { \ - 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \ - } - -extern EFI_GUID gFrontPageFormSetGuid; -extern EFI_GUID gBootMaintFormSetGuid; -extern EFI_GUID gFileExploreFormSetGuid; -extern EFI_GUID gBootManagerFormSetGuid; -extern EFI_GUID gDeviceManagerFormSetGuid; -extern EFI_GUID gDriverHealthFormSetGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h b/IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h deleted file mode 100644 index 1a2bb024c4..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/BdsLibHii.h +++ /dev/null @@ -1,25 +0,0 @@ -/** @file - GUID used as HII Package list GUID in GenericBdsLib module. - -Copyright (c) 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __BDS_LIB_HII_GUID_H__ -#define __BDS_LIB_HII_GUID_H__ - -#define BDS_LIB_STRING_PACKAGE_GUID \ - { \ - 0x3b4d9b23, 0x95ac, 0x44f6, { 0x9f, 0xcd, 0xe, 0x95, 0x94, 0x58, 0x6c, 0x72 } \ - } - -extern EFI_GUID gBdsLibStringPackageGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/BlockIoVendor.h b/IntelFrameworkModulePkg/Include/Guid/BlockIoVendor.h deleted file mode 100644 index 71aa05a595..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/BlockIoVendor.h +++ /dev/null @@ -1,31 +0,0 @@ -/** @file - Guid for unrecognized EDD 3.0 device. - -Copyright (c) 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __BLOCKIO_VENDOR_H__ -#define __BLOCKIO_VENDOR_H__ - -// -// Guid is to specifiy the unrecognized EDD 3.0 device. -// -#define BLOCKIO_VENDOR_GUID \ - { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} } - -typedef struct { - VENDOR_DEVICE_PATH DevicePath; - UINT8 LegacyDriveLetter; -} BLOCKIO_VENDOR_DEVICE_PATH; - -extern GUID gBlockIoVendorGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/CapsuleDataFile.h b/IntelFrameworkModulePkg/Include/Guid/CapsuleDataFile.h deleted file mode 100644 index 7e97d17f23..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/CapsuleDataFile.h +++ /dev/null @@ -1,23 +0,0 @@ -/** @file - GUID to specify which FFS file to store the updated capsule data. - -Copyright (c) 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __UPDATE_DATA_FILE_GUID_H__ -#define __UPDATE_DATA_FILE_GUID_H__ - -#define EFI_UPDATE_DATA_FILE_GUID \ - { 0x283fa2ee, 0x532c, 0x484d, { 0x93, 0x83, 0x9f, 0x93, 0xb3, 0x6f, 0xb, 0x7e } } - -extern GUID gEfiUpdateDataFileGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h b/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h deleted file mode 100644 index a03a09712c..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h +++ /dev/null @@ -1,61 +0,0 @@ -/** @file - GUID used to identify Data Hub records logged by Status Code Protocol. - -Copyright (c) 2006 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __DATA_HUB_STATUS_CODE_RECORD_H__ -#define __DATA_HUB_STATUS_CODE_RECORD_H__ - -/// -/// The Global ID used to identify a structure of type DATA_HUB_STATUS_CODE_DATA_RECORD. -/// -#define EFI_DATA_HUB_STATUS_CODE_RECORD_GUID \ - { \ - 0xd083e94c, 0x6560, 0x42e4, {0xb6, 0xd4, 0x2d, 0xf7, 0x5a, 0xdf, 0x6a, 0x2a } \ - } - -/// -/// The Data Hub data record that is used to store all the parameters passed into -/// the ReportStatusCode() service of the EFI_STATUS_CODE_PROTOCOL. -/// -typedef struct { - /// - /// Status Code type to be reported. - /// - EFI_STATUS_CODE_TYPE CodeType; - - /// - /// An operation, plus value information about the class and subclass, used to - /// classify the hardware and software entity. - /// - EFI_STATUS_CODE_VALUE Value; - - /// - /// The enumeration of a hardware or software entity within - /// the system. Valid instance numbers start with 1. - /// - UINT32 Instance; - - /// - /// Identify the caller. - /// - EFI_GUID CallerId; - - /// - /// Additional status code data. - /// - EFI_STATUS_CODE_DATA Data; -} DATA_HUB_STATUS_CODE_DATA_RECORD; - -extern EFI_GUID gEfiDataHubStatusCodeRecordGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/HdBootVariable.h b/IntelFrameworkModulePkg/Include/Guid/HdBootVariable.h deleted file mode 100644 index fae0839791..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/HdBootVariable.h +++ /dev/null @@ -1,31 +0,0 @@ -/** @file - GUID used as EFI Variable for the device path of Boot file on HardDevice. - -Copyright (c) 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __HD_DEVICE_PATH_VARIABLE_GUID_H__ -#define __HD_DEVICE_PATH_VARIABLE_GUID_H__ - -/// -/// This GUID is used for an EFI Variable that stores the front device pathes -/// for a partial device path that starts with the HD node. -/// -#define HD_BOOT_DEVICE_PATH_VARIABLE_GUID \ - { \ - 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } \ - } - -#define HD_BOOT_DEVICE_PATH_VARIABLE_NAME L"HDDP" - -extern EFI_GUID gHdBootDevicePathVariablGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/IntelFrameworkModulePkgTokenSpace.h b/IntelFrameworkModulePkg/Include/Guid/IntelFrameworkModulePkgTokenSpace.h deleted file mode 100644 index a80c2315ba..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/IntelFrameworkModulePkgTokenSpace.h +++ /dev/null @@ -1,27 +0,0 @@ -/** @file - GUID for IntelFrameworkModulePkg PCD Token Space - -Copyright (c) 2009 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 _INTEL_FRAMEWOKR_MODULEPKG_TOKEN_SPACE_GUID_H_ -#define _INTEL_FRAMEWOKR_MODULEPKG_TOKEN_SPACE_GUID_H_ - -/// -/// The Global ID for the IntelFrameworkModulePkg PCD Token Space . -/// -#define INTEL_FRAMEWORK_MODULEPKG_TOKEN_SPACE_GUID \ - { \ - 0xD3705011, 0xBC19, 0x4af7, { 0xBE, 0x16, 0xF6, 0x80, 0x30, 0x37, 0x8C, 0x15 } \ - } - -extern EFI_GUID gEfiIntelFrameworkModulePkgTokenSpaceGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/LastEnumLang.h b/IntelFrameworkModulePkg/Include/Guid/LastEnumLang.h deleted file mode 100644 index 8d9e37fab2..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/LastEnumLang.h +++ /dev/null @@ -1,31 +0,0 @@ -/** @file - GUID used as EFI variable to store platform language at last time enumeration. - -Copyright (c) 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __LAST_ENUM_LANGUAGE_GUID_H__ -#define __LAST_ENUM_LANGUAGE_GUID_H__ - -/// -/// This GUID is used for Set/Get platform language into/from variable at last time enumeration -/// to ensure the enumeration will only execute once. -/// -#define LAST_ENUM_LANGUAGE_GUID \ - { \ - 0xe8c545b, 0xa2ee, 0x470d, { 0x8e, 0x26, 0xbd, 0xa1, 0xa1, 0x3c, 0xa, 0xa3 } \ - } - -#define LAST_ENUM_LANGUAGE_VARIABLE_NAME L"LastEnumLang" - -extern EFI_GUID gLastEnumLangGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/LegacyBios.h b/IntelFrameworkModulePkg/Include/Guid/LegacyBios.h deleted file mode 100644 index 1fcea9ccfb..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/LegacyBios.h +++ /dev/null @@ -1,36 +0,0 @@ -/** @file - Defines a Tag GUID used to mark a UEFI legacy BIOS thunk driver based - on legacy BIOS services and legacy option ROM. This Tag GUID must be installed on - the ImageHandle of any module that follows the EFI Driver Model and uses - the Int86() or FarCall() services of the Legacy Bios Protocol to produce - a standard UEFI I/O Protocol. - -Copyright (c) 2006 - 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 _LEGACY_BIOS_H_ -#define _LEGACY_BIOS_H_ - -/// -/// The Global ID for the Legacy BIOS GUID that must be installed onto the ImageHandle -/// of any module follows the EFI Driver Model and uses the Int86() or FarCall() -/// services of the Legacy BIOS Protocol to produce a standard UEFI I/O Protocol. -/// -#define EFI_LEGACY_BIOS_GUID \ - { \ - 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 } \ - } - -extern EFI_GUID gEfiLegacyBiosGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/LegacyDevOrder.h b/IntelFrameworkModulePkg/Include/Guid/LegacyDevOrder.h deleted file mode 100644 index 684f098d58..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/LegacyDevOrder.h +++ /dev/null @@ -1,45 +0,0 @@ -/** @file - Guid of a NV Variable which store the information about the - FD/HD/CD/NET/BEV order. - -Copyright (c) 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __LEGACY_DEV_ORDER_VARIABLE_GUID_H__ -#define __LEGACY_DEV_ORDER_VARIABLE_GUID_H__ - -/// -/// Name and Guid of a NV Variable which stores the information about the -/// FD/HD/CD/NET/BEV order -/// -#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \ - { \ - 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52} \ - } - -typedef UINT8 BBS_TYPE; - -#pragma pack(1) -typedef struct { - BBS_TYPE BbsType; - /// - /// Length = sizeof (UINT16) + sizeof (Data) - /// - UINT16 Length; - UINT16 Data[1]; -} LEGACY_DEV_ORDER_ENTRY; -#pragma pack() - -#define VAR_LEGACY_DEV_ORDER L"LegacyDevOrder" - -extern EFI_GUID gEfiLegacyDevOrderVariableGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Guid/TianoDecompress.h b/IntelFrameworkModulePkg/Include/Guid/TianoDecompress.h deleted file mode 100644 index 7c2a6a6b93..0000000000 --- a/IntelFrameworkModulePkg/Include/Guid/TianoDecompress.h +++ /dev/null @@ -1,28 +0,0 @@ -/** @file - Tiano Custom decompress Guid definition. - -Copyright (c) 2006 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __TIANO_CUSTOM_DECOMPRESS_GUID_H__ -#define __TIANO_CUSTOM_DECOMPRESS_GUID_H__ - -/// -/// The Global ID used to identify a section of an FFS file of type -/// EFI_SECTION_GUID_DEFINED, whose contents have been compressed using -/// Tiano Custom compression. -/// -#define TIANO_CUSTOM_DECOMPRESS_GUID \ - { 0xA31280AD, 0x481E, 0x41B6, { 0x95, 0xE8, 0x12, 0x7F, 0x4C, 0x98, 0x47, 0x79 } } - -extern GUID gTianoCustomDecompressGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Library/GenericBdsLib.h b/IntelFrameworkModulePkg/Include/Library/GenericBdsLib.h deleted file mode 100644 index ecd68a003b..0000000000 --- a/IntelFrameworkModulePkg/Include/Library/GenericBdsLib.h +++ /dev/null @@ -1,1114 +0,0 @@ -/** @file - Generic BDS library defines general interfaces for a BDS driver, including: - 1) BDS boot policy interface. - 2) BDS boot device connect interface. - 3) BDS Misc interfaces for mainting boot variable, ouput string. - -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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 _GENERIC_BDS_LIB_H_ -#define _GENERIC_BDS_LIB_H_ - -#include - -/// -/// Constants which are variable names used to access variables. -/// -#define VAR_LEGACY_DEV_ORDER L"LegacyDevOrder" - -/// -/// Data structures and defines. -/// -#define FRONT_PAGE_QUESTION_ID 0x0000 -#define FRONT_PAGE_DATA_WIDTH 0x01 - -/// -/// ConnectType -/// -#define CONSOLE_OUT 0x00000001 -#define STD_ERROR 0x00000002 -#define CONSOLE_IN 0x00000004 -#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR) - -/// -/// Load Option Attributes -/// -#define LOAD_OPTION_ACTIVE 0x00000001 -#define LOAD_OPTION_FORCE_RECONNECT 0x00000002 - -#define LOAD_OPTION_HIDDEN 0x00000008 -#define LOAD_OPTION_CATEGORY 0x00001F00 - -#define LOAD_OPTION_CATEGORY_BOOT 0x00000000 -#define LOAD_OPTION_CATEGORY_APP 0x00000100 - -#define EFI_BOOT_OPTION_SUPPORT_KEY 0x00000001 -#define EFI_BOOT_OPTION_SUPPORT_APP 0x00000002 - -#define IS_LOAD_OPTION_TYPE(_c, _Mask) (BOOLEAN) (((_c) & (_Mask)) != 0) - -/// -/// Define the maximum characters that will be accepted. -/// -#define MAX_CHAR 480 -#define MAX_CHAR_SIZE (MAX_CHAR * 2) - -/// -/// Define maximum characters for boot option variable "BootXXXX". -/// -#define BOOT_OPTION_MAX_CHAR 10 - -// -// This data structure is the part of BDS_CONNECT_ENTRY -// -#define BDS_LOAD_OPTION_SIGNATURE SIGNATURE_32 ('B', 'd', 'C', 'O') - -typedef struct { - - UINTN Signature; - LIST_ENTRY Link; - - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - - CHAR16 *OptionName; - UINTN OptionNumber; - UINT16 BootCurrent; - UINT32 Attribute; - CHAR16 *Description; - VOID *LoadOptions; - UINT32 LoadOptionsSize; - CHAR16 *StatusString; - -} BDS_COMMON_OPTION; - -typedef struct { - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - UINTN ConnectType; -} BDS_CONSOLE_CONNECT_ENTRY; - -// -// Bds boot related lib functions -// -/** - Boot from the UEFI spec defined "BootNext" variable. - -**/ -VOID -EFIAPI -BdsLibBootNext ( - VOID - ); - -/** - Process the boot option according to the UEFI specification. The legacy boot option device path includes BBS_DEVICE_PATH. - - @param Option The boot option to be processed. - @param DevicePath The device path describing where to load the - boot image or the legcy 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 succeeded. - @retval EFI_NOT_FOUND 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 - ); - - -/** - This function will enumerate all possible boot devices in the system, and - automatically create boot options for Network, Shell, Removable BlockIo, - and Non-BlockIo Simplefile devices. - - BDS separates EFI boot options into six types: - 1. Network - The boot option points to the SimpleNetworkProtocol device. - Bds will try to automatically create this type of boot option during enumeration. - 2. Shell - The boot option points to internal flash shell. - Bds will try to automatically create this type of boot option during enumeration. - 3. Removable BlockIo - The boot option points to a removable media - device, such as a USB flash drive or DVD drive. - These devices 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 points to a Fixed blockIo device, - such as a hard disk. - These devices 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 options, - whose description rules 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 the user, either manually or with an OS loader. BDS will not delete or modify - these boot options. - - This function will enumerate all possible boot devices in the system, and - automatically create boot options for Network, Shell, Removable BlockIo, - and Non-BlockIo Simplefile devices. - It will excute once every boot. - - @param BdsBootOptionList The header of the linked list that indexed all - current boot options. - - @retval EFI_SUCCESS Finished all the boot device enumerations and - created the boot option based on the 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 - ); - -/** - Build the boot option with the handle parsed in. - - @param Handle The handle representing the device path for which - to create a boot option. - @param BdsBootOptionList The header of the link list that 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 - ); - - -/** - Build the on flash shell boot option with the handle parsed in. - - @param Handle The handle which present the device path to create - the on flash shell boot option. - @param BdsBootOptionList The header of the link list that indexed all - current boot options. - -**/ -VOID -EFIAPI -BdsLibBuildOptionFromShell ( - IN EFI_HANDLE Handle, - IN OUT LIST_ENTRY *BdsBootOptionList - ); - -// -// Bds misc lib functions -// -/** - Get boot mode by looking up the configuration table and parsing the HOB list. - - @param BootMode The boot mode from PEI handoff HOB. - - @retval EFI_SUCCESS Successfully got boot mode. - -**/ -EFI_STATUS -EFIAPI -BdsLibGetBootMode ( - OUT EFI_BOOT_MODE *BootMode - ); - - -/** - The function will go through the driver option link list, and then load and start - every driver to which the driver option device path points. - - @param BdsDriverLists The header of the current driver option link list. - -**/ -VOID -EFIAPI -BdsLibLoadDrivers ( - IN LIST_ENTRY *BdsDriverLists - ); - - -/** - This function processes BootOrder or DriverOrder variables, by calling - - BdsLibVariableToOption () for each UINT16 in the variables. - - @param BdsCommonOptionList The header of the option list base on the variable - VariableName. - @param VariableName An EFI Variable name indicate the BootOrder or - DriverOrder. - - @retval EFI_SUCCESS Successfully created the boot option or driver option - list. - @retval EFI_OUT_OF_RESOURCES Failed to get the boot option or the driver option list. -**/ -EFI_STATUS -EFIAPI -BdsLibBuildOptionFromVar ( - IN LIST_ENTRY *BdsCommonOptionList, - IN CHAR16 *VariableName - ); - -/** - This function reads the EFI variable (VendorGuid/Name) and returns a dynamically allocated - buffer and the size of the buffer. If it fails, return NULL. - - @param Name The string part of the EFI variable name. - @param VendorGuid The GUID part of the EFI variable name. - @param VariableSize Returns the size of the EFI variable that was read. - - @return Dynamically allocated memory that contains a copy - of the EFI variable. The caller is responsible for - freeing the buffer. - @retval NULL The variable was not read. - -**/ -VOID * -EFIAPI -BdsLibGetVariableAndSize ( - IN CHAR16 *Name, - IN EFI_GUID *VendorGuid, - OUT UINTN *VariableSize - ); - - -/** - This function prints a series of strings. - - @param ConOut A pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. - @param ... A variable argument list containing a series of - strings, the last string must be NULL. - - @retval EFI_SUCCESS Successfully printed 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, - ... - ); - -/** - 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, indicates if it is boot#### or - driver####. - - @retval BDS_COMMON_OPTION The option that was created. - @retval NULL Failed to get the new option. - -**/ -BDS_COMMON_OPTION * -EFIAPI -BdsLibVariableToOption ( - IN OUT LIST_ENTRY *BdsCommonOptionList, - IN CHAR16 *VariableName - ); - -/** - This function registers the new boot#### or driver#### option based 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 that 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 successfully - 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 - ); - -// -// Bds connect and disconnect driver lib funcions -// -/** - This function connects all system drivers with the corresponding controllers. - -**/ -VOID -EFIAPI -BdsLibConnectAllDriversToAllControllers ( - VOID - ); - -/** - This function connects all system drivers to controllers. - -**/ -VOID -EFIAPI -BdsLibConnectAll ( - VOID - ); - -/** - This function will create all handles associate with every device - path node. If the handle associate with one device path node can not - be created successfully, then still give chance to do the dispatch, - which load the missing drivers if possible. - - @param DevicePathToConnect The device path to be connected. Can be - a multi-instance device path. - - @retval EFI_SUCCESS All handles associates with every device path node - were created. - @retval EFI_OUT_OF_RESOURCES Not enough resources to create new handles. - @retval EFI_NOT_FOUND At least one handle could not be created. - -**/ -EFI_STATUS -EFIAPI -BdsLibConnectDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect - ); - -/** - 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 child handles have been - connected. - @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer(). -**/ -EFI_STATUS -EFIAPI -BdsLibConnectAllEfi ( - VOID - ); - -/** - 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 - ); - -// -// Bds console related lib functions -// -/** - This function will search every simpletxt device in the current system, - and make every simpletxt device a potential console device. - -**/ -VOID -EFIAPI -BdsLibConnectAllConsoles ( - VOID - ); - - -/** - This function will connect console device based on the console - device variable ConIn, ConOut and ErrOut. - - @retval EFI_SUCCESS At least one of the ConIn and ConOut devices have - been connected. - @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable (). - -**/ -EFI_STATUS -EFIAPI -BdsLibConnectAllDefaultConsoles ( - VOID - ); - - -/** - 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 - ); - - -/** - This function updates the console variable based on ConVarName. It can - add or remove one specific console device path from the variable - - @param ConVarName The console-related variable name: ConIn, ConOut, - ErrOut. - @param CustomizedConDevicePath The console device path to be added to - the console variable ConVarName. Cannot be multi-instance. - @param ExclusiveDevicePath The console device path to be removed - from the console variable ConVarName. Cannot be multi-instance. - - @retval EFI_UNSUPPORTED The added device path is the same as a removed one. - @retval EFI_SUCCESS Successfully added or removed the device path from the - console variable. - -**/ -EFI_STATUS -EFIAPI -BdsLibUpdateConsoleVariable ( - IN CHAR16 *ConVarName, - IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath - ); - -/** - Connect the console device base on the variable ConVarName, if - device path of the ConVarName is multi-instance device path 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 - ); - -// -// Bds device path related lib functions -// -/** - Delete the instance in Multi that overlaps with Single. - - @param Multi A pointer to a multi-instance device path data - structure. - @param Single A pointer to a single-instance device path data - structure. - - @return This function removes the device path instances in Multi that overlap - Single, and returns the resulting device path. If there is no - remaining device path as a result, this function will return NULL. - -**/ -EFI_DEVICE_PATH_PROTOCOL * -EFIAPI -BdsLibDelPartMatchInstance ( - IN EFI_DEVICE_PATH_PROTOCOL *Multi, - IN EFI_DEVICE_PATH_PROTOCOL *Single - ); - -/** - This function compares a device path data structure to that of all the nodes of a - second device path instance. - - @param Multi A pointer to a multi-instance device path data - structure. - @param Single A pointer to a single-instance device path data - structure. - - @retval TRUE If the Single device path is contained within a - Multi device path. - @retval FALSE The Single device path is not contained within a - Multi device path. - -**/ -BOOLEAN -EFIAPI -BdsLibMatchDevicePaths ( - IN EFI_DEVICE_PATH_PROTOCOL *Multi, - IN EFI_DEVICE_PATH_PROTOCOL *Single - ); - -/** - This function converts an input device structure to a Unicode string. - - @param DevPath A pointer to the device path structure. - - @return A newly allocated Unicode string that represents the device path. - -**/ -CHAR16 * -EFIAPI -DevicePathToStr ( - IN EFI_DEVICE_PATH_PROTOCOL *DevPath - ); - -// -// Internal definitions -// -typedef struct { - CHAR16 *Str; - UINTN Len; - UINTN Maxlen; -} POOL_PRINT; - -typedef -VOID -(*DEV_PATH_FUNCTION) ( - IN OUT POOL_PRINT *Str, - IN VOID *DevPath - ); - -typedef struct { - UINT8 Type; - UINT8 SubType; - DEV_PATH_FUNCTION Function; -} DEVICE_PATH_STRING_TABLE; - -typedef struct { - EFI_DEVICE_PATH_PROTOCOL Header; - EFI_GUID Guid; - UINT8 VendorDefinedData[1]; -} VENDOR_DEVICE_PATH_WITH_DATA; - -typedef struct { - EFI_DEVICE_PATH_PROTOCOL Header; - UINT16 NetworkProtocol; - UINT16 LoginOption; - UINT64 Lun; - UINT16 TargetPortalGroupTag; - CHAR16 TargetName[1]; -} ISCSI_DEVICE_PATH_WITH_NAME; - -// -// BBS support macros and functions -// - -#if defined(MDE_CPU_IA32) || defined(MDE_CPU_X64) -#define REFRESH_LEGACY_BOOT_OPTIONS \ - BdsDeleteAllInvalidLegacyBootOptions ();\ - BdsAddNonExistingLegacyBootOptions (); \ - BdsUpdateLegacyDevOrder () -#else -#define REFRESH_LEGACY_BOOT_OPTIONS -#endif - -/** - Delete all the invalid legacy boot options. - - @retval EFI_SUCCESS All invalid legacy boot options are deleted. - @retval EFI_OUT_OF_RESOURCES Failed to allocate necessary memory. - @retval EFI_NOT_FOUND Failed to retrieve variable of boot order. - -**/ -EFI_STATUS -EFIAPI -BdsDeleteAllInvalidLegacyBootOptions ( - VOID - ); - -/** - Add the legacy boot options from BBS table if they do not exist. - - @retval EFI_SUCCESS The boot options were 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 - ); - -/** - Add the legacy boot devices from BBS table into - the legacy device boot order. - - @retval EFI_SUCCESS The boot devices were added successfully. - @retval EFI_NOT_FOUND The legacy boot devices are not found. - @retval EFI_OUT_OF_RESOURCES Memory or storage is not enough. - @retval EFI_DEVICE_ERROR Failed to add the legacy device boot order into EFI variable - because of a hardware error. -**/ -EFI_STATUS -EFIAPI -BdsUpdateLegacyDevOrder ( - VOID - ); - -/** - Refresh the boot priority for BBS entries based on boot option entry and boot order. - - @param Entry The boot option is to be checked for a refreshed BBS table. - - @retval EFI_SUCCESS The boot priority for BBS entries 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 - ); - -/** - Delete the Boot Option from EFI Variable. The Boot Order Arrray - is also updated. - - @param OptionNumber The number of Boot options wanting 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 - ); - -// -//The interface functions related to the Setup Browser Reset Reminder feature -// -/** - Enable the setup browser reset reminder feature. - This routine is used in a platform tip. If the platform policy needs the feature, use the routine to enable it. - -**/ -VOID -EFIAPI -EnableResetReminderFeature ( - VOID - ); - -/** - Disable the setup browser reset reminder feature. - This routine is used in a platform tip. If the platform policy does not want the feature, use the routine to disable it. - -**/ -VOID -EFIAPI -DisableResetReminderFeature ( - VOID - ); - -/** - 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 - ); - - -/** - 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 - ); - -/** - Check whether platform policy enables the reset reminder feature. The default is enabled. - -**/ -BOOLEAN -EFIAPI -IsResetReminderFeatureEnable ( - VOID - ); - -/** - Check if the user changed any option setting that needs a system reset to be effective. - -**/ -BOOLEAN -EFIAPI -IsResetRequired ( - VOID - ); - -/** - Check whether a reset is needed, and finish the reset reminder feature. - If a reset is needed, pop up a menu to notice user, and finish the feature - according to the user selection. - -**/ -VOID -EFIAPI -SetupResetReminder ( - VOID - ); - - -/// -/// Define the boot type with which to classify the boot option type. -/// Different boot option types could have different boot behaviors. -/// Use their device path node (Type + SubType) as the type value. -/// The boot type here can be added according to requirements. -/// - -/// -/// ACPI boot type. For ACPI devices, using sub-types to distinguish devices is not allowed, so hardcode their values. -/// -#define BDS_EFI_ACPI_FLOPPY_BOOT 0x0201 -/// -/// Message boot type -/// If a device path of boot option only points to a message node, the boot option is a message boot type. -/// -#define BDS_EFI_MESSAGE_ATAPI_BOOT 0x0301 // Type 03; Sub-Type 01 -#define BDS_EFI_MESSAGE_SCSI_BOOT 0x0302 // Type 03; Sub-Type 02 -#define BDS_EFI_MESSAGE_USB_DEVICE_BOOT 0x0305 // Type 03; Sub-Type 05 -#define BDS_EFI_MESSAGE_SATA_BOOT 0x0312 // Type 03; Sub-Type 18 -#define BDS_EFI_MESSAGE_MAC_BOOT 0x030b // Type 03; Sub-Type 11 -#define BDS_EFI_MESSAGE_MISC_BOOT 0x03FF - -/// -/// Media boot type -/// If a device path of boot option contains a media node, the boot option is media boot type. -/// -#define BDS_EFI_MEDIA_HD_BOOT 0x0401 // Type 04; Sub-Type 01 -#define BDS_EFI_MEDIA_CDROM_BOOT 0x0402 // Type 04; Sub-Type 02 -/// -/// BBS boot type -/// If a device path of boot option contains a BBS node, the boot option is BBS boot type. -/// -#define BDS_LEGACY_BBS_BOOT 0x0501 // Type 05; Sub-Type 01 - -#define BDS_EFI_UNSUPPORT 0xFFFF - -/** - Check whether an instance in BlockIoDevicePath has the same partition node as the HardDriveDevicePath device path. - - @param BlockIoDevicePath Multi device path instances to check. - @param HardDriveDevicePath A device path starting 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 - ); - - -/** - 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. This function enables the device to boot. - To avoid requiring a connect on every boot, the front match is saved in a variable (the part point - to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ). - All successful history device paths - that point to the front part of the partition node 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 - ); - -/** - Return the bootable media handle. - First, check whether the device is connected. - Second, check whether the device path points to a device that supports SimpleFileSystemProtocol. - Third, detect the the default boot file in the Media, and return the removable Media handle. - - @param DevicePath The 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 - ); - - -/** - Checks whether the Device path in a boot option points to a valid bootable device, and if the device - is ready to boot now. - - @param DevPath The Device path in a boot option. - @param CheckMedia If true, check whether 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 - ); - -/** - Checks whether the Device path in a boot option points to a valid bootable device, and if the device - is ready to boot now. - If Description is not NULL and the device path points to a fixed BlockIo - device, this function checks whether the description conflicts with other auto-created - boot options. - - @param DevPath The Device path in a boot option. - @param CheckMedia If true, checks if the device is ready to boot now. - @param Description The description of 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 - ); - -/** - For a bootable Device path, return its boot type. - - @param DevicePath The bootable device Path to check. - - @retval BDS_EFI_MEDIA_HD_BOOT The given device path contains MEDIA_DEVICE_PATH type device path node, - whose subtype is MEDIA_HARDDRIVE_DP. - @retval BDS_EFI_MEDIA_CDROM_BOOT If given device path contains MEDIA_DEVICE_PATH type device path node, - whose subtype is MEDIA_CDROM_DP. - @retval BDS_EFI_ACPI_FLOPPY_BOOT A given device path contains ACPI_DEVICE_PATH type device path node, - whose HID is floppy device. - @retval BDS_EFI_MESSAGE_ATAPI_BOOT A 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 A 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 A 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 The device path does not contain any media device path node, and - its last device path node points to a message device path node. - @retval BDS_LEGACY_BBS_BOOT A given device path contains BBS_DEVICE_PATH type device path node. - @retval BDS_EFI_UNSUPPORT An EFI Removable BlockIO device path does not point to a media and message device. - - **/ -UINT32 -EFIAPI -BdsGetBootTypeFromDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ); - - -/** - This routine registers a function to adjust the different types of memory page numbers - just before booting, and saves the updated info into the variable for the next boot to use. - -**/ -VOID -EFIAPI -BdsLibSaveMemoryTypeInformation ( - VOID - ); - -/** - Identify a user and, if authenticated, returns the current user profile handle. - - @param[out] User Points to the user profile handle. - - @retval EFI_SUCCESS The user is successfully identified, or user identification - is not supported. - @retval EFI_ACCESS_DENIED The user was not successfully identified. - -**/ -EFI_STATUS -EFIAPI -BdsLibUserIdentify ( - OUT EFI_USER_PROFILE_HANDLE *User - ); - -/** - This function checks if a Fv file device path is valid, according to a file GUID. If it is invalid, - it tries to return the valid device path. - FV address maybe changes for memory layout adjust from time to time, use this funciton - could promise the Fv file device path is right. - - @param DevicePath On input, the Fv file device path to check. On - output, the updated valid Fv file device path - @param FileGuid the Fv file GUID. - - @retval EFI_INVALID_PARAMETER The input DevicePath or FileGuid is invalid. - @retval EFI_UNSUPPORTED The input DevicePath does not contain an Fv file - GUID at all. - @retval EFI_ALREADY_STARTED The input DevicePath has pointed to the Fv file and is - valid. - @retval EFI_SUCCESS Successfully updated the invalid DevicePath - and returned the updated device path in DevicePath. - -**/ -EFI_STATUS -EFIAPI -BdsLibUpdateFvFileDevicePath ( - IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath, - IN EFI_GUID *FileGuid - ); - - -/** - Connect the specific USB device that matches the RemainingDevicePath, - 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. - - @retval EFI_SUCCESS The specific Usb device is connected successfully. - @retval EFI_INVALID_PARAMETER Invalid HostControllerPi (not 0x00, 0x20 or 0xFF) - or RemainingDevicePath is not the USB class device path. - @retval EFI_NOT_FOUND The device specified by device path is not found. - -**/ -EFI_STATUS -EFIAPI -BdsLibConnectUsbDevByShortFormDP( - IN UINT8 HostControllerPI, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - - -// -// The implementation of this function is provided by Platform code. -// -/** - Convert Vendor device path to a device name. - - @param Str The buffer storing device name. - @param DevPath The pointer to vendor device path. - -**/ -VOID -DevPathVendor ( - IN OUT POOL_PRINT *Str, - IN VOID *DevPath - ); - -/** - Concatenates a formatted unicode string to an allocated pool. - The caller must free the resulting buffer. - - @param Str Tracks the allocated pool, size in use, and amount of pool allocated. - @param Fmt The format string. - @param ... The data will be printed. - - @return Allocated buffer with the formatted string printed in it. - The caller must free the allocated buffer. - The buffer allocation is not packed. - -**/ -CHAR16 * -EFIAPI -CatPrint ( - IN OUT POOL_PRINT *Str, - IN CHAR16 *Fmt, - ... - ); - -/** - Use SystemTable ConOut to stop video based Simple Text Out consoles from going - to the video device. Put up LogoFile on every video device that is a console. - - @param[in] LogoFile The file name of logo to display on the center of the screen. - - @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed. - @retval EFI_UNSUPPORTED Logo not found. - -**/ -EFI_STATUS -EFIAPI -EnableQuietBoot ( - IN EFI_GUID *LogoFile - ); - - -/** - Use SystemTable ConOut to turn on video based Simple Text Out consoles. The - Simple Text Out screens will now be synced up with all non-video output devices. - - @retval EFI_SUCCESS UGA devices are back in text mode and synced up. - -**/ -EFI_STATUS -EFIAPI -DisableQuietBoot ( - VOID - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Include/Library/PlatformBdsLib.h b/IntelFrameworkModulePkg/Include/Library/PlatformBdsLib.h deleted file mode 100644 index af237a6030..0000000000 --- a/IntelFrameworkModulePkg/Include/Library/PlatformBdsLib.h +++ /dev/null @@ -1,156 +0,0 @@ -/** @file - Platform BDS library definition. A platform can implement - instances to support platform-specific behavior. - -Copyright (c) 2008 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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_BDS_LIB_H_ -#define __PLATFORM_BDS_LIB_H_ - -#include -#include - -/** - Perform the memory test base on the memory test intensive level, - and update the memory resource. - - @param Level The memory test intensive level. - - @retval EFI_STATUS Successfully test all the system memory, and update - the memory resource - -**/ -typedef -EFI_STATUS -(EFIAPI *BASEM_MEMORY_TEST)( - IN EXTENDMEM_COVERAGE_LEVEL Level - ); - -/** - This routine is called to see if there are any capsules we need to process. - If the boot mode is not UPDATE, then we do nothing. Otherwise, find the - capsule HOBS and produce firmware volumes for them via the DXE service. - Then call the dispatcher to dispatch drivers from them. Finally, check - the status of the updates. - - This function should be called by BDS in case we need to do some - sort of processing even if there is no capsule to process. We - need to do this if an earlier update went away and we need to - clear the capsule variable so on the next reset PEI does not see it and - think there is a capsule available. - - @param BootMode The current boot mode - - @retval EFI_INVALID_PARAMETER The boot mode is not correct for an update. - @retval EFI_SUCCESS There is no error when processing a capsule. - -**/ -typedef -EFI_STATUS -(EFIAPI *PROCESS_CAPSULES)( - IN EFI_BOOT_MODE BootMode - ); - -/** - Platform Bds initialization. Includes the platform firmware vendor, revision - and so crc check. - -**/ -VOID -EFIAPI -PlatformBdsInit ( - VOID - ); - -/** - 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() - -**/ -VOID -EFIAPI -PlatformBdsPolicyBehavior ( - IN LIST_ENTRY *DriverOptionList, - IN LIST_ENTRY *BootOptionList, - IN PROCESS_CAPSULES ProcessCapsules, - IN BASEM_MEMORY_TEST BaseMemoryTest - ); - -/** - Hook point for a user-provided function, for after a boot attempt fails. - - @param Option A pointer to Boot Option that failed to boot. - @param Status The status returned from failed boot. - @param ExitData The exit data returned from failed boot. - @param ExitDataSize The exit data size returned from failed boot. - -**/ -VOID -EFIAPI -PlatformBdsBootFail ( - IN BDS_COMMON_OPTION *Option, - IN EFI_STATUS Status, - IN CHAR16 *ExitData, - IN UINTN ExitDataSize - ); - -/** - 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 also a platform implementation, and can be customized by an IBV/OEM. - - @param Option A pointer to the Boot Option that successfully booted. - -**/ -VOID -EFIAPI -PlatformBdsBootSuccess ( - IN BDS_COMMON_OPTION *Option - ); - - -/** - This function locks platform flash that is not allowed to be updated during normal boot path. - The flash layout is platform specific. - - **/ -VOID -EFIAPI -PlatformBdsLockNonUpdatableFlash ( - VOID - ); - -/** - 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 The 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 - ); - -#endif diff --git a/IntelFrameworkModulePkg/Include/Protocol/ExitPmAuth.h b/IntelFrameworkModulePkg/Include/Protocol/ExitPmAuth.h deleted file mode 100644 index 748ab96620..0000000000 --- a/IntelFrameworkModulePkg/Include/Protocol/ExitPmAuth.h +++ /dev/null @@ -1,25 +0,0 @@ -/** @file - Defines the ExitPmAuth protocol. - -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 _EXIT_PM_AUTH_PROTOCOL_H_ -#define _EXIT_PM_AUTH_PROTOCOL_H_ - -#define EXIT_PM_AUTH_PROTOCOL_GUID \ - { 0xd088a413, 0xa70, 0x4217, { 0xba, 0x55, 0x9a, 0x3c, 0xb6, 0x5c, 0x41, 0xb3 }} - -extern EFI_GUID gExitPmAuthProtocolGuid; - -#endif // #ifndef _EXIT_PM_AUTH_PROTOCOL_H_ diff --git a/IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h b/IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h deleted file mode 100644 index 7de3504417..0000000000 --- a/IntelFrameworkModulePkg/Include/Protocol/IsaAcpi.h +++ /dev/null @@ -1,304 +0,0 @@ -/** @file - EFI ISA ACPI Protocol is used to enumerate and manage all the ISA controllers on - the platform's ISA Bus. - -Copyright (c) 2006 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __ISA_ACPI_H_ -#define __ISA_ACPI_H_ - -/// -/// Global ID for the EFI ISA ACPI Protocol. -/// -#define EFI_ISA_ACPI_PROTOCOL_GUID \ - { \ - 0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55 } \ - } - -/// -/// Forward declaration fo the EFI ISA ACPI Protocol -/// -typedef struct _EFI_ISA_ACPI_PROTOCOL EFI_ISA_ACPI_PROTOCOL; - -/// -/// ISA ACPI Protocol interrupt resource attributes. -/// -#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE 0x01 ///< Edge triggered interrupt on a rising edge. -#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE 0x02 ///< Edge triggered interrupt on a falling edge. -#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE 0x04 ///< Level sensitive interrupt active high. -#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE 0x08 ///< Level sensitive interrupt active low. - -/// -/// ISA ACPI Protocol DMA resource attributes. -/// -#define EFI_ISA_ACPI_DMA_SPEED_TYPE_MASK 0x03 ///< Bit mask of supported DMA speed attributes. -#define EFI_ISA_ACPI_DMA_SPEED_TYPE_COMPATIBILITY 0x00 ///< ISA controller supports compatibility mode DMA transfers. -#define EFI_ISA_ACPI_DMA_SPEED_TYPE_A 0x01 ///< ISA controller supports type A DMA transfers. -#define EFI_ISA_ACPI_DMA_SPEED_TYPE_B 0x02 ///< ISA controller supports type B DMA transfers. -#define EFI_ISA_ACPI_DMA_SPEED_TYPE_F 0x03 ///< ISA controller supports type F DMA transfers. -#define EFI_ISA_ACPI_DMA_COUNT_BY_BYTE 0x04 ///< ISA controller increments DMA address by bytes (8-bit). -#define EFI_ISA_ACPI_DMA_COUNT_BY_WORD 0x08 ///< ISA controller increments DMA address by words (16-bit). -#define EFI_ISA_ACPI_DMA_BUS_MASTER 0x10 ///< ISA controller is a DMA bus master. -#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT 0x20 ///< ISA controller only supports 8-bit DMA transfers. -#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT 0x40 ///< ISA controller both 8-bit and 16-bit DMA transfers. -#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x80 ///< ISA controller only supports 16-bit DMA transfers. - -/// -/// ISA ACPI Protocol MMIO resource attributes -/// -#define EFI_ISA_ACPI_MEMORY_WIDTH_MASK 0x03 ///< Bit mask of supported ISA memory width attributes. -#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT 0x00 ///< ISA MMIO region only supports 8-bit access. -#define EFI_ISA_ACPI_MEMORY_WIDTH_16_BIT 0x01 ///< ISA MMIO region only supports 16-bit access. -#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT_AND_16_BIT 0x02 ///< ISA MMIO region supports both 8-bit and 16-bit access. -#define EFI_ISA_ACPI_MEMORY_WRITEABLE 0x04 ///< ISA MMIO region supports write transactions. -#define EFI_ISA_ACPI_MEMORY_CACHEABLE 0x08 ///< ISA MMIO region supports being cached. -#define EFI_ISA_ACPI_MEMORY_SHADOWABLE 0x10 ///< ISA MMIO region may be shadowed. -#define EFI_ISA_ACPI_MEMORY_EXPANSION_ROM 0x20 ///< ISA MMIO region is an expansion ROM. - -/// -/// ISA ACPI Protocol I/O resource attributes -/// -#define EFI_ISA_ACPI_IO_DECODE_10_BITS 0x01 ///< ISA controllers uses a 10-bit address decoder for I/O cycles. -#define EFI_ISA_ACPI_IO_DECODE_16_BITS 0x02 ///< ISA controllers uses a 16-bit address decoder for I/O cycles. - -/// -/// EFI ISA ACPI resource type -/// -typedef enum { - EfiIsaAcpiResourceEndOfList, ///< Marks the end if a resource list. - EfiIsaAcpiResourceIo, ///< ISA I/O port resource range. - EfiIsaAcpiResourceMemory, ///< ISA MMIO resource range. - EfiIsaAcpiResourceDma, ///< ISA DMA resource. - EfiIsaAcpiResourceInterrupt ///< ISA interrupt resource. -} EFI_ISA_ACPI_RESOURCE_TYPE; - -/// -/// EFI ISA ACPI generic resource structure -/// -typedef struct { - EFI_ISA_ACPI_RESOURCE_TYPE Type; ///< The type of resource (I/O, MMIO, DMA, Interrupt). - UINT32 Attribute; ///< Bit mask of attributes associated with this resource. See EFI_ISA_ACPI_xxx macros for valid combinations. - UINT32 StartRange; ///< The start of the resource range. - UINT32 EndRange; ///< The end of the resource range. -} EFI_ISA_ACPI_RESOURCE; - -/// -/// EFI ISA ACPI resource device identifier -/// -typedef struct { - UINT32 HID; ///< The ACPI Hardware Identifier value associated with an ISA controller. Matchs ACPI DSDT contents. - UINT32 UID; ///< The ACPI Unique Identifier value associated with an ISA controller. Matches ACPI DSDT contents. -} EFI_ISA_ACPI_DEVICE_ID; - -/// -/// EFI ISA ACPI resource list -/// -typedef struct { - EFI_ISA_ACPI_DEVICE_ID Device; ///< The ACPI HID/UID associated with an ISA controller. - EFI_ISA_ACPI_RESOURCE *ResourceItem; ///< A pointer to the list of resources associated with an ISA controller. -} EFI_ISA_ACPI_RESOURCE_LIST; - -/** - Enumerates the ISA controllers on an ISA bus. - - This service allows all the ISA controllers on an ISA bus to be enumerated. If - Device is a pointer to a NULL value, then the first ISA controller on the ISA - bus is returned in Device and EFI_SUCCESS is returned. If Device is a pointer - to a value that was returned on a prior call to DeviceEnumerate(), then the next - ISA controller on the ISA bus is returned in Device and EFI_SUCCESS is returned. - If Device is a pointer to the last ISA controller on the ISA bus, then - EFI_NOT_FOUND is returned. - - @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. - @param[out] Device The pointer to an ISA controller named by ACPI HID/UID. - - @retval EFI_SUCCESS The next ISA controller on the ISA bus was returned. - @retval EFI_NOT_FOUND No device found. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_ACPI_DEVICE_ENUMERATE)( - IN EFI_ISA_ACPI_PROTOCOL *This, - OUT EFI_ISA_ACPI_DEVICE_ID **Device - ); - -/** - Sets the power state of an ISA controller. - - This services sets the power state of the ISA controller specified by Device to - the power state specified by OnOff. TRUE denotes on, FALSE denotes off. - If the power state is sucessfully set on the ISA Controller, then - EFI_SUCCESS is returned. - - @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. - @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. - @param[in] OnOff TRUE denotes on, FALSE denotes off. - - @retval EFI_SUCCESS Successfully set the power state of the ISA controller. - @retval Other The ISA controller could not be placed in the requested power state. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_ACPI_SET_DEVICE_POWER)( - IN EFI_ISA_ACPI_PROTOCOL *This, - IN EFI_ISA_ACPI_DEVICE_ID *Device, - IN BOOLEAN OnOff - ); - -/** - Retrieves the current set of resources associated with an ISA controller. - - Retrieves the set of I/O, MMIO, DMA, and interrupt resources currently - assigned to the ISA controller specified by Device. These resources - are returned in ResourceList. - - @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. - @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. - @param[out] ResourceList The pointer to the current resource list for Device. - - @retval EFI_SUCCESS Successfully retrieved the current resource list. - @retval EFI_NOT_FOUND The resource list could not be retrieved. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_ACPI_GET_CUR_RESOURCE)( - IN EFI_ISA_ACPI_PROTOCOL *This, - IN EFI_ISA_ACPI_DEVICE_ID *Device, - OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList - ); - -/** - Retrieves the set of possible resources that may be assigned to an ISA controller - with SetResource(). - - Retrieves the possible sets of I/O, MMIO, DMA, and interrupt resources for the - ISA controller specified by Device. The sets are returned in ResourceList. - - @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. - @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. - @param[out] ResourceList The pointer to the returned list of resource lists. - - @retval EFI_UNSUPPORTED This service is not supported. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_ACPI_GET_POS_RESOURCE)( - IN EFI_ISA_ACPI_PROTOCOL *This, - IN EFI_ISA_ACPI_DEVICE_ID *Device, - OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList - ); - -/** - Assigns resources to an ISA controller. - - Assigns the I/O, MMIO, DMA, and interrupt resources specified by ResourceList - to the ISA controller specified by Device. ResourceList must match a resource list returned by GetPosResource() for the same ISA controller. - - @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. - @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. - @param[in] ResourceList The pointer to a resources list that must be one of the - resource lists returned by GetPosResource() for the - ISA controller specified by Device. - - @retval EFI_SUCCESS Successfully set resources on the ISA controller. - @retval Other The resources could not be set for the ISA controller. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_ACPI_SET_RESOURCE)( - IN EFI_ISA_ACPI_PROTOCOL *This, - IN EFI_ISA_ACPI_DEVICE_ID *Device, - IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList - ); - -/** - Enables or disables an ISA controller. - - @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. - @param[in] Device The pointer to the ISA controller to enable/disable. - @param[in] Enable TRUE to enable the ISA controller. FALSE to disable the - ISA controller. - - @retval EFI_SUCCESS Successfully enabled/disabled the ISA controller. - @retval Other The ISA controller could not be placed in the requested state. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_ACPI_ENABLE_DEVICE)( - IN EFI_ISA_ACPI_PROTOCOL *This, - IN EFI_ISA_ACPI_DEVICE_ID *Device, - IN BOOLEAN Enable - ); - -/** - Initializes an ISA controller, so that it can be used. This service must be called - before SetResource(), EnableDevice(), or SetPower() will behave as expected. - - @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. - @param[in] Device The pointer to an ISA controller named by ACPI HID/UID. - - @retval EFI_SUCCESS Successfully initialized an ISA controller. - @retval Other The ISA controller could not be initialized. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_ACPI_INIT_DEVICE)( - IN EFI_ISA_ACPI_PROTOCOL *This, - IN EFI_ISA_ACPI_DEVICE_ID *Device - ); - -/** - Initializes all the HW states required for the ISA controllers on the ISA bus - to be enumerated and managed by the rest of the services in this prorotol. - This service must be called before any of the other services in this - protocol will function as expected. - - @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. - - @retval EFI_SUCCESS Successfully initialized all required hardware states. - @retval Other The ISA interface could not be initialized. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_ACPI_INTERFACE_INIT)( - IN EFI_ISA_ACPI_PROTOCOL *This - ); - -/// -/// The EFI_ISA_ACPI_PROTOCOL provides the services to enumerate and manage -/// ISA controllers on an ISA bus. These services include the ability to initialize, -/// enable, disable, and manage the power state of ISA controllers. It also -/// includes services to query current resources, query possible resources, -/// and assign resources to an ISA controller. -/// -struct _EFI_ISA_ACPI_PROTOCOL { - EFI_ISA_ACPI_DEVICE_ENUMERATE DeviceEnumerate; - EFI_ISA_ACPI_SET_DEVICE_POWER SetPower; - EFI_ISA_ACPI_GET_CUR_RESOURCE GetCurResource; - EFI_ISA_ACPI_GET_POS_RESOURCE GetPosResource; - EFI_ISA_ACPI_SET_RESOURCE SetResource; - EFI_ISA_ACPI_ENABLE_DEVICE EnableDevice; - EFI_ISA_ACPI_INIT_DEVICE InitDevice; - EFI_ISA_ACPI_INTERFACE_INIT InterfaceInit; -}; - -extern EFI_GUID gEfiIsaAcpiProtocolGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Protocol/IsaIo.h b/IntelFrameworkModulePkg/Include/Protocol/IsaIo.h deleted file mode 100644 index cf6632e737..0000000000 --- a/IntelFrameworkModulePkg/Include/Protocol/IsaIo.h +++ /dev/null @@ -1,362 +0,0 @@ -/** @file - ISA I/O Protocol is used by ISA device drivers to perform I/O, MMIO and DMA - operations on the ISA controllers they manage. - -Copyright (c) 2006 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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_ISA_IO_H_ -#define _EFI_ISA_IO_H_ - -#include - -/// -/// Global ID for the EFI_ISA_IO_PROTOCOL -/// -#define EFI_ISA_IO_PROTOCOL_GUID \ - { \ - 0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ - } - -/// -/// Forward declaration for the EFI_ISA_IO_PROTOCOL. -/// -typedef struct _EFI_ISA_IO_PROTOCOL EFI_ISA_IO_PROTOCOL; - -/// -/// Width of EFI_ISA_IO_PROTOCOL I/O Port and MMIO operations. -/// -typedef enum { - EfiIsaIoWidthUint8 = 0, ///< 8-bit operation. - EfiIsaIoWidthUint16, ///< 16-bit operation. - EfiIsaIoWidthUint32, ///< 32-bit operation - EfiIsaIoWidthReserved, - EfiIsaIoWidthFifoUint8, ///< 8-bit FIFO operation. - EfiIsaIoWidthFifoUint16, ///< 16-bit FIFO operation. - EfiIsaIoWidthFifoUint32, ///< 32-bit FIFO operation. - EfiIsaIoWidthFifoReserved, - EfiIsaIoWidthFillUint8, ///< 8-bit Fill operation. - EfiIsaIoWidthFillUint16, ///< 16-bit Fill operation. - EfiIsaIoWidthFillUint32, ///< 32-bit Fill operation. - EfiIsaIoWidthFillReserved, - EfiIsaIoWidthMaximum -} EFI_ISA_IO_PROTOCOL_WIDTH; - -/// -/// Attributes for the EFI_ISA_IO_PROTOCOL common DMA buffer allocations. -/// -#define EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x080 ///< Map a memory range so write are combined. -#define EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED 0x800 ///< Map a memory range so all read and write accesses are cached. -#define EFI_ISA_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 ///< Disable a memory range. - -/// -/// Channel attribute for EFI_ISA_IO_PROTOCOL slave DMA requests -/// -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE 0x001 ///< Set the speed of the DMA transfer in compatible mode. -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A 0x002 ///< Not supported. -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B 0x004 ///< Not supported. -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C 0x008 ///< Not supported. -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8 0x010 ///< Request 8-bit DMA transfers. Only available on channels 0..3. -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16 0x020 ///< Request 16-bit DMA transfers. Only available on channels 4..7. -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE 0x040 ///< Request a single DMA transfer. -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE 0x080 ///< Request multiple DMA transfers until TC (Terminal Count) or EOP (End of Process). -#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE 0x100 ///< Automatically reload base and count at the end of the DMA transfer. - -/// -/// The DMA opreration type for EFI_ISA_IO_PROTOCOL DMA requests. -/// -typedef enum { - /// - /// A read operation from system memory by a bus master. - /// - EfiIsaIoOperationBusMasterRead, - /// - /// A write operation to system memory by a bus master. - /// - EfiIsaIoOperationBusMasterWrite, - /// - /// Provides both read and write access to system memory by both the processor - /// and a bus master. The buffer is coherent from both the processor's and the - /// bus master's point of view. - /// - EfiIsaIoOperationBusMasterCommonBuffer, - /// - /// A read operation from system memory by a slave device. - /// - EfiIsaIoOperationSlaveRead, - /// - /// A write operation to system memory by a slave master. - /// - EfiIsaIoOperationSlaveWrite, - EfiIsaIoOperationMaximum -} EFI_ISA_IO_PROTOCOL_OPERATION; - -/** - Performs ISA I/O and MMIO Read/Write Cycles - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the I/O or MMIO operation. - @param[in] Offset The offset into the ISA I/O or MMIO space to start the - operation. - @param[in] Count The number of I/O or MMIO operations to perform. - @param[in, out] Buffer For read operations, the destination buffer to store - the results. For write operations, the source buffer to - write data from. - - @retval EFI_SUCCESS The data was successfully read from or written to the device. - @retval EFI_UNSUPPORTED The Offset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_IO_PROTOCOL_IO_MEM)( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN OUT VOID *Buffer - ); - -/// -/// Structure of functions for accessing ISA I/O and MMIO space. -/// -typedef struct { - /// - /// Read from ISA I/O or MMIO space. - /// - EFI_ISA_IO_PROTOCOL_IO_MEM Read; - /// - /// Write to ISA I/O or MMIO space. - /// - EFI_ISA_IO_PROTOCOL_IO_MEM Write; -} EFI_ISA_IO_PROTOCOL_ACCESS; - -/** - Copies data from one region of ISA MMIO space to another region of ISA - MMIO space. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Width Specifies the width of the MMIO copy operation. - @param[in] DestOffset The offset of the destination in ISA MMIO space. - @param[in] SrcOffset The offset of the source in ISA MMIO space. - @param[in] Count The number tranfers to perform for this copy operation. - - @retval EFI_SUCCESS The data was copied sucessfully. - @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. - @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_IO_PROTOCOL_COPY_MEM)( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_WIDTH Width, - IN UINT32 DestOffset, - IN UINT32 SrcOffset, - IN UINTN Count - ); - -/** - Maps a memory region for DMA. - - This function returns the device-specific addresses required to access system memory. - This function is used to map system memory for ISA DMA operations. All ISA DMA - operations must be performed through their mapped addresses, and such mappings must - be freed with EFI_ISA_IO_PROTOCOL.Unmap() after the DMA operation is completed. - - If the DMA operation is a single read or write data transfer through an ISA bus - master, then EfiIsaIoOperationBusMasterRead or EfiIsaIoOperationBusMasterWrite - is used and the range is unmapped to complete the operation. If the DMA operation - is a single read or write data transfer through an ISA slave controller, then - EfiIsaIoOperationSlaveRead or EfiIsaIoOperationSlaveWrite is used and the range - is unmapped to complete the operation. - - If performing a DMA read operation, all the data must be present in system memory before the Map() is performed. Similarly, - if performing a DMA write operation, the data must not be accessed in system - memory until EFI_ISA_IO_PROTOCOL.Unmap() is performed. Bus master operations that - require both read and write access or require multiple host device interactions - within the same mapped region must use EfiIsaIoOperationBusMasterCommonBuffer. - However, only memory allocated via the EFI_ISA_IO_PROTOCOL.AllocateBuffer() interface - is guaranteed to be able to be mapped for this operation type. In all mapping - requests the NumberOfBytes returned may be less than originally requested. It is - the caller's responsibility to make additional requests to complete the entire - transfer. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Operation Indicates the type of DMA (slave or bus master), - and if the DMA operation is going to read or - write to system memory. - @param[in] ChannelNumber The slave channel number to use for this DMA - operation. If Operation and ChannelAttributes - shows that this device performs bus mastering - DMA, then this field is ignored. The legal - range for this field is 0..7. - @param[in] ChannelAttributes A bitmask of the attributes used to configure - the slave DMA channel for this DMA operation. - See EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_* for the - legal bit combinations. - @param[in] HostAddress The system memory address to map to the device. - @param[in, out] NumberOfBytes On input the number of bytes to map. On - output the number of bytes that were mapped. - @param[out] DeviceAddress The resulting map address for the bus master - device to use to access the hosts HostAddress. - @param[out] Mapping A returned value that must be passed to into - EFI_ISA_IO_PROTOCOL.Unmap() to free all the the - resources associated with this map request. - - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_INVALID_PARAMETER The Operation is undefined. - @retval EFI_INVALID_PARAMETER The HostAddress is undefined. - @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_IO_PROTOCOL_MAP)( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, - IN UINT8 ChannelNumber OPTIONAL, - IN UINT32 ChannelAttributes, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ); - -/** - Unmaps a memory region that was previously mapped with EFI_ISA_IO_PROTOCOL.Map(). - - The EFI_ISA_IO_PROTOCOL.Map() operation is completed and any corresponding - resources are released. If the operation was EfiIsaIoOperationSlaveWrite - or EfiIsaIoOperationBusMasterWrite, the data is committed to system memory. - Any resources used for the mapping are freed. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Mapping The mapping value returned from EFI_ISA_IO_PROTOCOL.Map(). - - @retval EFI_SUCCESS The memory region was unmapped. - @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_IO_PROTOCOL_UNMAP)( - IN EFI_ISA_IO_PROTOCOL *This, - IN VOID *Mapping - ); - -/** - Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer - mapping. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Type The type allocation to perform. - @param[in] MemoryType The type of memory to allocate. - @param[in] Pages The number of pages to allocate. - @param[out] HostAddress A pointer to store the base address of the allocated range. - @param[in] Attributes The requested bit mask of attributes for the allocated range. - - @retval EFI_SUCCESS The requested memory pages were allocated. - @retval EFI_INVALID_PARAMETER Type is invalid. - @retval EFI_INVALID_PARAMETER MemoryType is invalid. - @retval EFI_INVALID_PARAMETER HostAddress is NULL. - @retval EFI_UNSUPPORTED Attributes is unsupported. - @retval EFI_UNSUPPORTED The memory range specified by HostAddress, Pages, - and Type is not available for common buffer use. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER)( - IN EFI_ISA_IO_PROTOCOL *This, - IN EFI_ALLOCATE_TYPE Type, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Pages, - OUT VOID **HostAddress, - IN UINT64 Attributes - ); - -/** - Frees a common buffer that was allocated with EFI_ISA_IO_PROTOCOL.AllocateBuffer(). - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - @param[in] Pages The number of pages to free from the previously allocated common buffer. - @param[in] HostAddress The base address of the previously allocated common buffer. - - - @retval EFI_SUCCESS The requested memory pages were freed. - @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_IO_PROTOCOL_FREE_BUFFER)( - IN EFI_ISA_IO_PROTOCOL *This, - IN UINTN Pages, - IN VOID *HostAddress - ); - -/** - Flushes a DMA buffer, which forces all DMA posted write transactions to complete. - - @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. - - @retval EFI_SUCCESS The DMA buffers were flushed. - @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_ISA_IO_PROTOCOL_FLUSH)( - IN EFI_ISA_IO_PROTOCOL *This - ); - -/// -/// The EFI_ISA_IO_PROTOCOL provides the basic Memory, I/O, and DMA interfaces -/// used to abstract accesses to ISA controllers. There is one EFI_ISA_IO_PROTOCOL -/// instance for each ISA controller on a ISA bus. A device driver that wishes -/// to manage an ISA controller in a system will have to retrieve the -/// ISA_PCI_IO_PROTOCOL instance associated with the ISA controller. -/// -struct _EFI_ISA_IO_PROTOCOL { - EFI_ISA_IO_PROTOCOL_ACCESS Mem; - EFI_ISA_IO_PROTOCOL_ACCESS Io; - EFI_ISA_IO_PROTOCOL_COPY_MEM CopyMem; - EFI_ISA_IO_PROTOCOL_MAP Map; - EFI_ISA_IO_PROTOCOL_UNMAP Unmap; - EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; - EFI_ISA_IO_PROTOCOL_FREE_BUFFER FreeBuffer; - EFI_ISA_IO_PROTOCOL_FLUSH Flush; - /// - /// The list of I/O , MMIO, DMA, and Interrupt resources associated with the - /// ISA controller abstracted by this instance of the EFI_ISA_IO_PROTOCOL. - /// - EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; - /// - /// The size, in bytes, of the ROM image. - /// - UINT32 RomSize; - /// - /// A pointer to the in memory copy of the ROM image. The ISA Bus Driver is responsible - /// for allocating memory for the ROM image, and copying the contents of the ROM to memory - /// during ISA Bus initialization. - /// - VOID *RomImage; -}; - -extern EFI_GUID gEfiIsaIoProtocolGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Protocol/OEMBadging.h b/IntelFrameworkModulePkg/Include/Protocol/OEMBadging.h deleted file mode 100644 index c56b7e725b..0000000000 --- a/IntelFrameworkModulePkg/Include/Protocol/OEMBadging.h +++ /dev/null @@ -1,88 +0,0 @@ -/** @file - The OEM Badging Protocol defines the interface to get the OEM badging - image with the display attribute. This protocol can be produced based on OEM badging images. - -Copyright (c) 2006 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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_OEM_BADGING_H__ -#define __EFI_OEM_BADGING_H__ - -// -// GUID for EFI OEM Badging Protocol -// -#define EFI_OEM_BADGING_PROTOCOL_GUID \ - { 0x170e13c0, 0xbf1b, 0x4218, {0x87, 0x1d, 0x2a, 0xbd, 0xc6, 0xf8, 0x87, 0xbc } } - - -typedef struct _EFI_OEM_BADGING_PROTOCOL EFI_OEM_BADGING_PROTOCOL; - -typedef enum { - EfiBadgingFormatBMP, - EfiBadgingFormatJPEG, - EfiBadgingFormatTIFF, - EfiBadgingFormatGIF, - EfiBadgingFormatUnknown -} EFI_BADGING_FORMAT; - -typedef enum { - EfiBadgingDisplayAttributeLeftTop, - EfiBadgingDisplayAttributeCenterTop, - EfiBadgingDisplayAttributeRightTop, - EfiBadgingDisplayAttributeCenterRight, - EfiBadgingDisplayAttributeRightBottom, - EfiBadgingDisplayAttributeCenterBottom, - EfiBadgingDisplayAttributeLeftBottom, - EfiBadgingDisplayAttributeCenterLeft, - EfiBadgingDisplayAttributeCenter, - EfiBadgingDisplayAttributeCustomized -} EFI_BADGING_DISPLAY_ATTRIBUTE; - -/** - - Load an OEM badge image and return its data and attributes. - - @param This The pointer to this protocol instance. - @param Instance The visible image instance is found. - @param Format The format of the image. Examples: BMP, JPEG. - @param ImageData The image data for the badge file. Currently only - supports the .bmp file format. - @param ImageSize The size of the image returned. - @param Attribute The display attributes of the image returned. - @param CoordinateX The X coordinate of the image. - @param CoordinateY The Y coordinate of the image. - - @retval EFI_SUCCESS The image was fetched successfully. - @retval EFI_NOT_FOUND The specified image could not be found. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_BADGING_GET_IMAGE)( - IN EFI_OEM_BADGING_PROTOCOL *This, - IN OUT UINT32 *Instance, - OUT EFI_BADGING_FORMAT *Format, - OUT UINT8 **ImageData, - OUT UINTN *ImageSize, - OUT EFI_BADGING_DISPLAY_ATTRIBUTE *Attribute, - OUT UINTN *CoordinateX, - OUT UINTN *CoordinateY -); - - -struct _EFI_OEM_BADGING_PROTOCOL { - EFI_BADGING_GET_IMAGE GetImage; -}; - - -extern EFI_GUID gEfiOEMBadgingProtocolGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Protocol/Ps2Policy.h b/IntelFrameworkModulePkg/Include/Protocol/Ps2Policy.h deleted file mode 100644 index 8e915edaf5..0000000000 --- a/IntelFrameworkModulePkg/Include/Protocol/Ps2Policy.h +++ /dev/null @@ -1,41 +0,0 @@ -/** @file - PS/2 policy protocol abstracts the specific platform initialization and settings. - -Copyright (c) 2006 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 _PS2_POLICY_PROTOCOL_H_ -#define _PS2_POLICY_PROTOCOL_H_ - -#define EFI_PS2_POLICY_PROTOCOL_GUID \ - { \ - 0x4df19259, 0xdc71, 0x4d46, {0xbe, 0xf1, 0x35, 0x7b, 0xb5, 0x78, 0xc4, 0x18 } \ - } - -#define EFI_KEYBOARD_CAPSLOCK 0x0004 -#define EFI_KEYBOARD_NUMLOCK 0x0002 -#define EFI_KEYBOARD_SCROLLLOCK 0x0001 - -typedef -EFI_STATUS -(EFIAPI *EFI_PS2_INIT_HARDWARE) ( - IN EFI_HANDLE Handle - ); - -typedef struct { - UINT8 KeyboardLight; - EFI_PS2_INIT_HARDWARE Ps2InitHardware; -} EFI_PS2_POLICY_PROTOCOL; - -extern EFI_GUID gEfiPs2PolicyProtocolGuid; - -#endif diff --git a/IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h b/IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h deleted file mode 100644 index e912eed213..0000000000 --- a/IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h +++ /dev/null @@ -1,94 +0,0 @@ -/** @file - The VGA Mini Port Protocol used to set the text display mode of a VGA controller. - -Copyright (c) 2006 - 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 that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -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 __VGA_MINI_PORT_H_ -#define __VGA_MINI_PORT_H_ - -/// -/// Global ID for the EFI_VGA_MINI_PORT_PROTOCOL. -/// -#define EFI_VGA_MINI_PORT_PROTOCOL_GUID \ - { \ - 0xc7735a2f, 0x88f5, 0x4882, {0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3 } \ - } - -/// -/// Forward declaration for the EFI_VGA_MINI_PORT_PROTOCOL. -/// -typedef struct _EFI_VGA_MINI_PORT_PROTOCOL EFI_VGA_MINI_PORT_PROTOCOL; - -/** - Sets the text display mode of a VGA controller. - - Sets the text display mode of the VGA controller to the mode specified by - ModeNumber. A ModeNumber of 0 is a request for an 80x25 text mode. A - ModeNumber of 1 is a request for an 80x50 text mode. If ModeNumber is greater - than MaxModeNumber, then EFI_UNSUPPORTED is returned. If the VGA controller - is not functioning properly, then EFI_DEVICE_ERROR is returned. If the VGA - controller is sucessfully set to the mode number specified by ModeNumber, then - EFI_SUCCESS is returned. - - @param[in] This A pointer to the EFI_VGA_MINI_PORT_PROTOCOL instance. - @param[in] ModeNumber The requested mode number. 0 for 80x25. 1 for 80x5. - - @retval EFI_SUCCESS The mode number was set. - @retval EFI_UNSUPPORTED The mode number specified by ModeNumber is not supported. - @retval EFI_DEVICE_ERROR The device is not functioning properly. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_VGA_MINI_PORT_SET_MODE)( - IN EFI_VGA_MINI_PORT_PROTOCOL *This, - IN UINTN ModeNumber - ); - -struct _EFI_VGA_MINI_PORT_PROTOCOL { - EFI_VGA_MINI_PORT_SET_MODE SetMode; - /// - /// MMIO base address of the VGA text mode framebuffer. Typically set to 0xB8000. - /// - UINT64 VgaMemoryOffset; - /// - /// I/O Port address for the VGA CRTC address register. Typically set to 0x3D4. - /// - UINT64 CrtcAddressRegisterOffset; - /// - /// I/O Port address for the VGA CRTC data register. Typically set to 0x3D5. - /// - UINT64 CrtcDataRegisterOffset; - /// - /// PCI Controller MMIO BAR index of the VGA text mode frame buffer. Typically - /// set to EFI_PCI_IO_PASS_THROUGH_BAR - /// - UINT8 VgaMemoryBar; - /// - /// PCI Controller I/O BAR index of the VGA CRTC address register. Typically - /// set to EFI_PCI_IO_PASS_THROUGH_BAR - /// - UINT8 CrtcAddressRegisterBar; - /// - /// PCI Controller I/O BAR index of the VGA CRTC data register. Typically set - /// to EFI_PCI_IO_PASS_THROUGH_BAR - /// - UINT8 CrtcDataRegisterBar; - /// - /// The maximum number of text modes that this VGA controller supports. - /// - UINT8 MaxMode; -}; - -extern EFI_GUID gEfiVgaMiniPortProtocolGuid; - -#endif diff --git a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec deleted file mode 100644 index 8bbde8e2c9..0000000000 --- a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec +++ /dev/null @@ -1,283 +0,0 @@ -## @file -# Intel Framework Module Package. -# -# This package contains the definitions and module implementation -# which follows Intel EFI Framework Specification. -# -# Copyright (c) 2007 - 2015, Intel 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] - DEC_SPECIFICATION = 0x00010005 - PACKAGE_NAME = IntelFrameworkModulePkg - PACKAGE_UNI_FILE = IntelFrameworkModulePkg.uni - PACKAGE_GUID = 88894582-7553-4822-B484-624E24B6DECF - PACKAGE_VERSION = 0.96 - -[Includes] - Include # Root include for the package - -[LibraryClasses] - ## @libraryclass Platform BDS library definition about platform specific behavior. - PlatformBdsLib|Include/Library/PlatformBdsLib.h - - ## @libraryclass Generic BDS library definition, include the data structure and function. - GenericBdsLib|Include/Library/GenericBdsLib.h - -[Guids] - ## IntelFrameworkModule package token space guid - # Include/Guid/IntelFrameworkModulePkgTokenSpace.h - gEfiIntelFrameworkModulePkgTokenSpaceGuid = { 0xD3705011, 0xBC19, 0x4af7, { 0xBE, 0x16, 0xF6, 0x80, 0x30, 0x37, 0x8C, 0x15 }} - - ## GUID identifies Data Hub records logged by Status Code Runtime Protocol. - # Include/Guid/DataHubStatusCodeRecord.h - gEfiDataHubStatusCodeRecordGuid = { 0xD083E94C, 0x6560, 0x42E4, { 0xB6, 0xD4, 0x2D, 0xF7, 0x5A, 0xDF, 0x6A, 0x2A }} - - ## GUID indicates the tiano custom compress/decompress algorithm. - # Include/Guid/TianoDecompress.h - gTianoCustomDecompressGuid = { 0xA31280AD, 0x481E, 0x41B6, { 0x95, 0xE8, 0x12, 0x7F, 0x4C, 0x98, 0x47, 0x79 }} - - ## Include/Guid/AcpiVariable.h - gEfiAcpiVariableCompatiblityGuid = { 0xc020489e, 0x6db2, 0x4ef2, { 0x9a, 0xa5, 0xca, 0x6, 0xfc, 0x11, 0xd3, 0x6a }} - - ## Include/Guid/LegacyBios.h - gEfiLegacyBiosGuid = { 0x2E3044AC, 0x879F, 0x490F, { 0x97, 0x60, 0xBB, 0xDF, 0xAF, 0x69, 0x5F, 0x50 }} - - ## Include/Guid/LegacyDevOrder.h - gEfiLegacyDevOrderVariableGuid = { 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52 }} - - ## Include/Guid/CapsuleDataFile.h - gEfiUpdateDataFileGuid = { 0x283fa2ee, 0x532c, 0x484d, { 0x93, 0x83, 0x9f, 0x93, 0xb3, 0x6f, 0xb, 0x7e }} - - ## Include/Guid/BlockIoVendor.h - gBlockIoVendorGuid = { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b }} - - ## Include/Guid/BdsHii.h - gFrontPageFormSetGuid = { 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }} - gBootManagerFormSetGuid = { 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }} - gDeviceManagerFormSetGuid = { 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 }} - gDriverHealthFormSetGuid = { 0xf76e0a70, 0xb5ed, 0x4c38, {0xac, 0x9a, 0xe5, 0xf5, 0x4b, 0xf1, 0x6e, 0x34 }} - gBootMaintFormSetGuid = { 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22 }} - gFileExploreFormSetGuid = { 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b }} - - ## Include/Guid/BdsLibHii.h - gBdsLibStringPackageGuid = { 0x3b4d9b23, 0x95ac, 0x44f6, {0x9f, 0xcd, 0xe, 0x95, 0x94, 0x58, 0x6c, 0x72 }} - - ## Include/Guid/LastEnumLang.h - gLastEnumLangGuid = { 0xe8c545b, 0xa2ee, 0x470d, {0x8e, 0x26, 0xbd, 0xa1, 0xa1, 0x3c, 0xa, 0xa3 }} - - ## Include/Guid/HdBootVariable.h - gHdBootDevicePathVariablGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, {0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde }} - -[Protocols] - ## Vga Mini port binding for a VGA controller - # Include/Protocol/VgaMiniPort.h - gEfiVgaMiniPortProtocolGuid = { 0xc7735a2f, 0x88f5, 0x4882, { 0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3 }} - - ## ISA I/O Protocol is used to perform ISA device Io/Mem operations. - # Include/Protocol/IsaIo.h - gEfiIsaIoProtocolGuid = { 0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }} - - ## ISA Acpi Protocol is used to operate and communicate with ISA device. - # Include/Protocol/IsaAcpi.h - gEfiIsaAcpiProtocolGuid = { 0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55 }} - - ## PS/2 policy protocol abstracts the specific platform initialization and setting. - # Include/Protocol/Ps2Policy.h - gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE, 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 }} - - ## OEM Badging Protocol defines the interface to get the OEM badging image with the dispaly attribute. - # Include/Protocol/OEMBadging.h - gEfiOEMBadgingProtocolGuid = { 0x170E13C0, 0xBF1B, 0x4218, { 0x87, 0x1D, 0x2A, 0xBD, 0xC6, 0xF8, 0x87, 0xBC }} - - ## Include/Protocol/ExitPmAuth.h - gExitPmAuthProtocolGuid = { 0xd088a413, 0xa70, 0x4217, { 0xba, 0x55, 0x9a, 0x3c, 0xb6, 0x5c, 0x41, 0xb3 }} - -# -# [Error.gEfiIntelFrameworkModulePkgTokenSpaceGuid] -# 0x80000001 | Invalid value provided. -# 0x80000002 | Reserved bits must be set to zero. -# - -[PcdsFeatureFlag] - ## Indicates if OEM device is enabled as StatusCode report device. - # It is only used in Framework StatusCode implementation.

- # TRUE - Enable OEM device.
- # FALSE - Disable OEM device.
- # @Prompt Report StatusCode via OEM Device - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseOEM|FALSE|BOOLEAN|0x00010024 - - ## Indicates if StatusCode report is loged into DataHub.

- # TRUE - Log StatusCode report into DataHub.
- # FALSE - Does not log StatusCode report into DataHub.
- # @Prompt Log StatusCode into DataHub - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub|FALSE|BOOLEAN|0x00010029 - - ## Indicates if Serial device uses half hand shake.

- # TRUE - Serial device uses half hand shake.
- # FALSE - Serial device doesn't use half hand shake.
- # @Prompt Enable Serial device Half Hand Shake - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE|BOOLEAN|0x00010043 - - ## Indicates if Legacy support is needed for ACPI S3 Save.

- # TRUE - Support Legacy OS with S3 boot.
- # FALSE - Does not support Legacy OS with S3 boot.
- # @Prompt Turn on Legacy Support in S3 Boot - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformCsmSupport|TRUE|BOOLEAN|0x00010044 - - ## Indicates if PS2 keyboard does a extended verification during start. - # Extended verification will take some performance. It can be set to FALSE for boot performance.

- # TRUE - Turn on PS2 keyboard extended verification.
- # FALSE - Turn off PS2 keyboard extended verification.
- # @Prompt Turn on PS2 Keyboard Extended Verification - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|TRUE|BOOLEAN|0x00010045 - - ## Indicates if Framework Acpi Support protocol is installed.

- # TRUE - Install Framework Acpi Support protocol.
- # FALSE - Doesn't install Framework Acpi Support protocol.
- # @Prompt Enable Framework Acpi Support - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdInstallAcpiSupportProtocol|TRUE|BOOLEAN|0x00010046 - - - ## Indicates if PS2 mouse does a extended verification during start. - # Extended verification will take some performance. It can be set to FALSE for boot performance.

- # TRUE - Turn on PS2 mouse extended verification.
- # FALSE - Turn off PS2 mouse extended verification.
- # @Prompt Turn on PS2 Mouse Extended Verification - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification|TRUE|BOOLEAN|0x00010047 - - ## Indicates if only Boot logo is showed and all message output is disabled in BDS.

- # TRUE - Only Boot Logo is showed in boot.
- # FALSE - All messages and Boot Logo are showed in boot.
- # @Prompt Enable Boot Logo only - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootlogoOnlyEnable|FALSE|BOOLEAN|0x00010048 - -[PcdsFixedAtBuild, PcdsPatchableInModule] - ## FFS filename to find the default BMP Logo file. - # @Prompt FFS Name of Boot Logo File - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile |{ 0x99, 0x8b, 0xB2, 0x7B, 0xBB, 0x61, 0xD5, 0x11, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }|VOID*|0x40000003 - - ## FFS filename to find the shell application. - # @Prompt FFS Name of Shell Application - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0xB7, 0xD6, 0x7A, 0xC5, 0x15, 0x05, 0xA8, 0x40, 0x9D, 0x21, 0x55, 0x16, 0x52, 0x85, 0x4E, 0x37 }|VOID*|0x40000004 - - ## ISA Bus features to support DMA, SlaveDMA and ISA Memory.

- # BIT0 indicates if DMA is supported
- # BIT1 indicates if only slave DMA is supported
- # BIT2 indicates if ISA memory is supported
- # Other BITs are reseved and must be zero. - # If more than one features are supported, the different BIT will be enabled at the same time. - # @Prompt ISA Bus Features - # @Expression 0x80000002 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures & 0xF8) == 0 - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures|0x05|UINT8|0x00010040 - -[PcdsDynamic, PcdsDynamicEx] - ## Indicates if the machine has completed one boot cycle before. - # After the complete boot, BootState will be set to FALSE.

- # TRUE - The complete boot cycle has not happened before.
- # FALSE - The complete boot cycle has happened before.
- # @Prompt Boot State Flag - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|TRUE|BOOLEAN|0x0001002f - -[PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule] - ## I/O Base address of floppy device controller. - # @Prompt I/O Base Address of Floppy Device Controller - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFdcBaseAddress|0x3f0|UINT16|0x30000000 - - ## Indicates if BiosVideo driver will switch to 80x25 Text VGA Mode when exiting boot service.

- # TRUE - Switch to Text VGA Mode.
- # FALSE - Does not switch to Text VGA Mode.
- # @Prompt Switch to Text VGA Mode on UEFI Boot - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable|FALSE|BOOLEAN|0x30000001 - - ## Indicates if BiosVideo driver will check for VESA BIOS Extension service support.

- # TRUE - Check for VESA BIOS Extension service.
- # FALSE - Does not check for VESA BIOS Extension service.
- # @Prompt Enable Check for VESA BIOS Extension Service - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable|TRUE|BOOLEAN|0x30000002 - - ## Indicates if BiosVideo driver will check for VGA service support. - # NOTE: If both PcdBiosVideoCheckVbeEnable and PcdBiosVideoCheckVgaEnable are set to FALSE, - # that means Graphics Output protocol will not be installed, the VGA miniport protocol will be installed instead.

- # TRUE - Check for VGA service.
- # FALSE - Does not check for VGA service.
- # @Prompt Enable Check for VGA Service - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable|TRUE|BOOLEAN|0x30000003 - - ## Indicates if memory space for legacy region will be set as cacheable.

- # TRUE - Set cachebility for legacy region.
- # FALSE - Does not set cachebility for legacy region.
- # @Prompt Enable Cachebility for Legacy Region - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion|TRUE|BOOLEAN|0x00000004 - - ## Specify memory size with bytes to reserve EBDA below 640K for OPROM. - # The value should be a multiple of 4KB. - # @Prompt Reserved EBDA Memory Size - # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize < 0xA0000) AND ((gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize & 0x1000) == 0) - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize|0x8000|UINT32|0x30000005 - - ## Specify memory base address for OPROM to find free memory. - # Some OPROMs do not use EBDA or PMM to allocate memory for its usage, - # instead they find the memory filled with zero from 0x20000. - # The value should be a multiple of 4KB. - # The range should be below the EBDA reserved range from - # (CONVENTIONAL_MEMORY_TOP - Reserved EBDA Memory Size) to CONVENTIONAL_MEMORY_TOP. - # @Prompt Reserved Memory Base Address for OPROM - # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase >= 0x20000) AND ((gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase & 0x1000) == 0) - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase|0x60000|UINT32|0x3000000c - - ## Specify memory size with bytes for OPROM to find free memory. - # The value should be a multiple of 4KB. And the range should be below the EBDA reserved range from - # (CONVENTIONAL_MEMORY_TOP - Reserved EBDA Memory Size) to CONVENTIONAL_MEMORY_TOP. - # @Prompt Reserved Memory Size for OPROM - # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize < 0x80000) AND ((gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize & 0x1000) == 0) - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize|0x28000|UINT32|0x3000000d - - ## Specify memory size with page number for a pre-allocated reserved memory to be used - # by PEI in S3 phase. The default size 32K. When changing the value make sure the memory size - # is large enough to meet PEI requirement in the S3 phase. - # @Prompt Reserved S3 Boot ACPI Memory Size - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize|0x8000|UINT32|0x30000006 - - ## Specify memory size for boot script executor stack usage in S3 phase. - # The default size 32K. When changing the value make sure the memory size is large enough - # to meet boot script executor requirement in the S3 phase. - # @Prompt Reserved S3 Boot Script Stack ACPI Memory Size - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3BootScriptStackSize|0x8000|UINT32|0x30000007 - - ## Specify the end of address below 1MB for the OPROM. - # The last shadowed OpROM should not exceed this address. - # @Prompt Top Address of Shadowed Legacy OpROM - # @Expression 0x80000001 | gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEndOpromShadowAddress < 0x100000 - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEndOpromShadowAddress|0xdffff|UINT32|0x30000008 - - ## Specify the low PMM (Post Memory Manager) size with bytes below 1MB. - # The value should be a multiple of 4KB. - # @Prompt Low PMM (Post Memory Manager) Size - # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize < 0x100000) AND ((gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize & 0x1000) == 0) - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize|0x10000|UINT32|0x30000009 - - ## Specify the high PMM (Post Memory Manager) size with bytes above 1MB. - # The value should be a multiple of 4KB. - # @Prompt High PMM (Post Memory Manager) Size - # @Expression 0x80000001 | (gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize & 0x1000) == 0 - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize|0x400000|UINT32|0x3000000a - - ## Indicates if 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.

- # TRUE - Use the optimized timing for best PS2 detection performance.
- # FALSE - Use the normal timing to detect PS2.
- # @Prompt Enable fast PS2 detection - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection|FALSE|BOOLEAN|0x3000000b - -[UserExtensions.TianoCore."ExtraFiles"] - IntelFrameworkModulePkgExtra.uni diff --git a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc deleted file mode 100644 index b4adab11ef..0000000000 --- a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc +++ /dev/null @@ -1,198 +0,0 @@ -## @file -# Intel Framework Reference Module Package for All Architectures -# -# This file is used to build all modules in IntelFrameworkModulePkg. -# -#Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
-#This program and the accompanying materials are licensed and made available under -#the terms and conditions of the BSD License that accompanies this distribution. -#The full text of the license may be found at -#http://opensource.org/licenses/bsd-license.php. -# -# 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 = IntelFrameworkModuleAll - PLATFORM_GUID = FFF87D9A-E5BB-4AFF-9ADE-8645492E8087 - PLATFORM_VERSION = 0.96 - DSC_SPECIFICATION = 0x00010005 - OUTPUT_DIRECTORY = Build/IntelFrameworkModuleAll - SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC|ARM - BUILD_TARGETS = DEBUG|RELEASE - SKUID_IDENTIFIER = DEFAULT - -################################################################################ -# -# SKU Identification section - list of all SKU IDs supported by this -# Platform. -# -################################################################################ -[SkuIds] - 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required. - -[LibraryClasses] - CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf - DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf - DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf - DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf - BaseLib|MdePkg/Library/BaseLib/BaseLib.inf - SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf - BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf - IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf - PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf - PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf - TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf - OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf - SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf - UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf - HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf - PlatformBdsLib|IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf - CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf - PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf - PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf - PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf - DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf - ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf - PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf - PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf - PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf - UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf - UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf - UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf - PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf - PalLib|MdePkg/Library/BasePalLibNull/BasePalLibNull.inf - -[LibraryClasses.common.PEIM] - HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf - PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf - MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf - -[LibraryClasses.EBC.PEIM] - IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf - -[LibraryClasses.common.DXE_DRIVER] - LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf - -[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER] - HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - -[LibraryClasses.common.DXE_RUNTIME_DRIVER] - DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf - -################################################################################ -# -# Pcd Section - list of all EDK II PCD Entries defined by this Platform -# -################################################################################ -[PcdsFeatureFlag] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE - -[PcdsFixedAtBuild] - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f - gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06 - gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000 - -[PcdsFixedAtBuild.IPF] - gEfiMdePkgTokenSpaceGuid.PcdIoBlockBaseAddressForIpf|0x0ffffc000000 - -################################################################################################### -# -# Components Section - list of the modules and components that will be processed by compilation -# tools and the EDK II tools to generate PE32/PE32+/Coff image files. -# -# Note: The EDK II DSC file is not used to specify how compiled binary images get placed -# into firmware volume images. This section is just a list of modules to compile from -# source into UEFI-compliant binaries. -# It is the FDF file that contains information on combining binary files into firmware -# volume images, whose concept is beyond UEFI and is described in PI specification. -# Binary modules do not need to be listed in this section, as they should be -# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi), -# Logo (Logo.bmp), and etc. -# There may also be modules listed in this section that are not required in the FDF file, -# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be -# generated for it, but the binary will not be put into any firmware volume. -# -################################################################################################### - -[Components] - IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf - IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf - IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf - IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf - IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf - IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf - IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf - IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf - IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf - IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf - IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf - IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf - - IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf - IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf - IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf - IntelFrameworkModulePkg/Bus/Isa/IsaFloppyPei/IsaFloppyPei.inf - IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf - IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf - IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf - - IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf - IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf - IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf - IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf - - IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf - IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf - IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf - IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf - IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf - IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf - IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf - IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf - IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf - IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf - IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf - -[Components.IA32,Components.X64] - IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf - IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf - -[Components.IA32,Components.X64,Components.IPF] - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf - -[Components.IA32] - IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf - IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf { - - IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf - } - -[Components.X64] - IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf - IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf { - - IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf - } - -[Components.IPF] - IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf { - - IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf - } diff --git a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.uni b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.uni deleted file mode 100644 index 50106e10d5..0000000000 Binary files a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/IntelFrameworkModulePkgExtra.uni b/IntelFrameworkModulePkg/IntelFrameworkModulePkgExtra.uni deleted file mode 100644 index 15fdff98ad..0000000000 Binary files a/IntelFrameworkModulePkg/IntelFrameworkModulePkgExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c b/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c deleted file mode 100644 index 2e527234e2..0000000000 --- a/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c +++ /dev/null @@ -1,1050 +0,0 @@ -/** @file - UEFI and Tiano Custom Decompress Library - It will do Tiano or UEFI decompress with different verison parameter. - -Copyright (c) 2006 - 2015, Intel 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 "BaseUefiTianoCustomDecompressLibInternals.h" - -/** - Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. - - @param Sd The global scratch data - @param NumOfBits The number of bits to shift and read. -**/ -VOID -FillBuf ( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfBits - ) -{ - // - // Left shift NumOfBits of bits in advance - // - Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); - - // - // Copy data needed in bytes into mSbuBitBuf - // - while (NumOfBits > Sd->mBitCount) { - - Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); - - if (Sd->mCompSize > 0) { - // - // Get 1 byte into SubBitBuf - // - Sd->mCompSize--; - Sd->mSubBitBuf = 0; - Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; - Sd->mBitCount = 8; - - } else { - // - // No more bits from the source, just pad zero bit. - // - Sd->mSubBitBuf = 0; - Sd->mBitCount = 8; - - } - } - - // - // Calculate additional bit count read to update mBitCount - // - Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); - - // - // Copy NumOfBits of bits from mSubBitBuf into mBitBuf - // - Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; -} - -/** - Get NumOfBits of bits out from mBitBuf - - Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent - NumOfBits of bits from source. Returns NumOfBits of bits that are - popped out. - - @param Sd The global scratch data. - @param NumOfBits The number of bits to pop and read. - - @return The bits that are popped out. - -**/ -UINT32 -GetBits ( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfBits - ) -{ - UINT32 OutBits; - - // - // Pop NumOfBits of Bits from Left - // - OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); - - // - // Fill up mBitBuf from source - // - FillBuf (Sd, NumOfBits); - - return OutBits; -} - -/** - Creates Huffman Code mapping table according to code length array. - - Creates Huffman Code mapping table for Extra Set, Char&Len Set - and Position Set according to code length array. - If TableBits > 16, then ASSERT (). - - @param Sd The global scratch data - @param NumOfChar Number of symbols in the symbol set - @param BitLen Code length array - @param TableBits The width of the mapping table - @param Table The table to be created. - - @retval 0 OK. - @retval BAD_TABLE The table is corrupted. - -**/ -UINT16 -MakeTable ( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfChar, - IN UINT8 *BitLen, - IN UINT16 TableBits, - OUT UINT16 *Table - ) -{ - UINT16 Count[17]; - UINT16 Weight[17]; - UINT16 Start[18]; - UINT16 *Pointer; - UINT16 Index3; - UINT16 Index; - UINT16 Len; - UINT16 Char; - UINT16 JuBits; - UINT16 Avail; - UINT16 NextCode; - UINT16 Mask; - UINT16 WordOfStart; - UINT16 WordOfCount; - - // - // The maximum mapping table width supported by this internal - // working function is 16. - // - ASSERT (TableBits <= 16); - - for (Index = 0; Index <= 16; Index++) { - Count[Index] = 0; - } - - for (Index = 0; Index < NumOfChar; Index++) { - Count[BitLen[Index]]++; - } - - Start[0] = 0; - Start[1] = 0; - - for (Index = 1; Index <= 16; Index++) { - WordOfStart = Start[Index]; - WordOfCount = Count[Index]; - Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index))); - } - - if (Start[17] != 0) { - /*(1U << 16)*/ - return (UINT16) BAD_TABLE; - } - - JuBits = (UINT16) (16 - TableBits); - - Weight[0] = 0; - for (Index = 1; Index <= TableBits; Index++) { - Start[Index] >>= JuBits; - Weight[Index] = (UINT16) (1U << (TableBits - Index)); - } - - while (Index <= 16) { - Weight[Index] = (UINT16) (1U << (16 - Index)); - Index++; - } - - Index = (UINT16) (Start[TableBits + 1] >> JuBits); - - if (Index != 0) { - Index3 = (UINT16) (1U << TableBits); - if (Index < Index3) { - SetMem16 (Table + Index, (Index3 - Index) * sizeof (*Table), 0); - } - } - - Avail = NumOfChar; - Mask = (UINT16) (1U << (15 - TableBits)); - - for (Char = 0; Char < NumOfChar; Char++) { - - Len = BitLen[Char]; - if (Len == 0 || Len >= 17) { - continue; - } - - NextCode = (UINT16) (Start[Len] + Weight[Len]); - - if (Len <= TableBits) { - - for (Index = Start[Len]; Index < NextCode; Index++) { - Table[Index] = Char; - } - - } else { - - Index3 = Start[Len]; - Pointer = &Table[Index3 >> JuBits]; - Index = (UINT16) (Len - TableBits); - - while (Index != 0) { - if (*Pointer == 0 && Avail < (2 * NC - 1)) { - Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; - *Pointer = Avail++; - } - - if (*Pointer < (2 * NC - 1)) { - if ((Index3 & Mask) != 0) { - Pointer = &Sd->mRight[*Pointer]; - } else { - Pointer = &Sd->mLeft[*Pointer]; - } - } - - Index3 <<= 1; - Index--; - } - - *Pointer = Char; - - } - - Start[Len] = NextCode; - } - // - // Succeeds - // - return 0; -} - -/** - Decodes a position value. - - Get a position value according to Position Huffman Table. - - @param Sd the global scratch data - - @return The position value decoded. -**/ -UINT32 -DecodeP ( - IN SCRATCH_DATA *Sd - ) -{ - UINT16 Val; - UINT32 Mask; - UINT32 Pos; - - Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; - - if (Val >= MAXNP) { - Mask = 1U << (BITBUFSIZ - 1 - 8); - - do { - - if ((Sd->mBitBuf & Mask) != 0) { - Val = Sd->mRight[Val]; - } else { - Val = Sd->mLeft[Val]; - } - - Mask >>= 1; - } while (Val >= MAXNP); - } - // - // Advance what we have read - // - FillBuf (Sd, Sd->mPTLen[Val]); - - Pos = Val; - if (Val > 1) { - Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); - } - - return Pos; -} - -/** - Reads code lengths for the Extra Set or the Position Set. - - Read in the Extra Set or Pointion Set Length Arrary, then - generate the Huffman code mapping for them. - - @param Sd The global scratch data. - @param nn Number of symbols. - @param nbit Number of bits needed to represent nn. - @param Special The special symbol that needs to be taken care of. - - @retval 0 OK. - @retval BAD_TABLE Table is corrupted. - -**/ -UINT16 -ReadPTLen ( - IN SCRATCH_DATA *Sd, - IN UINT16 nn, - IN UINT16 nbit, - IN UINT16 Special - ) -{ - UINT16 Number; - UINT16 CharC; - UINT16 Index; - UINT32 Mask; - - ASSERT (nn <= NPT); - // - // Read Extra Set Code Length Array size - // - Number = (UINT16) GetBits (Sd, nbit); - - if (Number == 0) { - // - // This represents only Huffman code used - // - CharC = (UINT16) GetBits (Sd, nbit); - - for (Index = 0; Index < 256; Index++) { - Sd->mPTTable[Index] = CharC; - } - - SetMem (Sd->mPTLen, nn, 0); - - return 0; - } - - Index = 0; - - while (Index < Number && Index < NPT) { - - CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); - - // - // If a code length is less than 7, then it is encoded as a 3-bit - // value. Or it is encoded as a series of "1"s followed by a - // terminating "0". The number of "1"s = Code length - 4. - // - if (CharC == 7) { - Mask = 1U << (BITBUFSIZ - 1 - 3); - while (Mask & Sd->mBitBuf) { - Mask >>= 1; - CharC += 1; - } - } - - FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); - - Sd->mPTLen[Index++] = (UINT8) CharC; - - // - // For Code&Len Set, - // After the third length of the code length concatenation, - // a 2-bit value is used to indicated the number of consecutive - // zero lengths after the third length. - // - if (Index == Special) { - CharC = (UINT16) GetBits (Sd, 2); - while ((INT16) (--CharC) >= 0 && Index < NPT) { - Sd->mPTLen[Index++] = 0; - } - } - } - - while (Index < nn && Index < NPT) { - Sd->mPTLen[Index++] = 0; - } - - return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); -} - -/** - Reads code lengths for Char&Len Set. - - Read in and decode the Char&Len Set Code Length Array, then - generate the Huffman Code mapping table for the Char&Len Set. - - @param Sd the global scratch data - -**/ -VOID -ReadCLen ( - SCRATCH_DATA *Sd - ) -{ - UINT16 Number; - UINT16 CharC; - UINT16 Index; - UINT32 Mask; - - Number = (UINT16) GetBits (Sd, CBIT); - - if (Number == 0) { - // - // This represents only Huffman code used - // - CharC = (UINT16) GetBits (Sd, CBIT); - - SetMem (Sd->mCLen, NC, 0); - - for (Index = 0; Index < 4096; Index++) { - Sd->mCTable[Index] = CharC; - } - - return ; - } - - Index = 0; - while (Index < Number && Index < NC) { - CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; - if (CharC >= NT) { - Mask = 1U << (BITBUFSIZ - 1 - 8); - - do { - - if (Mask & Sd->mBitBuf) { - CharC = Sd->mRight[CharC]; - } else { - CharC = Sd->mLeft[CharC]; - } - - Mask >>= 1; - - } while (CharC >= NT); - } - // - // Advance what we have read - // - FillBuf (Sd, Sd->mPTLen[CharC]); - - if (CharC <= 2) { - - if (CharC == 0) { - CharC = 1; - } else if (CharC == 1) { - CharC = (UINT16) (GetBits (Sd, 4) + 3); - } else if (CharC == 2) { - CharC = (UINT16) (GetBits (Sd, CBIT) + 20); - } - - while ((INT16) (--CharC) >= 0 && Index < NC) { - Sd->mCLen[Index++] = 0; - } - - } else { - - Sd->mCLen[Index++] = (UINT8) (CharC - 2); - - } - } - - SetMem (Sd->mCLen + Index, NC - Index, 0); - - MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); - - return ; -} - -/** - Decode a character/length value. - - Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates - Huffman code mapping table for Extra Set, Code&Len Set and - Position Set. - - @param Sd The global scratch data. - - @return The value decoded. - -**/ -UINT16 -DecodeC ( - SCRATCH_DATA *Sd - ) -{ - UINT16 Index2; - UINT32 Mask; - - if (Sd->mBlockSize == 0) { - // - // Starting a new block - // Read BlockSize from block header - // - Sd->mBlockSize = (UINT16) GetBits (Sd, 16); - - // - // Read in the Extra Set Code Length Arrary, - // Generate the Huffman code mapping table for Extra Set. - // - Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); - if (Sd->mBadTableFlag != 0) { - return 0; - } - - // - // Read in and decode the Char&Len Set Code Length Arrary, - // Generate the Huffman code mapping table for Char&Len Set. - // - ReadCLen (Sd); - - // - // Read in the Position Set Code Length Arrary, - // Generate the Huffman code mapping table for the Position Set. - // - Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); - if (Sd->mBadTableFlag != 0) { - return 0; - } - } - - // - // Get one code according to Code&Set Huffman Table - // - Sd->mBlockSize--; - Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; - - if (Index2 >= NC) { - Mask = 1U << (BITBUFSIZ - 1 - 12); - - do { - if ((Sd->mBitBuf & Mask) != 0) { - Index2 = Sd->mRight[Index2]; - } else { - Index2 = Sd->mLeft[Index2]; - } - - Mask >>= 1; - } while (Index2 >= NC); - } - // - // Advance what we have read - // - FillBuf (Sd, Sd->mCLen[Index2]); - - return Index2; -} - -/** - Decode the source data and put the resulting data into the destination buffer. - - @param Sd The global scratch data -**/ -VOID -Decode ( - SCRATCH_DATA *Sd - ) -{ - UINT16 BytesRemain; - UINT32 DataIdx; - UINT16 CharC; - - BytesRemain = (UINT16) (-1); - - DataIdx = 0; - - for (;;) { - // - // Get one code from mBitBuf - // - CharC = DecodeC (Sd); - if (Sd->mBadTableFlag != 0) { - goto Done; - } - - if (CharC < 256) { - // - // Process an Original character - // - if (Sd->mOutBuf >= Sd->mOrigSize) { - goto Done; - } else { - // - // Write orignal character into mDstBase - // - Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; - } - - } else { - // - // Process a Pointer - // - CharC = (UINT16) (CharC - (BIT8 - THRESHOLD)); - - // - // Get string length - // - BytesRemain = CharC; - - // - // Locate string position - // - DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; - - // - // Write BytesRemain of bytes into mDstBase - // - BytesRemain--; - while ((INT16) (BytesRemain) >= 0) { - Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; - if (Sd->mOutBuf >= Sd->mOrigSize) { - goto Done ; - } - - BytesRemain--; - } - } - } - -Done: - return ; -} - -/** - Given a compressed source buffer, this function retrieves the size of - the uncompressed buffer and the size of the scratch buffer required - to decompress the compressed source buffer. - - Retrieves the size of the uncompressed buffer and the temporary scratch buffer - required to decompress the buffer specified by Source and SourceSize. - If the size of the uncompressed buffer or the size of the scratch buffer cannot - be determined from the compressed data specified by Source and SourceData, - then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed - buffer is returned in DestinationSize, the size of the scratch buffer is returned - in ScratchSize, and RETURN_SUCCESS is returned. - This function does not have scratch buffer available to perform a thorough - checking of the validity of the source data. It just retrieves the "Original Size" - field from the beginning bytes of the source data and output it as DestinationSize. - And ScratchSize is specific to the decompression implementation. - - If Source is NULL, then ASSERT(). - If DestinationSize is NULL, then ASSERT(). - If ScratchSize is NULL, then ASSERT(). - - @param Source The source buffer containing the compressed data. - @param SourceSize The size, in bytes, of the source buffer. - @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer - that will be generated when the compressed buffer specified - by Source and SourceSize is decompressed.. - @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that - is required to decompress the compressed buffer specified - by Source and SourceSize. - - @retval RETURN_SUCCESS The size of the uncompressed data was returned - in DestinationSize and the size of the scratch - buffer was returned in ScratchSize. - @retval RETURN_INVALID_PARAMETER - The size of the uncompressed data or the size of - the scratch buffer cannot be determined from - the compressed data specified by Source - and SourceSize. -**/ -RETURN_STATUS -EFIAPI -UefiDecompressGetInfo ( - IN CONST VOID *Source, - IN UINT32 SourceSize, - OUT UINT32 *DestinationSize, - OUT UINT32 *ScratchSize - ) -{ - UINT32 CompressedSize; - - ASSERT (Source != NULL); - ASSERT (DestinationSize != NULL); - ASSERT (ScratchSize != NULL); - - if (SourceSize < 8) { - return RETURN_INVALID_PARAMETER; - } - - CompressedSize = ReadUnaligned32 ((UINT32 *)Source); - if (SourceSize < (CompressedSize + 8)) { - return RETURN_INVALID_PARAMETER; - } - - *ScratchSize = sizeof (SCRATCH_DATA); - *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1); - - return RETURN_SUCCESS; -} - -/** - Decompresses a compressed source buffer by EFI or Tiano algorithm. - - Extracts decompressed data to its original form. - This function is designed so that the decompression algorithm can be implemented - without using any memory services. As a result, this function is not allowed to - call any memory allocation services in its implementation. It is the caller's - responsibility to allocate and free the Destination and Scratch buffers. - If the compressed source data specified by Source is successfully decompressed - into Destination, then RETURN_SUCCESS is returned. If the compressed source data - specified by Source is not in a valid compressed data format, - then RETURN_INVALID_PARAMETER is returned. - - If Source is NULL, then ASSERT(). - If Destination is NULL, then ASSERT(). - If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT(). - - @param Source The source buffer containing the compressed data. - @param Destination The destination buffer to store the decompressed data - @param Scratch A temporary scratch buffer that is used to perform the decompression. - This is an optional parameter that may be NULL if the - required scratch buffer size is 0. - @param Version 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm. - - @retval RETURN_SUCCESS Decompression completed successfully, and - the uncompressed buffer is returned in Destination. - @retval RETURN_INVALID_PARAMETER - The source buffer specified by Source is corrupted - (not in a valid compressed format). -**/ -RETURN_STATUS -EFIAPI -UefiTianoDecompress ( - IN CONST VOID *Source, - IN OUT VOID *Destination, - IN OUT VOID *Scratch, - IN UINT32 Version - ) -{ - UINT32 CompSize; - UINT32 OrigSize; - SCRATCH_DATA *Sd; - CONST UINT8 *Src; - UINT8 *Dst; - - ASSERT (Source != NULL); - ASSERT (Destination != NULL); - ASSERT (Scratch != NULL); - - Src = Source; - Dst = Destination; - - Sd = (SCRATCH_DATA *) Scratch; - - CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); - OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); - - // - // If compressed file size is 0, return - // - if (OrigSize == 0) { - return RETURN_SUCCESS; - } - - Src = Src + 8; - - SetMem (Sd, sizeof (SCRATCH_DATA), 0); - - // - // The length of the field 'Position Set Code Length Array Size' in Block Header. - // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4 - // For Tiano de/compression algorithm(Version 2), mPBit = 5 - // - switch (Version) { - case 1 : - Sd->mPBit = 4; - break; - case 2 : - Sd->mPBit = 5; - break; - default: - ASSERT (FALSE); - } - Sd->mSrcBase = (UINT8 *)Src; - Sd->mDstBase = Dst; - // - // CompSize and OrigSize are calculated in bytes - // - Sd->mCompSize = CompSize; - Sd->mOrigSize = OrigSize; - - // - // Fill the first BITBUFSIZ bits - // - FillBuf (Sd, BITBUFSIZ); - - // - // Decompress it - // - Decode (Sd); - - if (Sd->mBadTableFlag != 0) { - // - // Something wrong with the source - // - return RETURN_INVALID_PARAMETER; - } - - return RETURN_SUCCESS; -} - -/** - Decompresses a UEFI compressed source buffer. - - Extracts decompressed data to its original form. - This function is designed so that the decompression algorithm can be implemented - without using any memory services. As a result, this function is not allowed to - call any memory allocation services in its implementation. It is the caller's - responsibility to allocate and free the Destination and Scratch buffers. - If the compressed source data specified by Source is successfully decompressed - into Destination, then RETURN_SUCCESS is returned. If the compressed source data - specified by Source is not in a valid compressed data format, - then RETURN_INVALID_PARAMETER is returned. - - If Source is NULL, then ASSERT(). - If Destination is NULL, then ASSERT(). - If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT(). - - @param Source The source buffer containing the compressed data. - @param Destination The destination buffer to store the decompressed data - @param Scratch A temporary scratch buffer that is used to perform the decompression. - This is an optional parameter that may be NULL if the - required scratch buffer size is 0. - - @retval RETURN_SUCCESS Decompression completed successfully, and - the uncompressed buffer is returned in Destination. - @retval RETURN_INVALID_PARAMETER - The source buffer specified by Source is corrupted - (not in a valid compressed format). -**/ -RETURN_STATUS -EFIAPI -UefiDecompress ( - IN CONST VOID *Source, - IN OUT VOID *Destination, - IN OUT VOID *Scratch OPTIONAL - ) -{ - return UefiTianoDecompress (Source, Destination, Scratch, 1); -} - -/** - Examines a GUIDed section and returns the size of the decoded buffer and the - size of an optional scratch buffer required to actually decode the data in a GUIDed section. - - Examines a GUIDed section specified by InputSection. - If GUID for InputSection does not match the GUID that this handler supports, - then RETURN_UNSUPPORTED is returned. - If the required information can not be retrieved from InputSection, - then RETURN_INVALID_PARAMETER is returned. - If the GUID of InputSection does match the GUID that this handler supports, - then the size required to hold the decoded buffer is returned in OututBufferSize, - the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field - from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute. - - If InputSection is NULL, then ASSERT(). - If OutputBufferSize is NULL, then ASSERT(). - If ScratchBufferSize is NULL, then ASSERT(). - If SectionAttribute is NULL, then ASSERT(). - - - @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. - @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required - if the buffer specified by InputSection were decoded. - @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space - if the buffer specified by InputSection were decoded. - @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes - field of EFI_GUID_DEFINED_SECTION in the PI Specification. - - @retval RETURN_SUCCESS The information about InputSection was returned. - @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. - @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection. - -**/ -RETURN_STATUS -EFIAPI -TianoDecompressGetInfo ( - IN CONST VOID *InputSection, - OUT UINT32 *OutputBufferSize, - OUT UINT32 *ScratchBufferSize, - OUT UINT16 *SectionAttribute - ) - -{ - ASSERT (SectionAttribute != NULL); - - if (InputSection == NULL) { - return RETURN_INVALID_PARAMETER; - } - - if (IS_SECTION2 (InputSection)) { - if (!CompareGuid ( - &gTianoCustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - // - // Get guid attribute of guid section. - // - *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes; - - // - // Call Tiano GetInfo to get the required size info. - // - return UefiDecompressGetInfo ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - OutputBufferSize, - ScratchBufferSize - ); - } else { - if (!CompareGuid ( - &gTianoCustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - // - // Get guid attribute of guid section. - // - *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes; - - // - // Call Tiano GetInfo to get the required size info. - // - return UefiDecompressGetInfo ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - OutputBufferSize, - ScratchBufferSize - ); - } -} - -/** - Decompress a Tiano compressed GUIDed section into a caller allocated output buffer. - - Decodes the GUIDed section specified by InputSection. - If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned. - If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned. - If the GUID of InputSection does match the GUID that this handler supports, then InputSection - is decoded into the buffer specified by OutputBuffer and the authentication status of this - decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the - data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise, - the decoded data will be placed in caller allocated buffer specified by OutputBuffer. - - If InputSection is NULL, then ASSERT(). - If OutputBuffer is NULL, then ASSERT(). - If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT(). - If AuthenticationStatus is NULL, then ASSERT(). - - - @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. - @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation. - @param[in] ScratchBuffer A caller allocated buffer that may be required by this function - as a scratch buffer to perform the decode operation. - @param[out] AuthenticationStatus - A pointer to the authentication status of the decoded output buffer. - See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI - section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must - never be set by this handler. - - @retval RETURN_SUCCESS The buffer specified by InputSection was decoded. - @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. - @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded. - -**/ -RETURN_STATUS -EFIAPI -TianoDecompress ( - IN CONST VOID *InputSection, - OUT VOID **OutputBuffer, - IN VOID *ScratchBuffer, OPTIONAL - OUT UINT32 *AuthenticationStatus - ) -{ - ASSERT (OutputBuffer != NULL); - ASSERT (InputSection != NULL); - - if (IS_SECTION2 (InputSection)) { - if (!CompareGuid ( - &gTianoCustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - - // - // Set Authentication to Zero. - // - *AuthenticationStatus = 0; - - // - // Call Tiano Decompress to get the raw data - // - return UefiTianoDecompress ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - *OutputBuffer, - ScratchBuffer, - 2 - ); - } else { - if (!CompareGuid ( - &gTianoCustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - - // - // Set Authentication to Zero. - // - *AuthenticationStatus = 0; - - // - // Call Tiano Decompress to get the raw data - // - return UefiTianoDecompress ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - *OutputBuffer, - ScratchBuffer, - 2 - ); - } -} - -/** - Registers TianoDecompress and TianoDecompressGetInfo handlers with TianoCustomerDecompressGuid - - @retval RETURN_SUCCESS Register successfully. - @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler. -**/ -RETURN_STATUS -EFIAPI -TianoDecompressLibConstructor ( -) -{ - return ExtractGuidedSectionRegisterHandlers ( - &gTianoCustomDecompressGuid, - TianoDecompressGetInfo, - TianoDecompress - ); -} diff --git a/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf b/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf deleted file mode 100644 index 18417d1956..0000000000 --- a/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf +++ /dev/null @@ -1,48 +0,0 @@ -## @file -# This library instance produces UefiDecompressLib and Tiano Custom decompression algorithm. -# Tiano custom decompression algorithm shares most of code with Uefi Decompress algorithm. -# -# 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 -# 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 = BaseUefiTianoDecompressLib - MODULE_UNI_FILE = BaseUefiTianoDecompressLib.uni - FILE_GUID = d774c4d9-c121-4da3-a5e2-0f317e3c630c - MODULE_TYPE = BASE - VERSION_STRING = 1.0 - LIBRARY_CLASS = UefiDecompressLib - CONSTRUCTOR = TianoDecompressLibConstructor - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - BaseUefiTianoCustomDecompressLibInternals.h - BaseUefiTianoCustomDecompressLib.c - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - BaseLib - DebugLib - BaseMemoryLib - ExtractGuidedSectionLib - -[Guids] - gTianoCustomDecompressGuid ## PRODUCES ## UNDEFINED # specifies tiano custom decompress algorithm. - diff --git a/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLibInternals.h b/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLibInternals.h deleted file mode 100644 index 6ba3f43f75..0000000000 --- a/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLibInternals.h +++ /dev/null @@ -1,220 +0,0 @@ -/** @file - Internal data structure and interfaces defintions for UEFI and Tiano Decompress Libary. - - Copyright (c) 2006 - 2009, Intel 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 __BASE_UEFI_TIANO_CUSTOM_DECOMPRESS_LIB_INTERNALS_H__ -#define __BASE_UEFI_TIANO_CUSTOM_DECOMPRESS_LIB_INTERNALS_H__ - -#include - -#include -#include -#include -#include -#include -#include - -// -// Decompression algorithm begins here -// -#define BITBUFSIZ 32 -#define MAXMATCH 256 -#define THRESHOLD 3 -#define CODE_BIT 16 -#define BAD_TABLE - 1 - -// -// C: Char&Len Set; P: Position Set; T: exTra Set -// -#define NC (0xff + MAXMATCH + 2 - THRESHOLD) -#define CBIT 9 -#define MAXPBIT 5 -#define TBIT 5 -#define MAXNP ((1U << MAXPBIT) - 1) -#define NT (CODE_BIT + 3) -#if NT > MAXNP -#define NPT NT -#else -#define NPT MAXNP -#endif - -typedef struct { - UINT8 *mSrcBase; // Starting address of compressed data - UINT8 *mDstBase; // Starting address of decompressed data - UINT32 mOutBuf; - UINT32 mInBuf; - - UINT16 mBitCount; - UINT32 mBitBuf; - UINT32 mSubBitBuf; - UINT16 mBlockSize; - UINT32 mCompSize; - UINT32 mOrigSize; - - UINT16 mBadTableFlag; - - UINT16 mLeft[2 * NC - 1]; - UINT16 mRight[2 * NC - 1]; - UINT8 mCLen[NC]; - UINT8 mPTLen[NPT]; - UINT16 mCTable[4096]; - UINT16 mPTTable[256]; - - /// - /// The length of the field 'Position Set Code Length Array Size' in Block Header. - /// For UEFI 2.0 de/compression algorithm, mPBit = 4 - /// For Tiano de/compression algorithm, mPBit = 5 - /// - UINT8 mPBit; -} SCRATCH_DATA; - -/** - Read NumOfBit of bits from source into mBitBuf. - - Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. - - @param Sd The global scratch data - @param NumOfBits The number of bits to shift and read. - -**/ -VOID -FillBuf ( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfBits - ); - -/** - Get NumOfBits of bits out from mBitBuf. - - Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent - NumOfBits of bits from source. Returns NumOfBits of bits that are - popped out. - - @param Sd The global scratch data. - @param NumOfBits The number of bits to pop and read. - - @return The bits that are popped out. - -**/ -UINT32 -GetBits ( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfBits - ); - -/** - Creates Huffman Code mapping table according to code length array. - - Creates Huffman Code mapping table for Extra Set, Char&Len Set - and Position Set according to code length array. - - @param Sd The global scratch data - @param NumOfChar Number of symbols in the symbol set - @param BitLen Code length array - @param TableBits The width of the mapping table - @param Table The table to be created. - - @retval 0 OK. - @retval BAD_TABLE The table is corrupted. - -**/ -UINT16 -MakeTable ( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfChar, - IN UINT8 *BitLen, - IN UINT16 TableBits, - OUT UINT16 *Table - ); - -/** - Decodes a position value. - - Get a position value according to Position Huffman Table. - - @param Sd the global scratch data - - @return The position value decoded. - -**/ -UINT32 -DecodeP ( - IN SCRATCH_DATA *Sd - ); - -/** - Reads code lengths for the Extra Set or the Position Set. - - Read in the Extra Set or Pointion Set Length Arrary, then - generate the Huffman code mapping for them. - - @param Sd The global scratch data. - @param nn Number of symbols. - @param nbit Number of bits needed to represent nn. - @param Special The special symbol that needs to be taken care of. - - @retval 0 OK. - @retval BAD_TABLE Table is corrupted. - -**/ -UINT16 -ReadPTLen ( - IN SCRATCH_DATA *Sd, - IN UINT16 nn, - IN UINT16 nbit, - IN UINT16 Special - ); - -/** - Reads code lengths for Char&Len Set. - - Read in and decode the Char&Len Set Code Length Array, then - generate the Huffman Code mapping table for the Char&Len Set. - - @param Sd the global scratch data - -**/ -VOID -ReadCLen ( - SCRATCH_DATA *Sd - ); - -/** - Decode a character/length value. - - Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates - Huffman code mapping table for Extra Set, Code&Len Set and - Position Set. - - @param Sd The global scratch data. - - @return The value decoded. - -**/ -UINT16 -DecodeC ( - SCRATCH_DATA *Sd - ); - -/** - Decode the source data and put the resulting data into the destination buffer. - - @param Sd The global scratch data - -**/ -VOID -Decode ( - SCRATCH_DATA *Sd - ); - -#endif diff --git a/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoDecompressLib.uni b/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoDecompressLib.uni deleted file mode 100644 index f18b1ff6b1..0000000000 Binary files a/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoDecompressLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c deleted file mode 100644 index fc9b533f2c..0000000000 --- a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c +++ /dev/null @@ -1,518 +0,0 @@ -/** @file - Capsule Library instance to process capsule images. - - 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. - -**/ -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/** - Function indicate the current completion progress of the firmware - update. Platform may override with own specific progress function. - - @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update - - @retval EFI_SUCESS Input capsule is a correct FMP capsule. -**/ -EFI_STATUS -EFIAPI -Update_Image_Progress ( - IN UINTN Completion -) -{ - return EFI_SUCCESS; -} - - -/** - Validate Fmp capsules layout. - - @param CapsuleHeader Points to a capsule header. - - @retval EFI_SUCESS Input capsule is a correct FMP capsule. - @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule. -**/ -EFI_STATUS -ValidateFmpCapsule ( - IN EFI_CAPSULE_HEADER *CapsuleHeader - ) -{ - EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader; - UINT8 *EndOfCapsule; - EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader; - UINT8 *EndOfPayload; - UINT64 *ItemOffsetList; - UINT32 ItemNum; - UINTN Index; - - FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); - EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize; - - if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) { - return EFI_INVALID_PARAMETER; - } - ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1); - - ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; - - if (ItemNum == FmpCapsuleHeader->EmbeddedDriverCount) { - // - // No payload element - // - if (((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]) < EndOfCapsule) { - return EFI_SUCCESS; - } else { - return EFI_INVALID_PARAMETER; - } - } - - if (FmpCapsuleHeader->PayloadItemCount != 0) { - // - // Check if the last payload is within capsule image range - // - ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]); - EndOfPayload = (UINT8 *)(ImageHeader + 1) + ImageHeader->UpdateImageSize + ImageHeader->UpdateVendorCodeSize; - } else { - // - // No driver & payload element in FMP - // - EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1); - } - - if (EndOfPayload != EndOfCapsule) { - return EFI_INVALID_PARAMETER; - } - - // - // All the address in ItemOffsetList must be stored in ascending order - // - if (ItemNum >= 2) { - for (Index = 0; Index < ItemNum - 1; Index++) { - if (ItemOffsetList[Index] >= ItemOffsetList[Index + 1]) { - return EFI_INVALID_PARAMETER; - } - } - } - - return EFI_SUCCESS; -} - -/** - Process Firmware management protocol data capsule. - - @param CapsuleHeader Points to a capsule header. - - @retval EFI_SUCESS Process Capsule Image successfully. - @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. - @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. - @retval EFI_OUT_OF_RESOURCES Not enough memory. -**/ -EFI_STATUS -ProcessFmpCapsuleImage ( - IN EFI_CAPSULE_HEADER *CapsuleHeader - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader; - EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader; - EFI_HANDLE ImageHandle; - UINT64 *ItemOffsetList; - UINT32 ItemNum; - UINTN Index; - UINTN ExitDataSize; - EFI_HANDLE *HandleBuffer; - EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; - UINTN NumberOfHandles; - UINTN DescriptorSize; - UINT8 FmpImageInfoCount; - UINT32 FmpImageInfoDescriptorVer; - UINTN ImageInfoSize; - UINT32 PackageVersion; - CHAR16 *PackageVersionName; - CHAR16 *AbortReason; - EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; - EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo; - UINTN DriverLen; - UINTN Index1; - UINTN Index2; - MEMMAP_DEVICE_PATH MemMapNode; - EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath; - - Status = EFI_SUCCESS; - HandleBuffer = NULL; - ExitDataSize = 0; - DriverDevicePath = NULL; - - FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); - - if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) { - return EFI_INVALID_PARAMETER; - } - ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1); - - ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; - - // - // capsule in which driver count and payload count are both zero is not processed. - // - if (ItemNum == 0) { - return EFI_SUCCESS; - } - - // - // 1. ConnectAll to ensure - // All the communication protocol required by driver in capsule installed - // All FMP protocols are installed - // - BdsLibConnectAll(); - - - // - // 2. Try to load & start all the drivers within capsule - // - SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode)); - MemMapNode.Header.Type = HARDWARE_DEVICE_PATH; - MemMapNode.Header.SubType = HW_MEMMAP_DP; - MemMapNode.MemoryType = EfiBootServicesCode; - MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader; - MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1); - - DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header); - if (DriverDevicePath == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) { - if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) { - // - // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER - // - DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index]; - } else { - DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index]; - } - - Status = gBS->LoadImage( - FALSE, - gImageHandle, - DriverDevicePath, - (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index], - DriverLen, - &ImageHandle - ); - if (EFI_ERROR(Status)) { - goto EXIT; - } - - Status = gBS->StartImage( - ImageHandle, - &ExitDataSize, - NULL - ); - if (EFI_ERROR(Status)) { - DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status)); - goto EXIT; - } - } - - // - // Connnect all again to connect drivers within capsule - // - if (FmpCapsuleHeader->EmbeddedDriverCount > 0) { - BdsLibConnectAll(); - } - - // - // 3. Route payload to right FMP instance - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiFirmwareManagementProtocolGuid, - NULL, - &NumberOfHandles, - &HandleBuffer - ); - - if (!EFI_ERROR(Status)) { - for(Index1 = 0; Index1 < NumberOfHandles; Index1++) { - Status = gBS->HandleProtocol( - HandleBuffer[Index1], - &gEfiFirmwareManagementProtocolGuid, - (VOID **)&Fmp - ); - if (EFI_ERROR(Status)) { - continue; - } - - ImageInfoSize = 0; - Status = Fmp->GetImageInfo ( - Fmp, - &ImageInfoSize, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL - ); - if (Status != EFI_BUFFER_TOO_SMALL) { - continue; - } - - FmpImageInfoBuf = NULL; - FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize); - if (FmpImageInfoBuf == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto EXIT; - } - - PackageVersionName = NULL; - Status = Fmp->GetImageInfo ( - Fmp, - &ImageInfoSize, // ImageInfoSize - FmpImageInfoBuf, // ImageInfo - &FmpImageInfoDescriptorVer, // DescriptorVersion - &FmpImageInfoCount, // DescriptorCount - &DescriptorSize, // DescriptorSize - &PackageVersion, // PackageVersion - &PackageVersionName // PackageVersionName - ); - - // - // If FMP GetInformation interface failed, skip this resource - // - if (EFI_ERROR(Status)) { - FreePool(FmpImageInfoBuf); - continue; - } - - if (PackageVersionName != NULL) { - FreePool(PackageVersionName); - } - - TempFmpImageInfo = FmpImageInfoBuf; - for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) { - // - // Check all the payload entry in capsule payload list - // - for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) { - ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]); - if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) && - ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) { - AbortReason = NULL; - if (ImageHeader->UpdateVendorCodeSize == 0) { - Status = Fmp->SetImage( - Fmp, - TempFmpImageInfo->ImageIndex, // ImageIndex - (UINT8 *)(ImageHeader + 1), // Image - ImageHeader->UpdateImageSize, // ImageSize - NULL, // VendorCode - Update_Image_Progress, // Progress - &AbortReason // AbortReason - ); - } else { - Status = Fmp->SetImage( - Fmp, - TempFmpImageInfo->ImageIndex, // ImageIndex - (UINT8 *)(ImageHeader + 1), // Image - ImageHeader->UpdateImageSize, // ImageSize - (UINT8 *)((UINT8 *) (ImageHeader + 1) + ImageHeader->UpdateImageSize), // VendorCode - Update_Image_Progress, // Progress - &AbortReason // AbortReason - ); - } - if (AbortReason != NULL) { - DEBUG ((EFI_D_ERROR, "%s\n", AbortReason)); - FreePool(AbortReason); - } - } - } - // - // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version - // - TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize); - } - FreePool(FmpImageInfoBuf); - } - } - -EXIT: - - if (HandleBuffer != NULL) { - FreePool(HandleBuffer); - } - - if (DriverDevicePath != NULL) { - FreePool(DriverDevicePath); - } - - return Status; -} - -/** - Those capsules supported by the firmwares. - - @param CapsuleHeader Points to a capsule header. - - @retval EFI_SUCESS Input capsule is supported by firmware. - @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware. - @retval EFI_INVALID_PARAMETER Input capsule layout is not correct -**/ -EFI_STATUS -EFIAPI -SupportCapsuleImage ( - IN EFI_CAPSULE_HEADER *CapsuleHeader - ) -{ - if (CompareGuid (&gEfiCapsuleGuid, &CapsuleHeader->CapsuleGuid)) { - return EFI_SUCCESS; - } - - if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)) { - // - // Check layout of FMP capsule - // - return ValidateFmpCapsule(CapsuleHeader); - } - - return EFI_UNSUPPORTED; -} - -/** - The firmware implements to process the capsule image. - - @param CapsuleHeader Points to a capsule header. - - @retval EFI_SUCESS Process Capsule Image successfully. - @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. - @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. - @retval EFI_OUT_OF_RESOURCES Not enough memory. -**/ -EFI_STATUS -EFIAPI -ProcessCapsuleImage ( - IN EFI_CAPSULE_HEADER *CapsuleHeader - ) -{ - UINT32 Length; - EFI_FIRMWARE_VOLUME_HEADER *FvImage; - EFI_FIRMWARE_VOLUME_HEADER *ProcessedFvImage; - EFI_STATUS Status; - EFI_HANDLE FvProtocolHandle; - UINT32 FvAlignment; - - FvImage = NULL; - ProcessedFvImage = NULL; - Status = EFI_SUCCESS; - - if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) { - return EFI_UNSUPPORTED; - } - - // - // Check FMP capsule layout - // - if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)){ - Status = ValidateFmpCapsule(CapsuleHeader); - if (EFI_ERROR(Status)) { - return Status; - } - - // - // Press EFI FMP Capsule - // - return ProcessFmpCapsuleImage(CapsuleHeader); - } - - // - // Skip the capsule header, move to the Firware Volume - // - FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); - Length = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize; - - while (Length != 0) { - // - // Point to the next firmware volume header, and then - // call the DXE service to process it. - // - if (FvImage->FvLength > (UINTN) Length) { - // - // Notes: need to stuff this status somewhere so that the - // error can be detected at OS runtime - // - Status = EFI_VOLUME_CORRUPTED; - break; - } - - FvAlignment = 1 << ((FvImage->Attributes & EFI_FVB2_ALIGNMENT) >> 16); - // - // FvAlignment must be more than 8 bytes required by FvHeader structure. - // - if (FvAlignment < 8) { - FvAlignment = 8; - } - // - // Check FvImage Align is required. - // - if (((UINTN) FvImage % FvAlignment) == 0) { - ProcessedFvImage = FvImage; - } else { - // - // Allocate new aligned buffer to store FvImage. - // - ProcessedFvImage = (EFI_FIRMWARE_VOLUME_HEADER *) AllocateAlignedPages ((UINTN) EFI_SIZE_TO_PAGES ((UINTN) FvImage->FvLength), (UINTN) FvAlignment); - if (ProcessedFvImage == NULL) { - Status = EFI_OUT_OF_RESOURCES; - break; - } - CopyMem (ProcessedFvImage, FvImage, (UINTN) FvImage->FvLength); - } - - Status = gDS->ProcessFirmwareVolume ( - (VOID *) ProcessedFvImage, - (UINTN) ProcessedFvImage->FvLength, - &FvProtocolHandle - ); - if (EFI_ERROR (Status)) { - break; - } - // - // Call the dispatcher to dispatch any drivers from the produced firmware volume - // - gDS->Dispatch (); - // - // On to the next FV in the capsule - // - Length -= (UINT32) FvImage->FvLength; - FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) FvImage + FvImage->FvLength); - } - - return Status; -} - - diff --git a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf deleted file mode 100644 index 28b4693c1f..0000000000 --- a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf +++ /dev/null @@ -1,55 +0,0 @@ -## @file -# Capsule library instance for DXE_DRIVER, DXE_RUNTIME_DRIVER. -# -# Copyright (c) 2007 - 2015, Intel 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 = DxeCapsuleLib - MODULE_UNI_FILE = DxeCapsuleLib.uni - FILE_GUID = 654950df-1ede-4b04-b144-6b77845736ad - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = CapsuleLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION - - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - DxeCapsuleLib.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - BaseMemoryLib - DebugLib - MemoryAllocationLib - DxeServicesTableLib - GenericBdsLib - UefiBootServicesTableLib - DevicePathLib - -[Protocols] - gEfiFirmwareManagementProtocolGuid ## SOMETIMES_CONSUMES - -[Guids] - gEfiCapsuleGuid ## SOMETIMES_CONSUMES ## GUID # Capsule Image Header Guid - gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID diff --git a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.uni b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.uni deleted file mode 100644 index 8191bfa72d..0000000000 Binary files a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf b/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf deleted file mode 100644 index a97d4e8aac..0000000000 --- a/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf +++ /dev/null @@ -1,58 +0,0 @@ -## @file -# Framework DXE report status code library to support EFI1.1 and UEFI2.0 system. -# -# 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 -# 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 = DxeReportStatusCodeLib - MODULE_UNI_FILE = DxeReportStatusCodeLib.uni - FILE_GUID = 3ddc3b12-99ea-4364-b315-6310a2050be5 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = ReportStatusCodeLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - ReportStatusCodeLib.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - PcdLib - BaseMemoryLib - MemoryAllocationLib - UefiBootServicesTableLib - DebugLib - UefiRuntimeServicesTableLib - DevicePathLib - -[Guids] - gEfiStatusCodeSpecificDataGuid ## SOMETIMES_CONSUMES ## UNDEFINED - gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## UNDEFINED - -[Protocols] - gEfiStatusCodeRuntimeProtocolGuid ## SOMETIMES_CONSUMES # Used if revision of the EFI Specification is not less than 0x20000 - -[Pcd] - gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask ## CONSUMES - diff --git a/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.uni b/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.uni deleted file mode 100644 index befd970aa5..0000000000 Binary files a/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/ReportStatusCodeLib.c b/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/ReportStatusCodeLib.c deleted file mode 100644 index a3603f862f..0000000000 --- a/IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/ReportStatusCodeLib.c +++ /dev/null @@ -1,634 +0,0 @@ -/** @file - Report Status Code Library for DXE Phase. - - Copyright (c) 2006 - 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -// -// Define the maximum extended data size that is supported when a status code is -// reported at TPL_HIGH_LEVEL. -// -#define MAX_EXTENDED_DATA_SIZE 0x200 - -EFI_REPORT_STATUS_CODE mReportStatusCode = NULL; - -/** - Locate the report status code service. - - @return Function pointer to the report status code service. - NULL is returned if no status code service is available. - -**/ -EFI_REPORT_STATUS_CODE -InternalGetReportStatusCode ( - VOID - ) -{ - EFI_STATUS_CODE_PROTOCOL *StatusCodeProtocol; - EFI_STATUS Status; - - if (gRT != NULL && gRT->Hdr.Revision < 0x20000) { - return ((FRAMEWORK_EFI_RUNTIME_SERVICES*)gRT)->ReportStatusCode; - } else if (gBS != NULL && gBS->LocateProtocol != NULL) { - Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol); - if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) { - return StatusCodeProtocol->ReportStatusCode; - } - } - - return NULL; -} - -/** - Internal worker function that reports a status code through the status code service. - - If status code service is not cached, then this function checks if status code service is - available in system. If status code service is not available, then EFI_UNSUPPORTED is - returned. If status code service is present, then it is cached in mReportStatusCode. - Finally this function reports status code through the status code service. - - @param Type Status code type. - @param Value Status code value. - @param Instance Status code instance number. - @param CallerId Pointer to a GUID that identifies the caller of this - function. This is an optional parameter that may be - NULL. - @param Data Pointer to the extended data buffer. This is an - optional parameter that may be NULL. - - @retval EFI_SUCCESS The status code was reported. - @retval EFI_UNSUPPORTED Status code service is not available. - @retval EFI_UNSUPPORTED Status code type is not supported. - -**/ -EFI_STATUS -InternalReportStatusCode ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance, - IN CONST EFI_GUID *CallerId OPTIONAL, - IN EFI_STATUS_CODE_DATA *Data OPTIONAL - ) -{ - if ((ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || - (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) || - (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)) { - // - // If mReportStatusCode is NULL, then check if status code service is available in system. - // - if (mReportStatusCode == NULL) { - mReportStatusCode = InternalGetReportStatusCode (); - if (mReportStatusCode == NULL) { - return EFI_UNSUPPORTED; - } - } - - // - // A status code service is present in system, so pass in all the parameters to the service. - // - return (*mReportStatusCode) (Type, Value, Instance, (EFI_GUID *)CallerId, Data); - } - - return EFI_UNSUPPORTED; -} - - -/** - Converts a status code to an 8-bit POST code value. - - Converts the status code specified by CodeType and Value to an 8-bit POST code - and returns the 8-bit POST code in PostCode. If CodeType is an - EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode - are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits - 24..26 of Value., and TRUE is returned. Otherwise, FALSE is returned. - - If PostCode is NULL, then ASSERT(). - - @param CodeType The type of status code being converted. - @param Value The status code value being converted. - @param PostCode A pointer to the 8-bit POST code value to return. - - @retval TRUE The status code specified by CodeType and Value was converted - to an 8-bit POST code and returned in PostCode. - @retval FALSE The status code specified by CodeType and Value could not be - converted to an 8-bit POST code value. - -**/ -BOOLEAN -EFIAPI -CodeTypeToPostCode ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - OUT UINT8 *PostCode - ) -{ - // - // If PostCode is NULL, then ASSERT() - // - ASSERT (PostCode != NULL); - - // - // Convert Value to an 8 bit post code - // - if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || - ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ) { - *PostCode = (UINT8) ((((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5) | - (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f)); - return TRUE; - } - return FALSE; -} - - -/** - Extracts ASSERT() information from a status code structure. - - Converts the status code specified by CodeType, Value, and Data to the ASSERT() - arguments specified by Filename, Description, and LineNumber. If CodeType is - an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and - Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract - Filename, Description, and LineNumber from the optional data area of the - status code buffer specified by Data. The optional data area of Data contains - a Null-terminated ASCII string for the FileName, followed by a Null-terminated - ASCII string for the Description, followed by a 32-bit LineNumber. If the - ASSERT() information could be extracted from Data, then return TRUE. - Otherwise, FALSE is returned. - - If Data is NULL, then ASSERT(). - If Filename is NULL, then ASSERT(). - If Description is NULL, then ASSERT(). - If LineNumber is NULL, then ASSERT(). - - @param CodeType The type of status code being converted. - @param Value The status code value being converted. - @param Data Pointer to status code data buffer. - @param Filename Pointer to the source file name that generated the ASSERT(). - @param Description Pointer to the description of the ASSERT(). - @param LineNumber Pointer to source line number that generated the ASSERT(). - - @retval TRUE The status code specified by CodeType, Value, and Data was - converted ASSERT() arguments specified by Filename, Description, - and LineNumber. - @retval FALSE The status code specified by CodeType, Value, and Data could - not be converted to ASSERT() arguments. - -**/ -BOOLEAN -EFIAPI -ReportStatusCodeExtractAssertInfo ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - IN CONST EFI_STATUS_CODE_DATA *Data, - OUT CHAR8 **Filename, - OUT CHAR8 **Description, - OUT UINT32 *LineNumber - ) -{ - EFI_DEBUG_ASSERT_DATA *AssertData; - - ASSERT (Data != NULL); - ASSERT (Filename != NULL); - ASSERT (Description != NULL); - ASSERT (LineNumber != NULL); - - if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && - ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) && - ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) { - AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1); - *Filename = (CHAR8 *)(AssertData + 1); - *Description = *Filename + AsciiStrLen (*Filename) + 1; - *LineNumber = AssertData->LineNumber; - return TRUE; - } - return FALSE; -} - - -/** - Extracts DEBUG() information from a status code structure. - - Converts the status code specified by Data to the DEBUG() arguments specified - by ErrorLevel, Marker, and Format. If type GUID in Data is - EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and - Format from the optional data area of the status code buffer specified by Data. - The optional data area of Data contains a 32-bit ErrorLevel followed by Marker - which is 12 UINTN parameters, followed by a Null-terminated ASCII string for - the Format. If the DEBUG() information could be extracted from Data, then - return TRUE. Otherwise, FALSE is returned. - - If Data is NULL, then ASSERT(). - If ErrorLevel is NULL, then ASSERT(). - If Marker is NULL, then ASSERT(). - If Format is NULL, then ASSERT(). - - @param Data Pointer to status code data buffer. - @param ErrorLevel Pointer to error level mask for a debug message. - @param Marker Pointer to the variable argument list associated with Format. - @param Format Pointer to a Null-terminated ASCII format string of a - debug message. - - @retval TRUE The status code specified by Data was converted DEBUG() arguments - specified by ErrorLevel, Marker, and Format. - @retval FALSE The status code specified by Data could not be converted to - DEBUG() arguments. - -**/ -BOOLEAN -EFIAPI -ReportStatusCodeExtractDebugInfo ( - IN CONST EFI_STATUS_CODE_DATA *Data, - OUT UINT32 *ErrorLevel, - OUT BASE_LIST *Marker, - OUT CHAR8 **Format - ) -{ - EFI_DEBUG_INFO *DebugInfo; - - ASSERT (Data != NULL); - ASSERT (ErrorLevel != NULL); - ASSERT (Marker != NULL); - ASSERT (Format != NULL); - - // - // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE - // - if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) { - return FALSE; - } - - // - // Retrieve the debug information from the status code record - // - DebugInfo = (EFI_DEBUG_INFO *)(Data + 1); - - *ErrorLevel = DebugInfo->ErrorLevel; - - // - // The first 12 * sizeof (UINT64) bytes following EFI_DEBUG_INFO are for variable arguments - // of format in DEBUG string. Its address is returned in Marker and has to be 64-bit aligned. - // It must be noticed that EFI_DEBUG_INFO follows EFI_STATUS_CODE_DATA, whose size is - // 20 bytes. The size of EFI_DEBUG_INFO is 4 bytes, so we can ensure that Marker - // returned is 64-bit aligned. - // 64-bit aligned is a must, otherwise retrieving 64-bit parameter from BASE_LIST will - // cause unalignment exception. - // - *Marker = (BASE_LIST) (DebugInfo + 1); - *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12); - - return TRUE; -} - - -/** - Reports a status code. - - Reports the status code specified by the parameters Type and Value. Status - code also require an instance, caller ID, and extended data. This function - passed in a zero instance, NULL extended data, and a caller ID of - gEfiCallerIdGuid, which is the GUID for the module. - - ReportStatusCode()must actively prevent recusrsion. If ReportStatusCode() - is called while processing another any other Report Status Code Library function, - then ReportStatusCode() must return immediately. - - @param Type Status code type. - @param Value Status code value. - - @retval EFI_SUCCESS The status code was reported. - @retval EFI_DEVICE_ERROR There status code could not be reported due to a - device error. - @retval EFI_UNSUPPORTED Report status code is not supported - -**/ -EFI_STATUS -EFIAPI -ReportStatusCode ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value - ) -{ - return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL); -} - - -/** - Reports a status code with a Device Path Protocol as the extended data. - - Allocates and fills in the extended data section of a status code with the - Device Path Protocol specified by DevicePath. This function is responsible - for allocating a buffer large enough for the standard header and the device - path. The standard header is filled in with a GUID of - gEfiStatusCodeSpecificDataGuid. The status code is reported with a zero - instance and a caller ID of gEfiCallerIdGuid. - - ReportStatusCodeWithDevicePath()must actively prevent recursion. If - ReportStatusCodeWithDevicePath() is called while processing another any other - Report Status Code Library function, then ReportStatusCodeWithDevicePath() - must return EFI_DEVICE_ERROR immediately. - - If DevicePath is NULL, then ASSERT(). - - @param Type Status code type. - @param Value Status code value. - @param DevicePath Pointer to the Device Path Protocol to be reported. - - @retval EFI_SUCCESS The status code was reported with the extended - data specified by DevicePath. - @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the - extended data section. - @retval EFI_UNSUPPORTED Report status code is not supported - -**/ -EFI_STATUS -EFIAPI -ReportStatusCodeWithDevicePath ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - ASSERT (DevicePath != NULL); - return ReportStatusCodeWithExtendedData ( - Type, - Value, - (VOID *)DevicePath, - GetDevicePathSize (DevicePath) - ); -} - - -/** - Reports a status code with an extended data buffer. - - Allocates and fills in the extended data section of a status code with the - extended data specified by ExtendedData and ExtendedDataSize. ExtendedData - is assumed to be one of the data structures specified in Related Definitions. - These data structure do not have the standard header, so this function is - responsible for allocating a buffer large enough for the standard header and - the extended data passed into this function. The standard header is filled - in with a GUID of gEfiStatusCodeSpecificDataGuid. The status code is reported - with a zero instance and a caller ID of gEfiCallerIdGuid. - - ReportStatusCodeWithExtendedData()must actively prevent recursion. If - ReportStatusCodeWithExtendedData() is called while processing another any other - Report Status Code Library function, then ReportStatusCodeWithExtendedData() - must return EFI_DEVICE_ERROR immediately. - - If ExtendedData is NULL, then ASSERT(). - If ExtendedDataSize is 0, then ASSERT(). - - @param Type Status code type. - @param Value Status code value. - @param ExtendedData Pointer to the extended data buffer to be reported. - @param ExtendedDataSize The size, in bytes, of the extended data buffer to - be reported. - - @retval EFI_SUCCESS The status code was reported with the extended - data specified by ExtendedData and ExtendedDataSize. - @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the - extended data section. - @retval EFI_UNSUPPORTED Report status code is not supported - -**/ -EFI_STATUS -EFIAPI -ReportStatusCodeWithExtendedData ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN CONST VOID *ExtendedData, - IN UINTN ExtendedDataSize - ) -{ - ASSERT (ExtendedData != NULL); - ASSERT (ExtendedDataSize != 0); - return ReportStatusCodeEx ( - Type, - Value, - 0, - NULL, - NULL, - ExtendedData, - ExtendedDataSize - ); -} - - -/** - Reports a status code with full parameters. - - The function reports a status code. If ExtendedData is NULL and ExtendedDataSize - is 0, then an extended data buffer is not reported. If ExtendedData is not - NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. - ExtendedData is assumed not have the standard status code header, so this function - is responsible for allocating a buffer large enough for the standard header and - the extended data passed into this function. The standard header is filled in - with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a - GUID of gEfiStatusCodeSpecificDataGuid is used. The status code is reported with - an instance specified by Instance and a caller ID specified by CallerId. If - CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. - - ReportStatusCodeEx()must actively prevent recursion. If - ReportStatusCodeEx() is called while processing another any - other Report Status Code Library function, then - ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. - - If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). - If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). - - @param Type Status code type. - @param Value Status code value. - @param Instance Status code instance number. - @param CallerId Pointer to a GUID that identifies the caller of this - function. If this parameter is NULL, then a caller - ID of gEfiCallerIdGuid is used. - @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. - If this parameter is NULL, then a the status code - standard header is filled in with - gEfiStatusCodeSpecificDataGuid. - @param ExtendedData Pointer to the extended data buffer. This is an - optional parameter that may be NULL. - @param ExtendedDataSize The size, in bytes, of the extended data buffer. - - @retval EFI_SUCCESS The status code was reported. - @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate - the extended data section if it was specified. - @retval EFI_UNSUPPORTED Report status code is not supported - -**/ -EFI_STATUS -EFIAPI -ReportStatusCodeEx ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance, - IN CONST EFI_GUID *CallerId OPTIONAL, - IN CONST EFI_GUID *ExtendedDataGuid OPTIONAL, - IN CONST VOID *ExtendedData OPTIONAL, - IN UINTN ExtendedDataSize - ) -{ - EFI_STATUS Status; - EFI_STATUS_CODE_DATA *StatusCodeData; - EFI_TPL Tpl; - UINT64 Buffer[(MAX_EXTENDED_DATA_SIZE / sizeof (UINT64)) + 1]; - - ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); - ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); - - if (gBS == NULL || gBS->AllocatePool == NULL || gBS->FreePool == NULL) { - return EFI_UNSUPPORTED; - } - - // - // Retrieve the current TPL - // - Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - gBS->RestoreTPL (Tpl); - - StatusCodeData = NULL; - if (Tpl <= TPL_NOTIFY) { - // - // Allocate space for the Status Code Header and its buffer - // - gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData); - } - - if (StatusCodeData == NULL) { - // - // If a buffer could not be allocated, then see if the local variable Buffer can be used - // - if (ExtendedDataSize > (MAX_EXTENDED_DATA_SIZE - sizeof (EFI_STATUS_CODE_DATA))) { - // - // The local variable Buffer not large enough to hold the extended data associated - // with the status code being reported. - // - DEBUG ((EFI_D_ERROR, "Status code extended data is too large to be reported!\n")); - return EFI_OUT_OF_RESOURCES; - } - StatusCodeData = (EFI_STATUS_CODE_DATA *)Buffer; - } - - // - // Fill in the extended data header - // - StatusCodeData->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA); - StatusCodeData->Size = (UINT16)ExtendedDataSize; - if (ExtendedDataGuid == NULL) { - ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid; - } - CopyGuid (&StatusCodeData->Type, ExtendedDataGuid); - - // - // Fill in the extended data buffer - // - if (ExtendedData != NULL) { - CopyMem (StatusCodeData + 1, ExtendedData, ExtendedDataSize); - } - - // - // Report the status code - // - if (CallerId == NULL) { - CallerId = &gEfiCallerIdGuid; - } - Status = InternalReportStatusCode (Type, Value, Instance, CallerId, StatusCodeData); - - // - // Free the allocated buffer - // - if (StatusCodeData != (EFI_STATUS_CODE_DATA *)Buffer) { - gBS->FreePool (StatusCodeData); - } - - return Status; -} - - -/** - Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled - - This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED - bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is set. - @retval FALSE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -ReportProgressCodeEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0); -} - - -/** - Returns TRUE if status codes of type EFI_ERROR_CODE are enabled - - This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED - bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is set. - @retval FALSE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -ReportErrorCodeEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0); -} - - -/** - Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled - - This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED - bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is set. - @retval FALSE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -ReportDebugCodeEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0); -} diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c deleted file mode 100644 index bba62a801a..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c +++ /dev/null @@ -1,4356 +0,0 @@ -/** @file - BDS Lib functions which relate with create or process the boot option. - -Copyright (c) 2004 - 2016, Intel 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 - ); - // - // Deleting variable with existing variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - // - // 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 - // - UnicodeStrToAsciiStrS (BootDesc, HelpString, sizeof (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; - } - - BootOrder = BdsLibGetVariableAndSize ( - L"BootOrder", - &gEfiGlobalVariableGuid, - &BootOrderSize - ); - if (BootOrder == NULL) { - return EFI_NOT_FOUND; - } - - LegacyBios->GetBbsInfo ( - LegacyBios, - &HddCount, - &LocalHddInfo, - &BbsCount, - &LocalBbsTable - ); - - 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 - ); - // - // Shrinking variable with existing variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - 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)) { - ASSERT (BootOrder != NULL); - 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_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_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 *) ((UINTN) 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; - } - } - - FreePool (DeviceType); - - 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; - LIST_ENTRY TempBootLists; - EFI_BOOT_LOGO_PROTOCOL *BootLogo; - - Status = EFI_SUCCESS; - *ExitDataSize = 0; - *ExitData = 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. - // - SetVariableAndReportStatusCodeOnError ( - L"BootCurrent", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - sizeof (UINT16), - &Option->BootCurrent - ); - } - - // - // Signal the EVT_SIGNAL_READY_TO_BOOT event - // - EfiSignalEventReadyToBoot(); - - // - // Report Status Code to indicate ReadyToBoot event was signalled - // - REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT)); - - // - // 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 - // Deleting variable with current implementation shouldn't fail. - // - gRT->SetVariable ( - L"BootCurrent", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - 0, - NULL - ); - - 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 - // - GetVariable2 ( - HD_BOOT_DEVICE_PATH_VARIABLE_NAME, - &gHdBootDevicePathVariablGuid, - (VOID **) &CachedDevicePath, - &CachedDevicePathSize - ); - - // - // Delete the invalid HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable. - // - if ((CachedDevicePath != NULL) && !IsDevicePathValid (CachedDevicePath, CachedDevicePathSize)) { - FreePool (CachedDevicePath); - CachedDevicePath = NULL; - Status = gRT->SetVariable ( - HD_BOOT_DEVICE_PATH_VARIABLE_NAME, - &gHdBootDevicePathVariablGuid, - 0, - 0, - NULL - ); - ASSERT_EFI_ERROR (Status); - } - - 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 - // Failure to set the variable only impacts the performance when next time expanding the short-form device path. - // - Status = gRT->SetVariable ( - HD_BOOT_DEVICE_PATH_VARIABLE_NAME, - &gHdBootDevicePathVariablGuid, - EFI_VARIABLE_BOOTSERVICE_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 - // Failure to set the variable only impacts the performance when next time expanding the short-form device path. - // - Status = gRT->SetVariable ( - HD_BOOT_DEVICE_PATH_VARIABLE_NAME, - &gHdBootDevicePathVariablGuid, - EFI_VARIABLE_BOOTSERVICE_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 - ); - // - // Shrinking variable with existing variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - 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 - ); - // - // Deleting variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - // - // 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 - ); - // - // Shrinking variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - 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 - ); - // - // Failure to set the variable only impacts the performance next time enumerating the boot options. - // - - 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 logical partition - // - if (EFI_ERROR (Status) || BlkIo->Media->LogicalPartition) { - continue; - } - - // - // firstly fixed block io then the removable block io - // - if (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: - default: - 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; - } - } - } - - 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)), Index); - } else { - UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK))); - } - 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 - ) -{ - EFI_STATUS Status; - 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) { - Status = gRT->SetVariable ( - L"BootNext", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - 0, - NULL - ); - // - // Deleting variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - // - // 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); - FreePool(BootOption); - FreePool(BootNext); - } - -} - -/** - 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); - ASSERT (NewDevicePath != NULL); - *DevicePath = NewDevicePath; - return EFI_SUCCESS; - } - return EFI_NOT_FOUND; -} diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c deleted file mode 100644 index f487aa611a..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c +++ /dev/null @@ -1,435 +0,0 @@ -/** @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/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c deleted file mode 100644 index eefec0642a..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c +++ /dev/null @@ -1,1301 +0,0 @@ -/** @file - BDS Lib functions which contain all the code to connect console device - -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 -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 handle 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 handle 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 = SetVariableAndReportStatusCodeOnError ( - ConVarName, - &gEfiGlobalVariableGuid, - Attributes, - DevicePathSize, - NewDevicePath - ); - if ((DevicePathSize == 0) && (Status == EFI_NOT_FOUND)) { - Status = EFI_SUCCESS; - } - - 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/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c deleted file mode 100644 index 24c1998a14..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c +++ /dev/null @@ -1,1589 +0,0 @@ -/** @file - Misc BDS library function - -Copyright (c) 2004 - 2015, Intel 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; - } - FreePool(OptionBuffer); - 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; - - if (DevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - - 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)) { - FreePool(OptionPtr); - 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)) { - FreePool (Variable); - 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) { - FreePool (Variable); - 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); - StrCpyS ( - StringBuffer1, - MAX_STRING_LEN, - L"Configuration changed. Reset to apply it Now." - ); - StrCpyS ( - StringBuffer2, - MAX_STRING_LEN, - 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 = SetVariableAndReportStatusCodeOnError ( - EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, - &gEfiMemoryTypeInformationGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, - VariableSize, - PreviousMemoryTypeInformation - ); - - if (!EFI_ERROR (Status)) { - // - // 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); - } - } else { - DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n")); - } - } -} - -/** - 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); -} - -/** - Set the variable and report the error through status code upon failure. - - @param VariableName A Null-terminated string that is the name of the vendor's variable. - Each VariableName is unique for each VendorGuid. VariableName must - contain 1 or more characters. If VariableName is an empty string, - then EFI_INVALID_PARAMETER is returned. - @param VendorGuid A unique identifier for the vendor. - @param Attributes Attributes bitmask to set for the variable. - @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero - causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is - set, then a SetVariable() call with a DataSize of zero will not cause any change to - the variable value (the timestamp associated with the variable may be updated however - even if no new data value is provided,see the description of the - EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not - be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). - @param Data The contents for the variable. - - @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as - defined by the Attributes. - @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the - DataSize exceeds the maximum allowed. - @retval EFI_INVALID_PARAMETER VariableName is an empty string. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. - @retval EFI_WRITE_PROTECTED The variable in question is read-only. - @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. - @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS - or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo - does NOT pass the validation check carried out by the firmware. - - @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. -**/ -EFI_STATUS -SetVariableAndReportStatusCodeOnError ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN UINT32 Attributes, - IN UINTN DataSize, - IN VOID *Data - ) -{ - EFI_STATUS Status; - EDKII_SET_VARIABLE_STATUS *SetVariableStatus; - UINTN NameSize; - - Status = gRT->SetVariable ( - VariableName, - VendorGuid, - Attributes, - DataSize, - Data - ); - if (EFI_ERROR (Status)) { - NameSize = StrSize (VariableName); - SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize); - if (SetVariableStatus != NULL) { - CopyGuid (&SetVariableStatus->Guid, VendorGuid); - SetVariableStatus->NameSize = NameSize; - SetVariableStatus->DataSize = DataSize; - SetVariableStatus->SetStatus = Status; - SetVariableStatus->Attributes = Attributes; - CopyMem (SetVariableStatus + 1, VariableName, NameSize); - if ((Data != NULL) && (DataSize != 0)) { - CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data, DataSize); - } - - REPORT_STATUS_CODE_EX ( - EFI_ERROR_CODE, - PcdGet32 (PcdErrorCodeSetVariable), - 0, - NULL, - &gEdkiiStatusCodeDataTypeVariableGuid, - SetVariableStatus, - sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize - ); - - FreePool (SetVariableStatus); - } - } - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c deleted file mode 100644 index 2f22e7df7f..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c +++ /dev/null @@ -1,33 +0,0 @@ -/** @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/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf b/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf deleted file mode 100644 index 5a138a9169..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf +++ /dev/null @@ -1,145 +0,0 @@ -## @file -# General BDS library. -# -# 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 - 2014, Intel 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 - MODULE_UNI_FILE = GenericBdsLib.uni - 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] - ## SOMETIMES_CONSUMES ## HOB # The hob holding memory type information - ## SOMETIMES_CONSUMES ## SystemTable # The identifier of memory type information type in system table - ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation" - ## SOMETIMES_PRODUCES ## Variable:L"MemoryTypeInformation" - gEfiMemoryTypeInformationGuid - ## SOMETIMES_CONSUMES ## Variable:L"BootXXXX" # Boot option variable - ## SOMETIMES_PRODUCES ## Variable:L"BootXXXX" # Boot option variable - ## SOMETIMES_CONSUMES ## Variable:L"DriverXXXX" # Driver load option. - ## SOMETIMES_PRODUCES ## Variable:L"DriverXXXX" # Driver load option. - ## SOMETIMES_CONSUMES ## Variable:L"BootNext" # Next Boot Option - ## SOMETIMES_PRODUCES ## Variable:L"BootNext" # Next Boot Option - ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" # The boot option array - ## SOMETIMES_PRODUCES ## Variable:L"BootOrder" # The boot option array - ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" # The driver order list - ## SOMETIMES_CONSUMES ## Variable:L"ConIn" # The device path of console in device - ## SOMETIMES_PRODUCES ## Variable:L"ConIn" # The device path of console in device - ## SOMETIMES_CONSUMES ## Variable:L"ConOut" # The device path of console out device - ## SOMETIMES_PRODUCES ## Variable:L"ConOut" # The device path of console out device - ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" # The device path of error out device - ## SOMETIMES_PRODUCES ## Variable:L"ErrOut" # The device path of error out device - ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" # The boot option of current boot - ## SOMETIMES_PRODUCES ## Variable:L"BootNext" # The number of next boot option - gEfiGlobalVariableGuid - gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID - gPerformanceProtocolGuid ## SOMETIMES_PRODUCES ## Variable:L"PerfDataMemAddr" # The ACPI address of performance data - 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 ## CONSUMES ## HII # HII String PackageList Guid - ## SOMETIMES_PRODUCES ## Variable:L"LegacyDevOrder" - ## SOMETIMES_CONSUMES ## Variable:L"LegacyDevOrder" - gEfiLegacyDevOrderVariableGuid - gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID - -[Protocols] - gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES - gEfiLoadFileProtocolGuid ## SOMETIMES_CONSUMES - gEfiSimpleTextOutProtocolGuid ## CONSUMES - gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES - gEfiSimpleNetworkProtocolGuid ## SOMETIMES_CONSUMES - gEfiDebugPortProtocolGuid ## SOMETIMES_CONSUMES - gEfiSimpleTextInProtocolGuid ## CONSUMES - gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMES - gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES - gEfiCpuArchProtocolGuid ## CONSUMES - gEfiDevicePathProtocolGuid ## CONSUMES - gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES - gEfiUgaDrawProtocolGuid |gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## SOMETIMES_CONSUMES - gEfiOEMBadgingProtocolGuid ## SOMETIMES_CONSUMES - gEfiHiiFontProtocolGuid ## CONSUMES - gEfiUserManagerProtocolGuid ## SOMETIMES_CONSUMES - gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES - -[FeaturePcd] - gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootlogoOnlyEnable ## CONSUMES - -[Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange ## SOMETIMES_CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad ## SOMETIMES_CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart ## SOMETIMES_CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile ## CONSUMES - -# -# [BootMode] -# RECOVERY_FULL ## SOMETIMES_CONSUMES # Memory Type Information variable -# - diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.uni b/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.uni deleted file mode 100644 index 5611f6f6bf..0000000000 Binary files a/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni b/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni deleted file mode 100644 index 7c3b4f9690..0000000000 Binary files a/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h b/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h deleted file mode 100644 index 7201d8a335..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h +++ /dev/null @@ -1,194 +0,0 @@ -/** @file - BDS library definition, include the file and data structure - -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 -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 - ); - -/** - Set the variable and report the error through status code upon failure. - - @param VariableName A Null-terminated string that is the name of the vendor's variable. - Each VariableName is unique for each VendorGuid. VariableName must - contain 1 or more characters. If VariableName is an empty string, - then EFI_INVALID_PARAMETER is returned. - @param VendorGuid A unique identifier for the vendor. - @param Attributes Attributes bitmask to set for the variable. - @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero - causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is - set, then a SetVariable() call with a DataSize of zero will not cause any change to - the variable value (the timestamp associated with the variable may be updated however - even if no new data value is provided,see the description of the - EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not - be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). - @param Data The contents for the variable. - - @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as - defined by the Attributes. - @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the - DataSize exceeds the maximum allowed. - @retval EFI_INVALID_PARAMETER VariableName is an empty string. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. - @retval EFI_WRITE_PROTECTED The variable in question is read-only. - @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. - @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS - or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo - does NOT pass the validation check carried out by the firmware. - - @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. -**/ -EFI_STATUS -SetVariableAndReportStatusCodeOnError ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN UINT32 Attributes, - IN UINTN DataSize, - IN VOID *Data - ); - -#endif // _BDS_LIB_H_ diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c deleted file mode 100644 index e50345a597..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c +++ /dev/null @@ -1,313 +0,0 @@ -/** @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 - 2015, Intel 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) { - AsciiStrCpyS (GaugeString, PERF_TOKEN_SIZE, " "); - } 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) { - 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; - - AsciiStrCpyS (GaugeString, PERF_TOKEN_SIZE, " "); - - // - // 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_SIZE]; - 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 VarSize; - BOOLEAN Found; - - // - // 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; - } - - // - // Reset the entry count - // - mPerfHeader.Count = 0; - - 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); - - // - // Get performance data - // - LogEntryKey = 0; - while ((LogEntryKey = GetPerformanceMeasurement ( - LogEntryKey, - &Handle, - &Token, - &Module, - &StartTicker, - &EndTicker)) != 0) { - if (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) { - continue; - } - - ZeroMem (&mPerfData, sizeof (PERF_DATA)); - - mPerfData.Duration = Duration; - - // - // See if the Handle is in the handle buffer - // - Found = FALSE; - for (Index = 0; Index < NoHandles; Index++) { - if (Handle == Handles[Index]) { - GetNameFromHandle (Handles[Index], GaugeString); - AsciiStrCpyS (mPerfData.Token, PERF_TOKEN_SIZE, GaugeString); - Found = TRUE; - break; - } - } - - if (!Found) { - AsciiStrnCpyS (mPerfData.Token, PERF_TOKEN_SIZE, Token, PERF_TOKEN_LENGTH); - } - - CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA)); - Ptr += sizeof (PERF_DATA); - - mPerfHeader.Count++; - if (mPerfHeader.Count == LimitCount) { - goto Done; - } - } - } - -Done: - - FreePool (Handles); - - mPerfHeader.Signiture = PERFORMANCE_SIGNATURE; - - // - // Put performance data to Reserved memory - // - CopyMem ( - (UINTN *) (UINTN) mAcpiLowMemoryBase, - &mPerfHeader, - sizeof (PERF_HEADER) - ); - - return ; -} diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c deleted file mode 100644 index 762871605d..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c +++ /dev/null @@ -1,32 +0,0 @@ -/** @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/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h b/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h deleted file mode 100644 index 13b745de87..0000000000 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h +++ /dev/null @@ -1,48 +0,0 @@ -/** @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/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c b/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c deleted file mode 100644 index bb320f37b2..0000000000 --- a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c +++ /dev/null @@ -1,1456 +0,0 @@ -/** @file - Legacy Boot Maintainence UI implementation. - -Copyright (c) 2004 - 2015, Intel 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 "LegacyBootMaintUi.h" - -LEGACY_BOOT_OPTION_CALLBACK_DATA *mLegacyBootOptionPrivate; -EFI_GUID mLegacyBootOptionGuid = LEGACY_BOOT_OPTION_FORMSET_GUID; -CHAR16 mLegacyBootStorageName[] = L"LegacyBootData"; -BBS_TYPE mBbsType[] = {BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM, BBS_EMBED_NETWORK, BBS_BEV_DEVICE, BBS_UNKNOWN}; - - -/// -/// Legacy FD Info from LegacyBios.GetBbsInfo() -/// -LEGACY_MENU_OPTION LegacyFDMenu = { - LEGACY_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy HD Info from LegacyBios.GetBbsInfo() -/// -LEGACY_MENU_OPTION LegacyHDMenu = { - LEGACY_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy CD Info from LegacyBios.GetBbsInfo() -/// -LEGACY_MENU_OPTION LegacyCDMenu = { - LEGACY_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy NET Info from LegacyBios.GetBbsInfo() -/// -LEGACY_MENU_OPTION LegacyNETMenu = { - LEGACY_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy NET Info from LegacyBios.GetBbsInfo() -/// -LEGACY_MENU_OPTION LegacyBEVMenu = { - LEGACY_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - - -VOID *mLegacyStartOpCodeHandle = NULL; -VOID *mLegacyEndOpCodeHandle = NULL; -EFI_IFR_GUID_LABEL *mLegacyStartLabel = NULL; -EFI_IFR_GUID_LABEL *mLegacyEndLabel = NULL; - - -HII_VENDOR_DEVICE_PATH mLegacyBootOptionHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - { 0x6bc75598, 0x89b4, 0x483d, { 0x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x35, 0x31 } } - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - (UINT8) (END_DEVICE_PATH_LENGTH), - (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) - } - } -}; - - -/** - Re-order the Boot Option according to the DevOrder. - - The routine re-orders the Boot Option in BootOption array according to - the order specified by DevOrder. - - @param DevOrder Pointer to buffer containing the BBS Index, - high 8-bit value 0xFF indicating a disabled boot option - @param DevOrderCount Count of the BBS Index - @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers - @param EnBootOptionCount Count of the enabled Boot Option Numbers - @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers - @param DisBootOptionCount Count of the disabled Boot Option Numbers -**/ -VOID -OrderLegacyBootOption4SameType ( - UINT16 *DevOrder, - UINTN DevOrderCount, - UINT16 **EnBootOption, - UINTN *EnBootOptionCount, - UINT16 **DisBootOption, - UINTN *DisBootOptionCount - ) -{ - EFI_STATUS Status; - UINT16 *NewBootOption; - UINT16 *BootOrder; - UINTN BootOrderSize; - UINTN Index; - UINTN StartPosition; - - EFI_BOOT_MANAGER_LOAD_OPTION BootOption; - - CHAR16 OptionName[sizeof ("Boot####")]; - UINT16 *BbsIndexArray; - UINT16 *DeviceTypeArray; - - GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize); - ASSERT (BootOrder != NULL); - - BbsIndexArray = AllocatePool (BootOrderSize); - DeviceTypeArray = AllocatePool (BootOrderSize); - *EnBootOption = AllocatePool (BootOrderSize); - *DisBootOption = AllocatePool (BootOrderSize); - *DisBootOptionCount = 0; - *EnBootOptionCount = 0; - Index = 0; - - ASSERT (BbsIndexArray != NULL); - ASSERT (DeviceTypeArray != NULL); - ASSERT (*EnBootOption != NULL); - ASSERT (*DisBootOption != NULL); - - for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { - - UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); - Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption); - ASSERT_EFI_ERROR (Status); - - if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) && - (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) { - // - // Legacy Boot Option - // - ASSERT (BootOption.OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); - - DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType; - BbsIndexArray [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption.OptionalData)->BbsIndex; - } else { - DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN; - BbsIndexArray [Index] = 0xFFFF; - } - EfiBootManagerFreeLoadOption (&BootOption); - } - - // - // Record the corresponding Boot Option Numbers according to the DevOrder - // Record the EnBootOption and DisBootOption according to the DevOrder - // - StartPosition = BootOrderSize / sizeof (UINT16); - NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16)); - ASSERT (NewBootOption != NULL); - while (DevOrderCount-- != 0) { - for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { - if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) { - StartPosition = MIN (StartPosition, Index); - NewBootOption[DevOrderCount] = BootOrder[Index]; - - if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) { - (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index]; - (*DisBootOptionCount)++; - } else { - (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index]; - (*EnBootOptionCount)++; - } - break; - } - } - } - - // - // Overwrite the old BootOption - // - CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16)); - Status = gRT->SetVariable ( - L"BootOrder", - &gEfiGlobalVariableGuid, - VAR_FLAG, - BootOrderSize, - BootOrder - ); - ASSERT_EFI_ERROR (Status); - - FreePool (NewBootOption); - FreePool (DeviceTypeArray); - FreePool (BbsIndexArray); -} - -/** - Update the legacy BBS boot option. L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable - is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid - is also updated. - - @param NVMapData The data for egacy BBS boot. - - @return EFI_SUCCESS The function completed successfully. - @retval EFI_NOT_FOUND If L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable can be found. - @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource -**/ -EFI_STATUS -UpdateBBSOption ( - IN LEGACY_BOOT_NV_DATA *NVMapData - ) -{ - UINTN Index; - UINTN Index2; - UINTN CurrentType; - VOID *BootOptionVar; - CHAR16 VarName[100]; - UINTN OptionSize; - EFI_STATUS Status; - UINT32 *Attribute; - LEGACY_MENU_OPTION *OptionMenu; - UINT16 *LegacyDev; - UINT16 *InitialLegacyDev; - UINT8 *VarData; - UINTN VarSize; - LEGACY_DEV_ORDER_ENTRY *DevOrder; - UINT8 *OriginalPtr; - UINT8 *DisMap; - UINTN Pos; - UINTN Bit; - UINT16 *NewOrder; - UINT16 Tmp; - UINT16 *EnBootOption; - UINTN EnBootOptionCount; - UINT16 *DisBootOption; - UINTN DisBootOptionCount; - UINTN BufferSize; - - - DisMap = NULL; - NewOrder = NULL; - CurrentType = 0; - - - DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap; - Status = EFI_SUCCESS; - - // - // Update the Variable "LegacyDevOrder" - // - GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize); - if (VarData == NULL) { - return EFI_NOT_FOUND; - } - OriginalPtr = VarData; - - while (mBbsType[CurrentType] != BBS_UNKNOWN) { - switch (mBbsType[CurrentType]) { - case BBS_FLOPPY: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu; - LegacyDev = NVMapData->LegacyFD; - InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD; - BufferSize = sizeof (NVMapData->LegacyFD); - break; - - case BBS_HARDDISK: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu; - LegacyDev = NVMapData->LegacyHD; - InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD; - - BufferSize = sizeof (NVMapData->LegacyHD); - break; - - case BBS_CDROM: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu; - LegacyDev = NVMapData->LegacyCD; - InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD; - BufferSize = sizeof (NVMapData->LegacyCD); - break; - - case BBS_EMBED_NETWORK: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu; - LegacyDev = NVMapData->LegacyNET; - InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET; - BufferSize = sizeof (NVMapData->LegacyNET); - break; - - default: - ASSERT (mBbsType[CurrentType] == BBS_BEV_DEVICE); - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu; - LegacyDev = NVMapData->LegacyBEV; - InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV; - BufferSize = sizeof (NVMapData->LegacyBEV); - break; - } - - // - // Check whether has value changed. - // - if (CompareMem (LegacyDev, InitialLegacyDev, BufferSize) == 0) { - CurrentType++; - continue; - } - - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) OriginalPtr; - while (VarData < OriginalPtr + VarSize) { - if (DevOrder->BbsType == mBbsType[CurrentType]) { - break; - } - - VarData += sizeof (BBS_TYPE) + DevOrder->Length; - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; - } - - if (VarData >= OriginalPtr + VarSize) { - FreePool (OriginalPtr); - return EFI_NOT_FOUND; - } - - NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length)); - if (NewOrder == NULL) { - FreePool (OriginalPtr); - return EFI_OUT_OF_RESOURCES; - } - - for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { - if (0xFF == LegacyDev[Index]) { - break; - } - - NewOrder[Index] = LegacyDev[Index]; - } - - // - // Only the enable/disable state of each boot device with same device type can be changed, - // so we can count on the index information in DevOrder. - // DisMap bit array is the only reliable source to check a device's en/dis state, - // so we use DisMap to set en/dis state of each item in NewOrder array - // - for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) { - Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF); - Pos = Tmp / 8; - Bit = 7 - (Tmp % 8); - if ((DisMap[Pos] & (1 << Bit)) != 0) { - NewOrder[Index] = (UINT16) (0xFF00 | Tmp); - Index++; - } - } - - CopyMem ( - DevOrder->Data, - NewOrder, - DevOrder->Length - sizeof (DevOrder->Length) - ); - FreePool (NewOrder); - - // - // Update BootOrder and Boot####.Attribute - // - // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order - // - ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1); - - OrderLegacyBootOption4SameType ( - DevOrder->Data, - DevOrder->Length / sizeof (UINT16) - 1, - &EnBootOption, - &EnBootOptionCount, - &DisBootOption, - &DisBootOptionCount - ); - - // - // 2. Deactivate the DisBootOption and activate the EnBootOption - // - for (Index = 0; Index < DisBootOptionCount; Index++) { - UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]); - GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize); - if (BootOptionVar != NULL) { - Attribute = (UINT32 *) BootOptionVar; - *Attribute &= ~LOAD_OPTION_ACTIVE; - - Status = gRT->SetVariable ( - VarName, - &gEfiGlobalVariableGuid, - VAR_FLAG, - OptionSize, - BootOptionVar - ); - - FreePool (BootOptionVar); - } - } - - for (Index = 0; Index < EnBootOptionCount; Index++) { - UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]); - GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize); - if (BootOptionVar != NULL) { - Attribute = (UINT32 *) BootOptionVar; - *Attribute |= LOAD_OPTION_ACTIVE; - - Status = gRT->SetVariable ( - VarName, - &gEfiGlobalVariableGuid, - VAR_FLAG, - OptionSize, - BootOptionVar - ); - - FreePool (BootOptionVar); - } - } - - - FreePool (EnBootOption); - FreePool (DisBootOption); - - CurrentType++; - } - - Status = gRT->SetVariable ( - VAR_LEGACY_DEV_ORDER, - &gEfiLegacyDevOrderVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, - VarSize, - OriginalPtr - ); - - FreePool (OriginalPtr); - return Status; -} - -/** - 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 illegal syntax, or unknown name. - @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. - -**/ -EFI_STATUS -EFIAPI -LegacyBootOptionExtractConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Request, - OUT EFI_STRING *Progress, - OUT EFI_STRING *Results - ) -{ - if (Progress == NULL || Results == NULL) { - return EFI_INVALID_PARAMETER; - } - *Progress = Request; - return EFI_NOT_FOUND; -} - -/** - 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 -LegacyBootOptionRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ) -{ - EFI_STATUS Status; - EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; - LEGACY_BOOT_NV_DATA *CurrentNVMapData; - UINTN BufferSize; - - - if (Configuration == NULL || Progress == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check routing data in . - // Note: there is no name for Name/Value storage, only GUID will be checked - // - if (!HiiIsConfigHdrMatch (Configuration, &mLegacyBootOptionGuid, mLegacyBootStorageName)) { - return EFI_NOT_FOUND; - } - - Status = gBS->LocateProtocol ( - &gEfiHiiConfigRoutingProtocolGuid, - NULL, - (VOID **) &ConfigRouting - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Convert to buffer data by helper function ConfigToBlock() - // - CurrentNVMapData = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData; - Status = ConfigRouting->ConfigToBlock ( - ConfigRouting, - Configuration, - (UINT8 *) CurrentNVMapData, - &BufferSize, - Progress - ); - ASSERT_EFI_ERROR (Status); - - Status = UpdateBBSOption (CurrentNVMapData); - - return Status; -} - -/** - Refresh the global UpdateData structure. - -**/ -VOID -RefreshLegacyUpdateData ( - VOID - ) -{ - // - // Free current updated date - // - if (mLegacyStartOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (mLegacyStartOpCodeHandle); - } - if (mLegacyEndOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (mLegacyEndOpCodeHandle); - } - - // - // Create new OpCode Handle - // - mLegacyStartOpCodeHandle = HiiAllocateOpCodeHandle (); - mLegacyEndOpCodeHandle = HiiAllocateOpCodeHandle (); - - // - // Create Hii Extend Label OpCode as the start opcode - // - mLegacyStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( - mLegacyStartOpCodeHandle, - &gEfiIfrTianoGuid, - NULL, - sizeof (EFI_IFR_GUID_LABEL) - ); - mLegacyStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - - mLegacyStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID; - - // - // Create Hii Extend Label OpCode as the start opcode - // - mLegacyEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( - mLegacyEndOpCodeHandle, - &gEfiIfrTianoGuid, - NULL, - sizeof (EFI_IFR_GUID_LABEL) - ); - mLegacyEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - - mLegacyEndLabel->Number = FORM_BOOT_LEGACY_LABEL_END; - -} - -/** - Get the Menu Entry from the list in Menu Entry List. - - If MenuNumber is great or equal to the number of Menu - Entry in the list, then ASSERT. - - @param MenuOption The Menu Entry List to read the menu entry. - @param MenuNumber The index of Menu Entry. - - @return The Menu Entry. - -**/ -LEGACY_MENU_ENTRY * -GetMenuEntry ( - LEGACY_MENU_OPTION *MenuOption, - UINTN MenuNumber - ) -{ - LEGACY_MENU_ENTRY *NewMenuEntry; - UINTN Index; - LIST_ENTRY *List; - - ASSERT (MenuNumber < MenuOption->MenuNumber); - - List = MenuOption->Head.ForwardLink; - for (Index = 0; Index < MenuNumber; Index++) { - List = List->ForwardLink; - } - - NewMenuEntry = CR (List, LEGACY_MENU_ENTRY, Link, LEGACY_MENU_ENTRY_SIGNATURE); - - return NewMenuEntry; -} - -/** - Create string tokens for a menu from its help strings and display strings - - @param HiiHandle Hii Handle of the package to be updated. - @param MenuOption The Menu whose string tokens need to be created - -**/ -VOID -CreateLegacyMenuStringToken ( - IN EFI_HII_HANDLE HiiHandle, - IN LEGACY_MENU_OPTION *MenuOption - ) -{ - LEGACY_MENU_ENTRY *NewMenuEntry; - UINTN Index; - - for (Index = 0; Index < MenuOption->MenuNumber; Index++) { - NewMenuEntry = GetMenuEntry (MenuOption, Index); - - NewMenuEntry->DisplayStringToken = HiiSetString ( - HiiHandle, - 0, - NewMenuEntry->DisplayString, - NULL - ); - - if (NULL == NewMenuEntry->HelpString) { - NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; - } else { - NewMenuEntry->HelpStringToken = HiiSetString ( - HiiHandle, - 0, - NewMenuEntry->HelpString, - NULL - ); - } - } -} - -/** - Create a dynamic page so that Legacy Device boot order - can be set for specified device type. - - @param UpdatePageId The form ID. It also spefies the legacy device type. - - -**/ -VOID -UpdateLegacyDeviceOrderPage ( - IN UINT16 UpdatePageId - ) -{ - LEGACY_MENU_OPTION *OptionMenu; - LEGACY_MENU_ENTRY *NewMenuEntry; - EFI_STRING_ID StrRef; - EFI_STRING_ID StrRefHelp; - UINT16 *Default; - UINT16 Index; - UINT16 Key; - CHAR16 String[100]; - CHAR16 *TypeStr; - CHAR16 *TypeStrHelp; - CHAR16 *FormTitle; - VOID *OptionsOpCodeHandle; - VOID *DefaultOpCodeHandle; - - Key = 0; - StrRef = 0; - StrRefHelp = 0; - OptionMenu = NULL; - TypeStr = NULL; - TypeStrHelp = NULL; - Default = NULL; - - RefreshLegacyUpdateData(); - - // - // Create oneof option list - // - switch (UpdatePageId) { - case FORM_FLOPPY_BOOT_ID: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu; - Key = (UINT16) LEGACY_FD_QUESTION_ID; - TypeStr = STR_FLOPPY; - TypeStrHelp = STR_FLOPPY_HELP; - FormTitle = STR_FLOPPY_TITLE; - Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyFD; - break; - - case FORM_HARDDISK_BOOT_ID: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu; - Key = (UINT16) LEGACY_HD_QUESTION_ID; - TypeStr = STR_HARDDISK; - TypeStrHelp = STR_HARDDISK_HELP; - FormTitle = STR_HARDDISK_TITLE; - Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyHD; - break; - - case FORM_CDROM_BOOT_ID: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu; - Key = (UINT16) LEGACY_CD_QUESTION_ID; - TypeStr = STR_CDROM; - TypeStrHelp = STR_CDROM_HELP; - FormTitle = STR_CDROM_TITLE; - Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyCD; - break; - - case FORM_NET_BOOT_ID: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu; - Key = (UINT16) LEGACY_NET_QUESTION_ID; - TypeStr = STR_NET; - TypeStrHelp = STR_NET_HELP; - FormTitle = STR_NET_TITLE; - Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyNET; - break; - - case FORM_BEV_BOOT_ID: - OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu; - Key = (UINT16) LEGACY_BEV_QUESTION_ID; - TypeStr = STR_BEV; - TypeStrHelp = STR_BEV_HELP; - FormTitle = STR_BEV_TITLE; - Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyBEV; - break; - - default: - DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n")); - return; - } - - HiiSetString (mLegacyBootOptionPrivate->HiiHandle, STRING_TOKEN(STR_ORDER_CHANGE_PROMPT), FormTitle, NULL); - - CreateLegacyMenuStringToken (mLegacyBootOptionPrivate->HiiHandle, OptionMenu); - - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - - for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { - NewMenuEntry = GetMenuEntry (OptionMenu, Index); - // - // Create OneOf for each legacy device - // - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - NewMenuEntry->DisplayStringToken, - 0, - EFI_IFR_TYPE_NUM_SIZE_16, - ((LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex - ); - } - - // - // Create OneOf for item "Disabled" - // - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE), - 0, - EFI_IFR_TYPE_NUM_SIZE_16, - 0xFF - ); - - // - // Create oneof tag here for FD/HD/CD #1 #2 - // - for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { - DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (DefaultOpCodeHandle != NULL); - - HiiCreateDefaultOpCode ( - DefaultOpCodeHandle, - EFI_HII_DEFAULT_CLASS_STANDARD, - EFI_IFR_TYPE_NUM_SIZE_16, - *Default++ - ); - - // - // Create the string for oneof tag - // - UnicodeSPrint (String, sizeof (String), TypeStr, Index); - StrRef = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL); - - UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index); - StrRefHelp = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL); - - HiiCreateOneOfOpCode ( - mLegacyStartOpCodeHandle, - (EFI_QUESTION_ID) (Key + Index), - VARSTORE_ID_LEGACY_BOOT, - (UINT16) (Key + Index * 2 - CONFIG_OPTION_OFFSET), - StrRef, - StrRefHelp, - EFI_IFR_FLAG_CALLBACK, - EFI_IFR_NUMERIC_SIZE_2, - OptionsOpCodeHandle, - DefaultOpCodeHandle //NULL // - ); - - HiiFreeOpCodeHandle (DefaultOpCodeHandle); - } - - HiiUpdateForm ( - mLegacyBootOptionPrivate->HiiHandle, - &mLegacyBootOptionGuid, - LEGACY_ORDER_CHANGE_FORM_ID, - mLegacyStartOpCodeHandle, - mLegacyEndOpCodeHandle - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); -} - - -/** - Adjust question value when one question value has been changed. - - @param QuestionId The question id for the value changed question. - @param Value The value for the changed question. - -**/ -VOID -AdjustOptionValue ( - IN UINT16 QuestionId, - IN EFI_IFR_TYPE_VALUE *Value - ) -{ - UINTN Number; - UINT16 *Default; - LEGACY_BOOT_NV_DATA *CurrentNVMap; - UINT16 *CurrentVal; - UINTN Index; - UINTN Index2; - UINTN Index3; - UINTN NewValuePos; - UINTN OldValue; - UINTN NewValue; - UINT8 *DisMap; - UINTN Pos; - UINTN Bit; - - Number = 0; - CurrentVal = 0; - Default = NULL; - NewValue = 0; - NewValuePos = 0; - OldValue = 0; - - // - // Update Select FD/HD/CD/NET/BEV Order Form - // - ASSERT ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)); - - CurrentNVMap = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData; - HiiGetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap); - DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap; - - if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyFDMenu.MenuNumber; - CurrentVal = CurrentNVMap->LegacyFD; - Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyFD; - } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyHDMenu.MenuNumber; - CurrentVal = CurrentNVMap->LegacyHD; - Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyHD; - } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyCDMenu.MenuNumber; - CurrentVal = CurrentNVMap->LegacyCD; - Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyCD; - } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyNETMenu.MenuNumber; - CurrentVal = CurrentNVMap->LegacyNET; - Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyNET; - } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyBEVMenu.MenuNumber; - CurrentVal = CurrentNVMap->LegacyBEV; - Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyBEV; - } - - // - // First, find the different position - // if there is change, it should be only one - // - for (Index = 0; Index < Number; Index++) { - if (CurrentVal[Index] != Default[Index]) { - OldValue = Default[Index]; - NewValue = CurrentVal[Index]; - break; - } - } - - if (Index != Number) { - // - // there is change, now process - // - if (0xFF == NewValue) { - // - // This item will be disable - // Just move the items behind this forward to overlap it - // - Pos = OldValue / 8; - Bit = 7 - (OldValue % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); - for (Index2 = Index; Index2 < Number - 1; Index2++) { - CurrentVal[Index2] = CurrentVal[Index2 + 1]; - } - - CurrentVal[Index2] = 0xFF; - } else { - for (Index2 = 0; Index2 < Number; Index2++) { - if (Index2 == Index) { - continue; - } - - if (Default[Index2] == NewValue) { - // - // If NewValue is in OldLegacyDev array - // remember its old position - // - NewValuePos = Index2; - break; - } - } - - if (Index2 != Number) { - // - // We will change current item to an existing item - // (It's hard to describe here, please read code, it's like a cycle-moving) - // - for (Index2 = NewValuePos; Index2 != Index;) { - if (NewValuePos < Index) { - CurrentVal[Index2] = Default[Index2 + 1]; - Index2++; - } else { - CurrentVal[Index2] = Default[Index2 - 1]; - Index2--; - } - } - } else { - // - // If NewValue is not in OldlegacyDev array, we are changing to a disabled item - // so we should modify DisMap to reflect the change - // - Pos = NewValue / 8; - Bit = 7 - (NewValue % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); - if (0xFF != OldValue) { - // - // Because NewValue is a item that was disabled before - // so after changing the OldValue should be disabled - // actually we are doing a swap of enable-disable states of two items - // - Pos = OldValue / 8; - Bit = 7 - (OldValue % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); - } - } - } - // - // To prevent DISABLE appears in the middle of the list - // we should perform a re-ordering - // - Index3 = Index; - Index = 0; - while (Index < Number) { - if (0xFF != CurrentVal[Index]) { - Index++; - continue; - } - - Index2 = Index; - Index2++; - while (Index2 < Number) { - if (0xFF != CurrentVal[Index2]) { - break; - } - - Index2++; - } - - if (Index2 < Number) { - CurrentVal[Index] = CurrentVal[Index2]; - CurrentVal[Index2] = 0xFF; - } - - Index++; - } - - // - // Return correct question value. - // - Value->u16 = CurrentVal[Index3]; - CopyMem (Default, CurrentVal, sizeof (UINT16) * Number); - } - - // - // Pass changed uncommitted data back to Form Browser - // - HiiSetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap, NULL); -} - -/** - This call back function is registered with Boot Manager formset. - When user selects a boot option, this call back function will - be triggered. The boot option is saved for later processing. - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. - -**/ -EFI_STATUS -EFIAPI -LegacyBootOptionCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - if (Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_CHANGING) { - // - // Do nothing for other UEFI Action. Only do call back when data is changed. - // - return EFI_UNSUPPORTED; - } - - if ((Value == NULL) || (ActionRequest == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if (Action == EFI_BROWSER_ACTION_CHANGING) { - switch (QuestionId) { - case FORM_FLOPPY_BOOT_ID: - case FORM_HARDDISK_BOOT_ID: - case FORM_CDROM_BOOT_ID: - case FORM_NET_BOOT_ID: - case FORM_BEV_BOOT_ID: - UpdateLegacyDeviceOrderPage (QuestionId); - break; - - default: - break; - } - } else if (Action == EFI_BROWSER_ACTION_CHANGED) { - if ((Value == NULL) || (ActionRequest == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) { - AdjustOptionValue(QuestionId, Value); - } - } - return EFI_SUCCESS; -} - - -/** - Create a menu entry by given menu type. - - @param MenuType The Menu type to be created. - - @retval NULL If failed to create the menu. - @return the new menu entry. - -**/ -LEGACY_MENU_ENTRY * -CreateMenuEntry ( - VOID - ) -{ - LEGACY_MENU_ENTRY *MenuEntry; - - // - // Create new menu entry - // - MenuEntry = AllocateZeroPool (sizeof (LEGACY_MENU_ENTRY)); - if (MenuEntry == NULL) { - return NULL; - } - - MenuEntry->VariableContext = AllocateZeroPool (sizeof (LEGACY_DEVICE_CONTEXT)); - if (MenuEntry->VariableContext == NULL) { - FreePool (MenuEntry); - return NULL; - } - - MenuEntry->Signature = LEGACY_MENU_ENTRY_SIGNATURE; - return MenuEntry; -} - -/** - - Base on the L"LegacyDevOrder" variable to build the current order data. - -**/ -VOID -GetLegacyOptionsOrder ( - VOID - ) -{ - UINTN VarSize; - UINT8 *VarData; - UINT8 *VarTmp; - LEGACY_DEV_ORDER_ENTRY *DevOrder; - UINT16 *LegacyDev; - UINTN Index; - LEGACY_MENU_OPTION *OptionMenu; - UINT16 VarDevOrder; - UINTN Pos; - UINTN Bit; - UINT8 *DisMap; - UINTN TotalLength; - - LegacyDev = NULL; - OptionMenu = NULL; - - DisMap = ZeroMem (mLegacyBootOptionPrivate->MaintainMapData->DisableMap, sizeof (mLegacyBootOptionPrivate->MaintainMapData->DisableMap)); - - // - // Get Device Order from variable - // - GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize); - VarTmp = VarData; - if (NULL != VarData) { - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; - while (VarData < VarTmp + VarSize) { - switch (DevOrder->BbsType) { - case BBS_FLOPPY: - LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD; - OptionMenu = &LegacyFDMenu; - break; - - case BBS_HARDDISK: - LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD; - OptionMenu = &LegacyHDMenu; - break; - - case BBS_CDROM: - LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD; - OptionMenu = &LegacyCDMenu; - break; - - case BBS_EMBED_NETWORK: - LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET; - OptionMenu = &LegacyNETMenu; - break; - - case BBS_BEV_DEVICE: - LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV; - OptionMenu = &LegacyBEVMenu; - break; - - case BBS_UNKNOWN: - default: - ASSERT (FALSE); - DEBUG ((DEBUG_ERROR, "Unsupported device type found!\n")); - break; - } - - // - // Create oneof tag here for FD/HD/CD #1 #2 - // - for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { - TotalLength = sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16); - VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + TotalLength); - - if (0xFF00 == (VarDevOrder & 0xFF00)) { - LegacyDev[Index] = 0xFF; - Pos = (VarDevOrder & 0xFF) / 8; - Bit = 7 - ((VarDevOrder & 0xFF) % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); - } else { - LegacyDev[Index] = VarDevOrder & 0xFF; - } - } - - VarData ++; - VarData += *(UINT16 *) VarData; - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; - } - } - - CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA)); - CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA)); -} - -/** - - Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). - -**/ -VOID -GetLegacyOptions ( - VOID - ) -{ - LEGACY_MENU_ENTRY *NewMenuEntry; - LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; - EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; - UINTN BootOptionCount; - UINT16 Index; - UINTN FDNum; - UINTN HDNum; - UINTN CDNum; - UINTN NETNum; - UINTN BEVNum; - - // - // Initialize Bbs Table Context from BBS info data - // - InitializeListHead (&LegacyFDMenu.Head); - InitializeListHead (&LegacyHDMenu.Head); - InitializeListHead (&LegacyCDMenu.Head); - InitializeListHead (&LegacyNETMenu.Head); - InitializeListHead (&LegacyBEVMenu.Head); - - FDNum = 0; - HDNum = 0; - CDNum = 0; - NETNum = 0; - BEVNum = 0; - - EfiBootManagerConnectAll (); - - // - // for better user experience - // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option - // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option - // - EfiBootManagerRefreshAllBootOption (); - - BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); - for (Index = 0; Index < BootOptionCount; Index++) { - if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) || - (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP) - ) { - continue; - } - ASSERT (BootOption[Index].OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); - NewMenuEntry = CreateMenuEntry (); - ASSERT (NewMenuEntry != NULL); - - NewLegacyDevContext = (LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; - NewLegacyDevContext->BbsIndex = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex; - NewLegacyDevContext->Description = AllocateCopyPool (StrSize (BootOption[Index].Description), BootOption[Index].Description); - ASSERT (NewLegacyDevContext->Description != NULL); - - NewMenuEntry->DisplayString = NewLegacyDevContext->Description; - NewMenuEntry->HelpString = NULL; - - switch (((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) { - case BBS_TYPE_FLOPPY: - InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); - FDNum++; - break; - - case BBS_TYPE_HARDDRIVE: - InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); - HDNum++; - break; - - case BBS_TYPE_CDROM: - InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); - CDNum++; - break; - - case BBS_TYPE_EMBEDDED_NETWORK: - InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); - NETNum++; - break; - - case BBS_TYPE_BEV: - InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); - BEVNum++; - break; - } - } - - EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); - - LegacyFDMenu.MenuNumber = FDNum; - LegacyHDMenu.MenuNumber = HDNum; - LegacyCDMenu.MenuNumber = CDNum; - LegacyNETMenu.MenuNumber = NETNum; - LegacyBEVMenu.MenuNumber = BEVNum; -} - - -/** - - Install Boot Manager Menu driver. - - @param ImageHandle The image handle. - @param SystemTable The system table. - - @retval EFI_SUCEESS Install Boot manager menu success. - @retval Other Return error status. - -**/ -EFI_STATUS -EFIAPI -LegacyBootMaintUiLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - LEGACY_BOOT_OPTION_CALLBACK_DATA *LegacyBootOptionData; - - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (!EFI_ERROR (Status)) { - // - // Create LegacyBootOptionData structures for Driver Callback - // - LegacyBootOptionData = AllocateZeroPool (sizeof (LEGACY_BOOT_OPTION_CALLBACK_DATA)); - ASSERT (LegacyBootOptionData != NULL); - - LegacyBootOptionData->MaintainMapData = AllocateZeroPool (sizeof (LEGACY_BOOT_MAINTAIN_DATA)); - ASSERT (LegacyBootOptionData->MaintainMapData != NULL); - - LegacyBootOptionData->ConfigAccess.ExtractConfig = LegacyBootOptionExtractConfig; - LegacyBootOptionData->ConfigAccess.RouteConfig = LegacyBootOptionRouteConfig; - LegacyBootOptionData->ConfigAccess.Callback = LegacyBootOptionCallback; - - // - // Install Device Path Protocol and Config Access protocol to driver handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &LegacyBootOptionData->DriverHandle, - &gEfiDevicePathProtocolGuid, - &mLegacyBootOptionHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &LegacyBootOptionData->ConfigAccess, - NULL - ); - ASSERT_EFI_ERROR (Status); - - // - // Publish our HII data - // - LegacyBootOptionData->HiiHandle = HiiAddPackages ( - &mLegacyBootOptionGuid, - LegacyBootOptionData->DriverHandle, - LegacyBootMaintUiVfrBin, - LegacyBootMaintUiLibStrings, - NULL - ); - ASSERT (LegacyBootOptionData->HiiHandle != NULL); - - mLegacyBootOptionPrivate = LegacyBootOptionData; - - GetLegacyOptions (); - - GetLegacyOptionsOrder(); - } - - return EFI_SUCCESS; -} - -/** - Destructor of Customized Display Library Instance. - - @param ImageHandle The firmware allocated handle for the EFI image. - @param SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The destructor completed successfully. - @retval Other value The destructor did not complete successfully. - -**/ -EFI_STATUS -EFIAPI -LegacyBootMaintUiLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - if (mLegacyBootOptionPrivate->DriverHandle != NULL) { - Status = gBS->UninstallMultipleProtocolInterfaces ( - mLegacyBootOptionPrivate->DriverHandle, - &gEfiDevicePathProtocolGuid, - &mLegacyBootOptionHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &mLegacyBootOptionPrivate->ConfigAccess, - NULL - ); - ASSERT_EFI_ERROR (Status); - - HiiRemovePackages (mLegacyBootOptionPrivate->HiiHandle); - - FreePool (mLegacyBootOptionPrivate->MaintainMapData); - FreePool (mLegacyBootOptionPrivate); - } - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.h b/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.h deleted file mode 100644 index 86ea8eba7a..0000000000 --- a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.h +++ /dev/null @@ -1,255 +0,0 @@ -/** @file - Legacy boot maintainence Ui definition. - -Copyright (c) 2004 - 2015, Intel 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 _EFI_LEGACY_BOOT_OPTION_H_ -#define _EFI_LEGACY_BOOT_OPTION_H_ - -#include - - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "LegacyBootMaintUiVfr.h" - -#define CONFIG_OPTION_OFFSET 0x1200 - -// -// VarOffset that will be used to create question -// all these values are computed from the structure -// defined below -// -#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((LEGACY_BOOT_NV_DATA *) 0)->Field))) - -// -// Question Id of Zero is invalid, so add an offset to it -// -#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET) - - -#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD) -#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD) -#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD) -#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET) -#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV) - - -// -// String Contant -// -#define STR_FLOPPY L"Floppy Drive #%02x" -#define STR_HARDDISK L"HardDisk Drive #%02x" -#define STR_CDROM L"ATAPI CDROM Drive #%02x" -#define STR_NET L"NET Drive #%02x" -#define STR_BEV L"BEV Drive #%02x" - -#define STR_FLOPPY_HELP L"Select Floppy Drive #%02x" -#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x" -#define STR_CDROM_HELP L"Select ATAPI CDROM Drive #%02x" -#define STR_NET_HELP L"NET Drive #%02x" -#define STR_BEV_HELP L"BEV Drive #%02x" - -#define STR_FLOPPY_TITLE L"Set Legacy Floppy Drive Order" -#define STR_HARDDISK_TITLE L"Set Legacy HardDisk Drive Order" -#define STR_CDROM_TITLE L"Set Legacy CDROM Drive Order" -#define STR_NET_TITLE L"Set Legacy NET Drive Order" -#define STR_BEV_TITLE L"Set Legacy BEV Drive Order" - -// -// These are the VFR compiler generated data representing our VFR data. -// -extern UINT8 LegacyBootMaintUiVfrBin[]; - -#pragma pack(1) - -/// -/// HII specific Vendor Device Path definition. -/// -typedef struct { - VENDOR_DEVICE_PATH VendorDevicePath; - EFI_DEVICE_PATH_PROTOCOL End; -} HII_VENDOR_DEVICE_PATH; - - - -// -// Variable created with this flag will be "Efi:...." -// -#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE - - -#define LEGACY_BOOT_OPTION_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('L', 'G', 'C', 'B') - -typedef struct { - UINTN Signature; - - // - // HII relative handles - // - EFI_HII_HANDLE HiiHandle; - EFI_HANDLE DriverHandle; - - // - // Produced protocols - // - EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; - - // - // Maintain the data. - // - LEGACY_BOOT_MAINTAIN_DATA *MaintainMapData; -} LEGACY_BOOT_OPTION_CALLBACK_DATA; - -// -// All of the signatures that will be used in list structure -// -#define LEGACY_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u') -#define LEGACY_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r') - -#define LEGACY_LEGACY_DEV_CONTEXT_SELECT 0x9 - -typedef struct { - UINTN Signature; - LIST_ENTRY Head; - UINTN MenuNumber; -} LEGACY_MENU_OPTION; - -typedef struct { - UINT16 BbsIndex; - CHAR16 *Description; -} LEGACY_DEVICE_CONTEXT; - -typedef struct { - UINTN Signature; - LIST_ENTRY Link; - UINTN OptionNumber; - UINT16 *DisplayString; - UINT16 *HelpString; - EFI_STRING_ID DisplayStringToken; - EFI_STRING_ID HelpStringToken; - VOID *VariableContext; -} LEGACY_MENU_ENTRY; - -typedef struct { - UINT16 BbsIndex; -} LEGACY_BOOT_OPTION_BBS_DATA; - -#pragma pack() - -/** - This call back function is registered with Boot Manager formset. - When user selects a boot option, this call back function will - be triggered. The boot option is saved for later processing. - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. - -**/ -EFI_STATUS -EFIAPI -LegacyBootOptionCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ); - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -LegacyBootOptionExtractConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Request, - OUT EFI_STRING *Progress, - OUT EFI_STRING *Results - ); - -/** - 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 -LegacyBootOptionRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ); - -#endif diff --git a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf b/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf deleted file mode 100644 index 17c9cac811..0000000000 --- a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf +++ /dev/null @@ -1,69 +0,0 @@ -## @file -# Legacy Boot Maintainence UI module is library for BDS phase. -# -# Copyright (c) 2015, Intel 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 = LegacyBootMaintUiLib - MODULE_UNI_FILE = LegacyBootMaintUiLib.uni - FILE_GUID = e6f7f038-3ed9-401a-af1f-5ea7bf644d34 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION - CONSTRUCTOR = LegacyBootMaintUiLibConstructor - DESTRUCTOR = LegacyBootMaintUiLibDestructor -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - LegacyBootMaintUiVfr.h - LegacyBootMaintUi.h - LegacyBootMaintUiVfr.Vfr - LegacyBootMaintUiStrings.uni - LegacyBootMaintUi.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - -[LibraryClasses] - DevicePathLib - BaseLib - UefiRuntimeServicesTableLib - UefiBootServicesTableLib - DebugLib - HiiLib - MemoryAllocationLib - UefiBootManagerLib - UefiLib - PrintLib - BaseMemoryLib - -[Guids] - gEfiIfrTianoGuid ## SOMETIMES_PRODUCES ## UNDEFINED # Extended IFR Guid Opcode - gEfiIfrBootMaintenanceGuid ## CONSUMES ## HII # BootMaint HII Package - gEfiLegacyDevOrderVariableGuid ## PRODUCES ## Variable:L"LegacyDevOrder" - -[Protocols] - gEfiHiiConfigAccessProtocolGuid ## PRODUCES - gEfiLegacyBiosProtocolGuid ## CONSUMES - gEfiHiiConfigRoutingProtocolGuid ## CONSUMES - -[Depex] - gEfiHiiDatabaseProtocolGuid - diff --git a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni b/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni deleted file mode 100644 index 892d6e218e..0000000000 Binary files a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni b/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni deleted file mode 100644 index dbec69bfd6..0000000000 Binary files a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr b/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr deleted file mode 100644 index 882da99f9e..0000000000 --- a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr +++ /dev/null @@ -1,73 +0,0 @@ -///** @file -// -// Browser formset. -// -// Copyright (c) 2015, Intel 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 "LegacyBootMaintUiVfr.h" - - -formset - guid = LEGACY_BOOT_OPTION_FORMSET_GUID, - title = STRING_TOKEN(STR_LEGACY_BOOT_PROMPT), - help = STRING_TOKEN(STR_LEGACY_BOOT_HELP), - classguid = EFI_IFR_BOOT_MAINTENANCE_GUID, - - varstore LEGACY_BOOT_NV_DATA, - varid = VARSTORE_ID_LEGACY_BOOT, - name = LegacyBootData, - guid = LEGACY_BOOT_OPTION_FORMSET_GUID; - - form formid = LEGACY_BOOT_FORM_ID, - title = STRING_TOKEN(STR_LEGACY_BOOT_PROMPT); - - goto LEGACY_ORDER_CHANGE_FORM_ID, - prompt = STRING_TOKEN(STR_FORM_FLOPPY_BOOT_TITLE), - help = STRING_TOKEN(STR_FORM_FLOPPY_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_FLOPPY_BOOT_ID; - - goto LEGACY_ORDER_CHANGE_FORM_ID, - prompt = STRING_TOKEN(STR_FORM_HARDDISK_BOOT_TITLE), - help = STRING_TOKEN(STR_FORM_HARDDISK_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_HARDDISK_BOOT_ID; - - goto LEGACY_ORDER_CHANGE_FORM_ID, - prompt = STRING_TOKEN(STR_FORM_CDROM_BOOT_TITLE), - help = STRING_TOKEN(STR_FORM_CDROM_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_CDROM_BOOT_ID; - - goto LEGACY_ORDER_CHANGE_FORM_ID, - prompt = STRING_TOKEN(STR_FORM_NET_BOOT_TITLE), - help = STRING_TOKEN(STR_FORM_NET_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_NET_BOOT_ID; - - goto LEGACY_ORDER_CHANGE_FORM_ID, - prompt = STRING_TOKEN(STR_FORM_BEV_BOOT_TITLE), - help = STRING_TOKEN(STR_FORM_BEV_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_BEV_BOOT_ID; - - endform; - - form formid = LEGACY_ORDER_CHANGE_FORM_ID, - title = STRING_TOKEN(STR_ORDER_CHANGE_PROMPT); - - label FORM_BOOT_LEGACY_DEVICE_ID; - label FORM_BOOT_LEGACY_LABEL_END; - - endform; - -endformset; diff --git a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h b/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h deleted file mode 100644 index 713ea4c640..0000000000 --- a/IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h +++ /dev/null @@ -1,85 +0,0 @@ -/** @file - Legacy Boot Maintainence UI definition. - -Copyright (c) 2004 - 2015, Intel 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 _EFI_LEGACY_BOOT_OPTION_VFR_H_ -#define _EFI_LEGACY_BOOT_OPTION_VFR_H_ - -#include - -#define MAX_MENU_NUMBER 100 - -#define LEGACY_BOOT_OPTION_FORMSET_GUID { 0x6bc75598, 0x89b4, 0x483d, { 0x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x35, 0x31 } } - -#define VARSTORE_ID_LEGACY_BOOT 0x0001 - - -#define LEGACY_BOOT_FORM_ID 0x1000 -#define LEGACY_ORDER_CHANGE_FORM_ID 0x1001 - - -#define FORM_FLOPPY_BOOT_ID 0x2000 -#define FORM_HARDDISK_BOOT_ID 0x2001 -#define FORM_CDROM_BOOT_ID 0x2002 -#define FORM_NET_BOOT_ID 0x2003 -#define FORM_BEV_BOOT_ID 0x2004 - - - -#define FORM_BOOT_LEGACY_DEVICE_ID 0x9000 -#define FORM_BOOT_LEGACY_LABEL_END 0x9001 - - -#pragma pack(1) - -/// -/// This is the structure that will be used to store the -/// question's current value. Use it at initialize time to -/// set default value for each question. When using at run -/// time, this map is returned by the callback function, -/// so dynamically changing the question's value will be -/// possible through this mechanism -/// -typedef struct { - // - // Legacy Device Order Selection Storage - // - UINT16 LegacyFD[MAX_MENU_NUMBER]; - UINT16 LegacyHD[MAX_MENU_NUMBER]; - UINT16 LegacyCD[MAX_MENU_NUMBER]; - UINT16 LegacyNET[MAX_MENU_NUMBER]; - UINT16 LegacyBEV[MAX_MENU_NUMBER]; -} LEGACY_BOOT_NV_DATA; - -/// -/// This is the structure that will be used to store the -/// question's current value. Use it at initialize time to -/// set default value for each question. When using at run -/// time, this map is returned by the callback function, -/// so dynamically changing the question's value will be -/// possible through this mechanism -/// -typedef struct { - // - // Legacy Device Order Selection Storage - // - LEGACY_BOOT_NV_DATA InitialNvData; - LEGACY_BOOT_NV_DATA CurrentNvData; - LEGACY_BOOT_NV_DATA LastTimeNvData; - UINT8 DisableMap[32]; -} LEGACY_BOOT_MAINTAIN_DATA; - -#pragma pack() - -#endif diff --git a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h b/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h deleted file mode 100644 index e7bdde9def..0000000000 --- a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h +++ /dev/null @@ -1,66 +0,0 @@ -/** @file - -Copyright (c) 2011 - 2015, Intel 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_LEGACY_BM_H_ -#define _INTERNAL_LEGACY_BM_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma pack(1) -typedef struct { - UINT16 BbsIndex; -} LEGACY_BM_BOOT_OPTION_BBS_DATA; -#pragma pack() - -/** - Boot the legacy system with the boot option. - - @param BootOption The legacy boot option which have BBS device path - On return, BootOption->Status contains the boot status. - EFI_UNSUPPORTED There is no legacybios protocol, do not support - legacy boot. - EFI_STATUS The status of LegacyBios->LegacyBoot (). -**/ -VOID -EFIAPI -LegacyBmBoot ( - IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption - ); - -/** - Refresh all legacy boot options. - -**/ -VOID -EFIAPI -LegacyBmRefreshAllBootOption ( - VOID - ); - -#endif // _INTERNAL_LEGACY_BM_H_ \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c b/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c deleted file mode 100644 index d3b48e8d0b..0000000000 --- a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c +++ /dev/null @@ -1,1536 +0,0 @@ -/** @file - This function deal with the legacy boot option, it create, delete - and manage the legacy boot option, all legacy boot option is getting from - the legacy BBS table. - -Copyright (c) 2011 - 2016, Intel 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 "InternalLegacyBm.h" - -#define LEGACY_BM_BOOT_DESCRIPTION_LENGTH 32 - -/** - Initialize legacy boot manager library by call EfiBootManagerRegisterLegacyBootSupport - function to export two function pointer. - - @param ImageHandle The image handle. - @param SystemTable The system table. - - @retval EFI_SUCCESS The legacy boot manager library is initialized correctly. - @return Other value if failed to initialize the legacy boot manager library. -**/ -EFI_STATUS -EFIAPI -LegacyBootManagerLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable -) -{ - EfiBootManagerRegisterLegacyBootSupport ( - LegacyBmRefreshAllBootOption, - LegacyBmBoot - ); - return EFI_SUCCESS; -} - -/** - Get the device type from the input legacy device path. - - @param DevicePath The legacy device path. - - @retval The legacy device type. -**/ -UINT16 -LegacyBmDeviceType ( - EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - ASSERT ((DevicePathType (DevicePath) == BBS_DEVICE_PATH) && - (DevicePathSubType (DevicePath) == BBS_BBS_DP)); - return ((BBS_BBS_DEVICE_PATH *) DevicePath)->DeviceType; -} - -/** - Validate the BbsEntry base on the Boot Priority info in the BbsEntry. - - @param BbsEntry The input bbs entry info. - - @retval TRUE The BbsEntry is valid. - @retval FALSE The BbsEntry is invalid. -**/ -BOOLEAN -LegacyBmValidBbsEntry ( - IN BBS_TABLE *BbsEntry - ) -{ - switch (BbsEntry->BootPriority) { - case BBS_IGNORE_ENTRY: - case BBS_DO_NOT_BOOT_FROM: - case BBS_LOWEST_PRIORITY: - return FALSE; - default: - return TRUE; - } -} - -/** - Build Legacy Device Name String according. - - @param CurBBSEntry BBS Table. - @param Index Index. - @param BufSize The buffer size. - @param BootString The output string. - -**/ -VOID -LegacyBmBuildLegacyDevNameString ( - IN BBS_TABLE *CurBBSEntry, - IN UINTN Index, - IN UINTN BufSize, - OUT CHAR16 *BootString - ) -{ - CHAR16 *Fmt; - CHAR16 *Type; - CHAR8 *StringDesc; - CHAR8 StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; - CHAR16 StringBufferU[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; - - 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 = (CHAR8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset); - if (NULL != StringDesc) { - // - // Only get fisrt 32 characters, this is suggested by BBS spec - // - CopyMem (StringBufferA, StringDesc, LEGACY_BM_BOOT_DESCRIPTION_LENGTH); - StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH] = 0; - AsciiStrToUnicodeStrS (StringBufferA, StringBufferU, sizeof (StringBufferU) / sizeof (StringBufferU[0])); - Fmt = L"%s"; - Type = StringBufferU; - } - - // - // 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); - } -} - -/** - Get the Bbs index for the input boot option. - - @param BootOption The input boot option info. - @param BbsTable The input Bbs table. - @param BbsCount The input total bbs entry number. - @param BbsIndexUsed The array shows how many BBS table indexs have been used. - - @retval The index for the input boot option. -**/ -UINT16 -LegacyBmFuzzyMatch ( - EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, - BBS_TABLE *BbsTable, - UINT16 BbsCount, - BOOLEAN *BbsIndexUsed - ) -{ - UINT16 Index; - LEGACY_BM_BOOT_OPTION_BBS_DATA *BbsData; - CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; - - BbsData = (LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData; - - // - // Directly check the BBS index stored in BootOption - // - if ((BbsData->BbsIndex < BbsCount) && - (LegacyBmDeviceType (BootOption->FilePath) == BbsTable[BbsData->BbsIndex].DeviceType)) { - LegacyBmBuildLegacyDevNameString ( - &BbsTable[BbsData->BbsIndex], - BbsData->BbsIndex, - sizeof (Description), - Description - ); - if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[BbsData->BbsIndex]) { - // - // If devices with the same description string are connected, - // the BbsIndex of the first device is returned for the other device also. - // So, check if the BbsIndex is already being used, before assigning the BbsIndex. - // - BbsIndexUsed[BbsData->BbsIndex] = TRUE; - return BbsData->BbsIndex; - } - } - - // - // BBS table could be changed (entry removed/moved) - // find the correct BBS index - // - for (Index = 0; Index < BbsCount; Index++) { - if (!LegacyBmValidBbsEntry (&BbsTable[Index]) || - (BbsTable[Index].DeviceType != LegacyBmDeviceType (BootOption->FilePath))) { - continue; - } - - LegacyBmBuildLegacyDevNameString ( - &BbsTable[Index], - Index, - sizeof (Description), - Description - ); - if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[Index]) { - // - // If devices with the same description string are connected, - // the BbsIndex of the first device is assigned for the other device also. - // So, check if the BbsIndex is already being used, before assigning the corrected BbsIndex. - // - break; - } - } - - // - // Add the corrected BbsIndex in the UsedBbsIndex Buffer - // - if (Index != BbsCount) { - BbsIndexUsed[Index] = TRUE; - } - - return Index; -} - -/** - - Update legacy device order base on the input info. - - @param LegacyDevOrder Legacy device order data buffer. - @param LegacyDevOrderSize Legacy device order data buffer size. - @param DeviceType Device type which need to check. - @param OldBbsIndex Old Bds Index. - @param NewBbsIndex New Bds Index, if it is -1,means remove this option. - -**/ -VOID -LegacyBmUpdateBbsIndex ( - LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder, - UINTN *LegacyDevOrderSize, - UINT16 DeviceType, - UINT16 OldBbsIndex, - UINT16 NewBbsIndex // Delete entry if -1 - ) -{ - LEGACY_DEV_ORDER_ENTRY *Entry; - UINTN Index; - - ASSERT (((LegacyDevOrder == NULL) && (*LegacyDevOrderSize == 0)) || - ((LegacyDevOrder != NULL) && (*LegacyDevOrderSize != 0)) - ); - - for (Entry = LegacyDevOrder; - Entry < (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) LegacyDevOrder + *LegacyDevOrderSize); - Entry = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) Entry + sizeof (BBS_TYPE) + Entry->Length) - ) { - if (Entry->BbsType == DeviceType) { - for (Index = 0; Index < Entry->Length / sizeof (UINT16) - 1; Index++) { - if (Entry->Data[Index] == OldBbsIndex) { - if (NewBbsIndex == (UINT16) -1) { - // - // Delete the old entry - // - CopyMem ( - &Entry->Data[Index], - &Entry->Data[Index + 1], - (UINT8 *) LegacyDevOrder + *LegacyDevOrderSize - (UINT8 *) &Entry->Data[Index + 1] - ); - Entry->Length -= sizeof (UINT16); - *LegacyDevOrderSize -= sizeof(UINT16); - } else { - Entry->Data[Index] = NewBbsIndex; - } - break; - } - } - break; - } - } -} - -/** - Delete all the legacy boot options. - - @retval EFI_SUCCESS All legacy boot options are deleted. -**/ -EFI_STATUS -LegacyBmDeleteAllBootOptions ( - VOID - ) -{ - EFI_STATUS Status; - UINTN Index; - EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; - UINTN BootOptionCount; - - BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); - for (Index = 0; Index < BootOptionCount; Index++) { - if ((DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) && - (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)) { - Status = EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType); - // - // Deleting variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } - } - - Status = gRT->SetVariable ( - VAR_LEGACY_DEV_ORDER, - &gEfiLegacyDevOrderVariableGuid, - 0, - 0, - NULL - ); - // - // Deleting variable with current variable implementation shouldn't fail. - // - ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND); - - return EFI_SUCCESS; -} - - -/** - 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 -LegacyBmDeleteAllInvalidBootOptions ( - VOID - ) -{ - EFI_STATUS Status; - UINT16 HddCount; - UINT16 BbsCount; - HDD_INFO *HddInfo; - BBS_TABLE *BbsTable; - UINT16 BbsIndex; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - UINTN Index; - EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; - UINTN BootOptionCount; - LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder; - UINTN LegacyDevOrderSize; - BOOLEAN *BbsIndexUsed; - - HddCount = 0; - BbsCount = 0; - HddInfo = NULL; - BbsTable = NULL; - - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = LegacyBios->GetBbsInfo ( - LegacyBios, - &HddCount, - &HddInfo, - &BbsCount, - &BbsTable - ); - if (EFI_ERROR (Status)) { - return Status; - } - - GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &LegacyDevOrder, &LegacyDevOrderSize); - - BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); - - BbsIndexUsed = AllocateZeroPool (BbsCount * sizeof (BOOLEAN)); - ASSERT (BbsIndexUsed != NULL); - - for (Index = 0; Index < BootOptionCount; Index++) { - // - // Skip non legacy boot option - // - if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) || - (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP)) { - continue; - } - - BbsIndex = LegacyBmFuzzyMatch (&BootOption[Index], BbsTable, BbsCount, BbsIndexUsed); - if (BbsIndex == BbsCount) { - DEBUG ((EFI_D_INFO, "[LegacyBds] Delete Boot Option Boot%04x: %s\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description)); - // - // Delete entry from LegacyDevOrder - // - LegacyBmUpdateBbsIndex ( - LegacyDevOrder, - &LegacyDevOrderSize, - LegacyBmDeviceType (BootOption[Index].FilePath), - ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, - (UINT16) -1 - ); - EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType); - } else { - if (((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex != BbsIndex) { - DEBUG ((EFI_D_INFO, "[LegacyBds] Update Boot Option Boot%04x: %s Bbs0x%04x->Bbs0x%04x\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description, - (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, (UINTN) BbsIndex)); - // - // Update the BBS index in LegacyDevOrder - // - LegacyBmUpdateBbsIndex ( - LegacyDevOrder, - &LegacyDevOrderSize, - LegacyBmDeviceType (BootOption[Index].FilePath), - ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, - BbsIndex - ); - - // - // Update the OptionalData in the Boot#### variable - // - ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex = BbsIndex; - EfiBootManagerLoadOptionToVariable (&BootOption[Index]); - } - } - } - EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); - - if (LegacyDevOrder != NULL) { - Status = gRT->SetVariable ( - VAR_LEGACY_DEV_ORDER, - &gEfiLegacyDevOrderVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, - LegacyDevOrderSize, - LegacyDevOrder - ); - // - // Shrink variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - FreePool (LegacyDevOrder); - } - FreePool(BbsIndexUsed); - return Status; -} - -/** - Create legacy boot option. - - @param BootOption Ponter to the boot option which will be crated. - @param BbsEntry The input bbs entry info. - @param BbsIndex The BBS index. - - @retval EFI_SUCCESS Create legacy boot option successfully. - @retval EFI_INVALID_PARAMETER Invalid input parameter. - -**/ -EFI_STATUS -LegacyBmCreateLegacyBootOption ( - IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, - IN BBS_TABLE *BbsEntry, - IN UINT16 BbsIndex - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; - CHAR8 HelpString[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; - UINTN StringLen; - LEGACY_BM_BOOT_OPTION_BBS_DATA *OptionalData; - BBS_BBS_DEVICE_PATH *BbsNode; - - if ((BootOption == NULL) || (BbsEntry == NULL)) { - return EFI_INVALID_PARAMETER; - } - - LegacyBmBuildLegacyDevNameString (BbsEntry, BbsIndex, sizeof (Description), Description); - - // - // Create the BBS device path with description string - // - UnicodeStrToAsciiStrS (Description, HelpString, sizeof (HelpString)); - StringLen = AsciiStrLen (HelpString); - DevicePath = AllocatePool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen + END_DEVICE_PATH_LENGTH); - ASSERT (DevicePath != NULL); - - BbsNode = (BBS_BBS_DEVICE_PATH *) DevicePath; - SetDevicePathNodeLength (BbsNode, sizeof (BBS_BBS_DEVICE_PATH) + StringLen); - BbsNode->Header.Type = BBS_DEVICE_PATH; - BbsNode->Header.SubType = BBS_BBS_DP; - BbsNode->DeviceType = BbsEntry->DeviceType; - CopyMem (&BbsNode->StatusFlag, &BbsEntry->StatusFlags, sizeof (BBS_STATUS_FLAGS)); - CopyMem (BbsNode->String, HelpString, StringLen + 1); - - SetDevicePathEndNode (NextDevicePathNode (BbsNode)); - - // - // Create the OptionalData - // - OptionalData = AllocatePool (sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA)); - ASSERT (OptionalData != NULL); - OptionalData->BbsIndex = BbsIndex; - - // - // Create the BootOption - // - Status = EfiBootManagerInitializeLoadOption ( - BootOption, - LoadOptionNumberUnassigned, - LoadOptionTypeBoot, - LOAD_OPTION_ACTIVE, - Description, - DevicePath, - (UINT8 *) OptionalData, - sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA) - ); - FreePool (DevicePath); - FreePool (OptionalData); - - 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 * -LegacyBmFillDevOrderBuf ( - IN BBS_TABLE *BbsTable, - IN BBS_TYPE BbsType, - IN UINTN BbsCount, - OUT UINT16 *Buf - ) -{ - UINTN Index; - - for (Index = 0; Index < BbsCount; Index++) { - if (!LegacyBmValidBbsEntry (&BbsTable[Index])) { - 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 EfiLegacyDevOrderGuid 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 -LegacyBmCreateDevOrder ( - 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 (!LegacyBmValidBbsEntry (&BbsTable[Index])) { - 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 *) LegacyBmFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data); - - DevOrderPtr->BbsType = BBS_HARDDISK; - DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16)); - DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data); - - DevOrderPtr->BbsType = BBS_CDROM; - DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16)); - DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data); - - DevOrderPtr->BbsType = BBS_EMBED_NETWORK; - DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16)); - DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (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 *) LegacyBmFillDevOrderBuf (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_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 -LegacyBmUpdateDevOrder ( - VOID - ) -{ - LEGACY_DEV_ORDER_ENTRY *DevOrder; - LEGACY_DEV_ORDER_ENTRY *NewDevOrder; - LEGACY_DEV_ORDER_ENTRY *Ptr; - LEGACY_DEV_ORDER_ENTRY *NewPtr; - 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; - } - - GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, NULL); - if (NULL == DevOrder) { - return LegacyBmCreateDevOrder (LocalBbsTable, BbsCount); - } - // - // First we figure out how many boot devices with same device type respectively - // - for (Index = 0; Index < BbsCount; Index++) { - if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { - 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || - 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || - 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || - 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || - 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || - 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { - 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_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 -LegacyBmSetPriorityForSameTypeDev ( - 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; - - GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, &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 *) ((UINTN) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length); - } - - if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) { - FreePool (DevOrder); - return EFI_NOT_FOUND; - } - - if (BbsIndex != (UINTN) -1) { - // - // In case the BBS entry isn't valid because devices were plugged or removed. - // - if (!LegacyBmValidBbsEntry (&LocalBbsTable[BbsIndex]) || (LocalBbsTable[BbsIndex].DeviceType != DeviceType)) { - FreePool (DevOrder); - return EFI_NOT_FOUND; - } - 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 -LegacyBmPrintBbsTable ( - IN BBS_TABLE *LocalBbsTable, - IN UINT16 BbsCount - ) -{ - UINT16 Index; - - DEBUG ((DEBUG_INFO, "\n")); - DEBUG ((DEBUG_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n")); - DEBUG ((DEBUG_INFO, "=============================================\n")); - for (Index = 0; Index < BbsCount; Index++) { - if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { - continue; - } - - DEBUG ( - (DEBUG_INFO, - " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n", - (UINTN) Index, - (UINTN) LocalBbsTable[Index].BootPriority, - (UINTN) LocalBbsTable[Index].Bus, - (UINTN) LocalBbsTable[Index].Device, - (UINTN) LocalBbsTable[Index].Function, - (UINTN) LocalBbsTable[Index].Class, - (UINTN) LocalBbsTable[Index].SubClass, - (UINTN) LocalBbsTable[Index].DeviceType, - (UINTN) * (UINT16 *) &LocalBbsTable[Index].StatusFlags, - (UINTN) LocalBbsTable[Index].BootHandlerSegment, - (UINTN) LocalBbsTable[Index].BootHandlerOffset, - (UINTN) ((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTable[Index].MfgStringOffset), - (UINTN) ((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTable[Index].DescStringOffset)) - ); - } - - DEBUG ((DEBUG_INFO, "\n")); -} - -/** - Set the boot priority for BBS entries based on boot option entry and boot order. - - @param BootOption 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 -LegacyBmRefreshBbsTableForBoot ( - IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption - ) -{ - 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 *DeviceType; - UINTN DeviceTypeCount; - UINTN DeviceTypeIndex; - EFI_BOOT_MANAGER_LOAD_OPTION *Option; - UINTN OptionCount; - - HddCount = 0; - BbsCount = 0; - LocalHddInfo = NULL; - LocalBbsTable = NULL; - DevType = BBS_UNKNOWN; - - 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; - } - - // - // 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 (LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { - LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; - } - } - // - // boot priority always starts at 0 - // - Priority = 0; - if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) && - (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) { - // - // If BootOption stands for a legacy boot option, we prioritize the devices with the same type first. - // - DevType = LegacyBmDeviceType (BootOption->FilePath); - BbsIndex = ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData)->BbsIndex; - Status = LegacyBmSetPriorityForSameTypeDev ( - 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 - // - Option = EfiBootManagerGetLoadOptions (&OptionCount, LoadOptionTypeBoot); - DeviceType = AllocatePool (sizeof (UINT16) * OptionCount); - ASSERT (DeviceType != NULL); - DeviceType[0] = DevType; - DeviceTypeCount = 1; - for (Index = 0; Index < OptionCount; Index++) { - if ((DevicePathType (Option[Index].FilePath) != BBS_DEVICE_PATH) || - (DevicePathSubType (Option[Index].FilePath) != BBS_BBS_DP)) { - continue; - } - - DevType = LegacyBmDeviceType (Option[Index].FilePath); - 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 - // - continue; - } - - DeviceType[DeviceTypeCount] = DevType; - DeviceTypeCount++; - - Status = LegacyBmSetPriorityForSameTypeDev ( - DevType, - (UINTN) -1, - LocalBbsTable, - &Priority - ); - } - EfiBootManagerFreeLoadOptions (Option, OptionCount); - - DEBUG_CODE_BEGIN(); - LegacyBmPrintBbsTable (LocalBbsTable, BbsCount); - DEBUG_CODE_END(); - - return Status; -} - - -/** - Boot the legacy system with the boot option. - - @param BootOption The legacy boot option which have BBS device path - On return, BootOption->Status contains the boot status. - EFI_UNSUPPORTED There is no legacybios protocol, do not support - legacy boot. - EFI_STATUS The status of LegacyBios->LegacyBoot (). -**/ -VOID -EFIAPI -LegacyBmBoot ( - IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - // - // If no LegacyBios protocol we do not support legacy boot - // - BootOption->Status = EFI_UNSUPPORTED; - return; - } - // - // Notes: if we separate the int 19, then we don't need to refresh BBS - // - Status = LegacyBmRefreshBbsTableForBoot (BootOption); - if (EFI_ERROR (Status)) { - BootOption->Status = Status; - return; - } - - BootOption->Status = LegacyBios->LegacyBoot ( - LegacyBios, - (BBS_BBS_DEVICE_PATH *) BootOption->FilePath, - BootOption->OptionalDataSize, - BootOption->OptionalData - ); -} - -/** - This function enumerates all the legacy boot options. - - @param BootOptionCount Return the legacy boot option count. - - @retval Pointer to the legacy boot option buffer. -**/ -EFI_BOOT_MANAGER_LOAD_OPTION * -LegacyBmEnumerateAllBootOptions ( - UINTN *BootOptionCount - ) -{ - EFI_STATUS Status; - UINT16 HddCount; - UINT16 BbsCount; - HDD_INFO *HddInfo; - BBS_TABLE *BbsTable; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - UINT16 Index; - EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; - - ASSERT (BootOptionCount != NULL); - - BootOptions = NULL; - *BootOptionCount = 0; - BbsCount = 0; - - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - return NULL; - } - - Status = LegacyBios->GetBbsInfo ( - LegacyBios, - &HddCount, - &HddInfo, - &BbsCount, - &BbsTable - ); - if (EFI_ERROR (Status)) { - return NULL; - } - - for (Index = 0; Index < BbsCount; Index++) { - if (!LegacyBmValidBbsEntry (&BbsTable[Index])) { - continue; - } - - BootOptions = ReallocatePool ( - sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount), - sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1), - BootOptions - ); - ASSERT (BootOptions != NULL); - - Status = LegacyBmCreateLegacyBootOption (&BootOptions[(*BootOptionCount)++], &BbsTable[Index], Index); - ASSERT_EFI_ERROR (Status); - } - - return BootOptions; -} - -/** - Return the index of the boot option in the boot option array. - - The function compares the Description, FilePath, OptionalData. - - @param Key The input boot option which is compared with. - @param Array The input boot option array. - @param Count The count of the input boot options. - - @retval The index of the input boot option in the array. - -**/ -INTN -LegacyBmFindBootOption ( - IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key, - IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array, - IN UINTN Count - ) -{ - UINTN Index; - - for (Index = 0; Index < Count; Index++) { - if ((StrCmp (Key->Description, Array[Index].Description) == 0) && - (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) && - (Key->OptionalDataSize == Array[Index].OptionalDataSize) && - (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) { - return (INTN) Index; - } - } - - return -1; -} - -/** - Refresh all legacy boot options. - -**/ -VOID -EFIAPI -LegacyBmRefreshAllBootOption ( - VOID - ) -{ - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - UINTN RootBridgeHandleCount; - EFI_HANDLE *RootBridgeHandleBuffer; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINTN RootBridgeIndex; - UINTN Index; - UINTN Flags; - EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; - UINTN BootOptionCount; - EFI_BOOT_MANAGER_LOAD_OPTION *ExistingBootOptions; - UINTN ExistingBootOptionCount; - - Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); - if (EFI_ERROR (Status)) { - LegacyBmDeleteAllBootOptions (); - return; - } - PERF_START (NULL, "LegacyBootOptionEnum", "BDS", 0); - - // - // Before enumerating the legacy boot option, we need to dispatch all the legacy option roms - // to ensure the GetBbsInfo() counts all the legacy devices. - // - gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciRootBridgeIoProtocolGuid, - NULL, - &RootBridgeHandleCount, - &RootBridgeHandleBuffer - ); - for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) { - gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE); - gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - for (Index = 0; Index < HandleCount; Index++) { - // - // Start the thunk driver so that the legacy option rom gets dispatched. - // Note: We don't directly call InstallPciRom because some thunk drivers - // (e.g. BlockIo thunk driver) depend on the immediate result after dispatching - // - Status = LegacyBios->CheckPciRom ( - LegacyBios, - HandleBuffer[Index], - NULL, - NULL, - &Flags - ); - if (!EFI_ERROR (Status)) { - gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); - } - } - } - - // - // Same algorithm pattern as the EfiBootManagerRefreshAllBootOption - // Firstly delete the invalid legacy boot options, - // then enumreate and save the newly appeared legacy boot options - // the last step is legacy boot option special action to refresh the LegacyDevOrder variable - // - LegacyBmDeleteAllInvalidBootOptions (); - - ExistingBootOptions = EfiBootManagerGetLoadOptions (&ExistingBootOptionCount, LoadOptionTypeBoot); - BootOptions = LegacyBmEnumerateAllBootOptions (&BootOptionCount); - - for (Index = 0; Index < BootOptionCount; Index++) { - if (LegacyBmFindBootOption (&BootOptions[Index], ExistingBootOptions, ExistingBootOptionCount) == -1) { - Status = EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1); - DEBUG (( - EFI_D_INFO, "[LegacyBds] New Boot Option: Boot%04x Bbs0x%04x %s %r\n", - (UINTN) BootOptions[Index].OptionNumber, - (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOptions[Index].OptionalData)->BbsIndex, - BootOptions[Index].Description, - Status - )); - // - // Continue upon failure to add boot option. - // - } - } - - EfiBootManagerFreeLoadOptions (ExistingBootOptions, ExistingBootOptionCount); - EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); - - // - // Failure to create LegacyDevOrder variable only impacts the boot order. - // - LegacyBmUpdateDevOrder (); - - PERF_END (NULL, "LegacyBootOptionEnum", "BDS", 0); -} diff --git a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf b/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf deleted file mode 100644 index 4025c82886..0000000000 --- a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf +++ /dev/null @@ -1,64 +0,0 @@ -## @file -# Legacy Boot Manager module is library for BDS phase. -# -# Copyright (c) 2011 - 2015, Intel 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 = LegacyBootManagerLib - MODULE_UNI_FILE = LegacyBootManagerLib.uni - FILE_GUID = F1B87BE4-0ACC-409A-A52B-7BFFABCC96A0 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION - CONSTRUCTOR = LegacyBootManagerLibConstructor - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 EBC -# - -[Sources] - LegacyBm.c - InternalLegacyBm.h - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - BaseLib - BaseMemoryLib - UefiBootServicesTableLib - UefiRuntimeServicesTableLib - DevicePathLib - MemoryAllocationLib - UefiLib - DebugLib - PrintLib - PerformanceLib - UefiBootManagerLib - -[Guids] - gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"Boot####" (Boot option variable) - ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array) - gEfiLegacyDevOrderVariableGuid - -[Protocols] - gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES - -[FeaturePcd] - -[Pcd] diff --git a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.uni b/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.uni deleted file mode 100644 index 2585c93496..0000000000 Binary files a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c deleted file mode 100644 index ada9a809fa..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c +++ /dev/null @@ -1,218 +0,0 @@ -/** @file - LZMA Decompress GUIDed Section Extraction Library, which produces LZMA custom - decompression algorithm with the converter for the different arch code. - It wraps Lzma decompress interfaces to GUIDed Section Extraction interfaces - and registers them into GUIDed handler table. - - 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. - -**/ - -#include "LzmaDecompressLibInternal.h" -#include "Sdk/C/Bra.h" - -/** - Examines a GUIDed section and returns the size of the decoded buffer and the - size of an scratch buffer required to actually decode the data in a GUIDed section. - - Examines a GUIDed section specified by InputSection. - If GUID for InputSection does not match the GUID that this handler supports, - then RETURN_UNSUPPORTED is returned. - If the required information can not be retrieved from InputSection, - then RETURN_INVALID_PARAMETER is returned. - If the GUID of InputSection does match the GUID that this handler supports, - then the size required to hold the decoded buffer is returned in OututBufferSize, - the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field - from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute. - - If InputSection is NULL, then ASSERT(). - If OutputBufferSize is NULL, then ASSERT(). - If ScratchBufferSize is NULL, then ASSERT(). - If SectionAttribute is NULL, then ASSERT(). - - - @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. - @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required - if the buffer specified by InputSection were decoded. - @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space - if the buffer specified by InputSection were decoded. - @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes - field of EFI_GUID_DEFINED_SECTION in the PI Specification. - - @retval RETURN_SUCCESS The information about InputSection was returned. - @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. - @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection. - -**/ -RETURN_STATUS -EFIAPI -LzmaArchGuidedSectionGetInfo ( - IN CONST VOID *InputSection, - OUT UINT32 *OutputBufferSize, - OUT UINT32 *ScratchBufferSize, - OUT UINT16 *SectionAttribute - ) -{ - ASSERT (InputSection != NULL); - ASSERT (OutputBufferSize != NULL); - ASSERT (ScratchBufferSize != NULL); - ASSERT (SectionAttribute != NULL); - - if (IS_SECTION2 (InputSection)) { - if (!CompareGuid ( - &gLzmaF86CustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - - *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes; - - return LzmaUefiDecompressGetInfo ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - OutputBufferSize, - ScratchBufferSize - ); - } else { - if (!CompareGuid ( - &gLzmaF86CustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - - *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes; - - return LzmaUefiDecompressGetInfo ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - OutputBufferSize, - ScratchBufferSize - ); - } -} - -/** - Decompress a LZAM compressed GUIDed section into a caller allocated output buffer. - - Decodes the GUIDed section specified by InputSection. - If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned. - If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned. - If the GUID of InputSection does match the GUID that this handler supports, then InputSection - is decoded into the buffer specified by OutputBuffer and the authentication status of this - decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the - data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise, - the decoded data will be placed in caller allocated buffer specified by OutputBuffer. - - If InputSection is NULL, then ASSERT(). - If OutputBuffer is NULL, then ASSERT(). - If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT(). - If AuthenticationStatus is NULL, then ASSERT(). - - - @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. - @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation. - @param[out] ScratchBuffer A caller allocated buffer that may be required by this function - as a scratch buffer to perform the decode operation. - @param[out] AuthenticationStatus - A pointer to the authentication status of the decoded output buffer. - See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI - section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must - never be set by this handler. - - @retval RETURN_SUCCESS The buffer specified by InputSection was decoded. - @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. - @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded. - -**/ -RETURN_STATUS -EFIAPI -LzmaArchGuidedSectionExtraction ( - IN CONST VOID *InputSection, - OUT VOID **OutputBuffer, - OUT VOID *ScratchBuffer, OPTIONAL - OUT UINT32 *AuthenticationStatus - ) -{ - EFI_GUID *InputGuid; - VOID *Source; - UINTN SourceSize; - EFI_STATUS Status; - UINT32 X86State; - UINT32 OutputBufferSize; - UINT32 ScratchBufferSize; - - ASSERT (OutputBuffer != NULL); - ASSERT (InputSection != NULL); - - if (IS_SECTION2 (InputSection)) { - InputGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid); - Source = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset; - SourceSize = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset; - } else { - InputGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid); - Source = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset; - SourceSize = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset; - } - - if (!CompareGuid (&gLzmaF86CustomDecompressGuid, InputGuid)) { - return RETURN_INVALID_PARAMETER; - } - - // - // Authentication is set to Zero, which may be ignored. - // - *AuthenticationStatus = 0; - - Status = LzmaUefiDecompress ( - Source, - SourceSize, - *OutputBuffer, - ScratchBuffer - ); - - // - // After decompress, the data need to be converted to the raw data. - // - if (!EFI_ERROR (Status)) { - Status = LzmaUefiDecompressGetInfo ( - Source, - (UINT32) SourceSize, - &OutputBufferSize, - &ScratchBufferSize - ); - - if (!EFI_ERROR (Status)) { - x86_Convert_Init(X86State); - x86_Convert(*OutputBuffer, OutputBufferSize, 0, &X86State, 0); - } - } - - return Status; -} - - -/** - Register LzmaArchDecompress and LzmaArchDecompressGetInfo handlers with LzmaF86CustomDecompressGuid. - - @retval RETURN_SUCCESS Register successfully. - @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler. -**/ -EFI_STATUS -EFIAPI -LzmaArchDecompressLibConstructor ( - ) -{ - return ExtractGuidedSectionRegisterHandlers ( - &gLzmaF86CustomDecompressGuid, - LzmaArchGuidedSectionGetInfo, - LzmaArchGuidedSectionExtraction - ); -} - diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/GuidedSectionExtraction.c b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/GuidedSectionExtraction.c deleted file mode 100644 index f19e0d28cd..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/GuidedSectionExtraction.c +++ /dev/null @@ -1,201 +0,0 @@ -/** @file - LZMA Decompress GUIDed Section Extraction Library. - It wraps Lzma decompress interfaces to GUIDed Section Extraction interfaces - and registers them into GUIDed handler table. - - Copyright (c) 2009 - 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 "LzmaDecompressLibInternal.h" - -/** - Examines a GUIDed section and returns the size of the decoded buffer and the - size of an scratch buffer required to actually decode the data in a GUIDed section. - - Examines a GUIDed section specified by InputSection. - If GUID for InputSection does not match the GUID that this handler supports, - then RETURN_UNSUPPORTED is returned. - If the required information can not be retrieved from InputSection, - then RETURN_INVALID_PARAMETER is returned. - If the GUID of InputSection does match the GUID that this handler supports, - then the size required to hold the decoded buffer is returned in OututBufferSize, - the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field - from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute. - - If InputSection is NULL, then ASSERT(). - If OutputBufferSize is NULL, then ASSERT(). - If ScratchBufferSize is NULL, then ASSERT(). - If SectionAttribute is NULL, then ASSERT(). - - - @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. - @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required - if the buffer specified by InputSection were decoded. - @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space - if the buffer specified by InputSection were decoded. - @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes - field of EFI_GUID_DEFINED_SECTION in the PI Specification. - - @retval RETURN_SUCCESS The information about InputSection was returned. - @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. - @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection. - -**/ -RETURN_STATUS -EFIAPI -LzmaGuidedSectionGetInfo ( - IN CONST VOID *InputSection, - OUT UINT32 *OutputBufferSize, - OUT UINT32 *ScratchBufferSize, - OUT UINT16 *SectionAttribute - ) -{ - ASSERT (InputSection != NULL); - ASSERT (OutputBufferSize != NULL); - ASSERT (ScratchBufferSize != NULL); - ASSERT (SectionAttribute != NULL); - - if (IS_SECTION2 (InputSection)) { - if (!CompareGuid ( - &gLzmaCustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - - *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes; - - return LzmaUefiDecompressGetInfo ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - OutputBufferSize, - ScratchBufferSize - ); - } else { - if (!CompareGuid ( - &gLzmaCustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - - *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes; - - return LzmaUefiDecompressGetInfo ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - OutputBufferSize, - ScratchBufferSize - ); - } -} - -/** - Decompress a LZAM compressed GUIDed section into a caller allocated output buffer. - - Decodes the GUIDed section specified by InputSection. - If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned. - If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned. - If the GUID of InputSection does match the GUID that this handler supports, then InputSection - is decoded into the buffer specified by OutputBuffer and the authentication status of this - decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the - data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise, - the decoded data will be placed in caller allocated buffer specified by OutputBuffer. - - If InputSection is NULL, then ASSERT(). - If OutputBuffer is NULL, then ASSERT(). - If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT(). - If AuthenticationStatus is NULL, then ASSERT(). - - - @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. - @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation. - @param[out] ScratchBuffer A caller allocated buffer that may be required by this function - as a scratch buffer to perform the decode operation. - @param[out] AuthenticationStatus - A pointer to the authentication status of the decoded output buffer. - See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI - section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must - never be set by this handler. - - @retval RETURN_SUCCESS The buffer specified by InputSection was decoded. - @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. - @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded. - -**/ -RETURN_STATUS -EFIAPI -LzmaGuidedSectionExtraction ( - IN CONST VOID *InputSection, - OUT VOID **OutputBuffer, - OUT VOID *ScratchBuffer, OPTIONAL - OUT UINT32 *AuthenticationStatus - ) -{ - ASSERT (OutputBuffer != NULL); - ASSERT (InputSection != NULL); - - if (IS_SECTION2 (InputSection)) { - if (!CompareGuid ( - &gLzmaCustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - - // - // Authentication is set to Zero, which may be ignored. - // - *AuthenticationStatus = 0; - - return LzmaUefiDecompress ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, - *OutputBuffer, - ScratchBuffer - ); - } else { - if (!CompareGuid ( - &gLzmaCustomDecompressGuid, - &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { - return RETURN_INVALID_PARAMETER; - } - - // - // Authentication is set to Zero, which may be ignored. - // - *AuthenticationStatus = 0; - - return LzmaUefiDecompress ( - (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, - *OutputBuffer, - ScratchBuffer - ); - } -} - - -/** - Register LzmaDecompress and LzmaDecompressGetInfo handlers with LzmaCustomerDecompressGuid. - - @retval RETURN_SUCCESS Register successfully. - @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler. -**/ -EFI_STATUS -EFIAPI -LzmaDecompressLibConstructor ( - ) -{ - return ExtractGuidedSectionRegisterHandlers ( - &gLzmaCustomDecompressGuid, - LzmaGuidedSectionGetInfo, - LzmaGuidedSectionExtraction - ); -} - diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt deleted file mode 100644 index e05b3bb853..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt +++ /dev/null @@ -1,4 +0,0 @@ -LzmaCustomDecompressLib is based on the LZMA SDK 4.65. -LZMA SDK 4.65 was placed in the public domain on -2009-02-03. It was released on the -http://www.7-zip.org/sdk.html website. \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf deleted file mode 100644 index ec7585d55b..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf +++ /dev/null @@ -1,66 +0,0 @@ -## @file -# LzmaArchCustomDecompressLib produces LZMA custom decompression algorithm with the converter for the different arch code. -# -# It is based on the LZMA SDK 4.65. -# LZMA SDK 4.65 was placed in the public domain on 2009-02-03. -# It was released on the http://www.7-zip.org/sdk.html website. -# -# Copyright (c) 2012 - 2015, Intel 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 = LzmaArchDecompressLib - MODULE_UNI_FILE = LzmaArchDecompressLib.uni - FILE_GUID = A853C1D2-E003-4cc4-9DD1-8824AD79FE48 - MODULE_TYPE = BASE - VERSION_STRING = 1.0 - LIBRARY_CLASS = NULL - CONSTRUCTOR = LzmaArchDecompressLibConstructor - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 -# - -[Sources] - LzmaDecompress.c - Sdk/C/Bra.h - Sdk/C/LzFind.c - Sdk/C/LzmaDec.c - Sdk/C/7zVersion.h - Sdk/C/CpuArch.h - Sdk/C/LzFind.h - Sdk/C/LzHash.h - Sdk/C/LzmaDec.h - Sdk/C/Types.h - UefiLzma.h - LzmaDecompressLibInternal.h - -[Sources.Ia32, Sources.X64] - Sdk/C/Bra86.c - F86GuidedSectionExtraction.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[Guids.Ia32, Guids.X64] - gLzmaF86CustomDecompressGuid ## PRODUCES ## GUID # specifies LZMA custom decompress algorithm with converter for x86 code. - -[LibraryClasses] - BaseLib - DebugLib - BaseMemoryLib - ExtractGuidedSectionLib - diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchDecompressLib.uni b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchDecompressLib.uni deleted file mode 100644 index 1830dae73c..0000000000 Binary files a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchDecompressLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf deleted file mode 100644 index f5624fd039..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf +++ /dev/null @@ -1,62 +0,0 @@ -## @file -# LzmaCustomDecompressLib produces LZMA custom decompression algorithm. -# -# It is based on the LZMA SDK 4.65. -# LZMA SDK 4.65 was placed in the public domain on 2009-02-03. -# It was released on the http://www.7-zip.org/sdk.html website. -# -# Copyright (c) 2009 - 2015, Intel 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 = LzmaDecompressLib - MODULE_UNI_FILE = LzmaDecompressLib.uni - FILE_GUID = 35194660-7421-44ad-9636-e44885f092d1 - MODULE_TYPE = BASE - VERSION_STRING = 1.0 - LIBRARY_CLASS = NULL - CONSTRUCTOR = LzmaDecompressLibConstructor - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - LzmaDecompress.c - Sdk/C/LzFind.c - Sdk/C/LzmaDec.c - Sdk/C/7zVersion.h - Sdk/C/CpuArch.h - Sdk/C/LzFind.h - Sdk/C/LzHash.h - Sdk/C/LzmaDec.h - Sdk/C/Types.h - GuidedSectionExtraction.c - UefiLzma.h - LzmaDecompressLibInternal.h - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[Guids] - gLzmaCustomDecompressGuid ## PRODUCES ## UNDEFINED # specifies LZMA custom decompress algorithm. - -[LibraryClasses] - BaseLib - DebugLib - BaseMemoryLib - ExtractGuidedSectionLib - diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c deleted file mode 100644 index e32b6a3025..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c +++ /dev/null @@ -1,220 +0,0 @@ -/** @file - LZMA Decompress interfaces - - Copyright (c) 2009 - 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 "LzmaDecompressLibInternal.h" -#include "Sdk/C/Types.h" -#include "Sdk/C/7zVersion.h" -#include "Sdk/C/LzmaDec.h" - -#define SCRATCH_BUFFER_REQUEST_SIZE SIZE_64KB - -typedef struct -{ - ISzAlloc Functions; - VOID *Buffer; - UINTN BufferSize; -} ISzAllocWithData; - -/** - Allocation routine used by LZMA decompression. - - @param P Pointer to the ISzAlloc instance - @param Size The size in bytes to be allocated - - @return The allocated pointer address, or NULL on failure -**/ -VOID * -SzAlloc ( - VOID *P, - size_t Size - ) -{ - VOID *Addr; - ISzAllocWithData *Private; - - Private = (ISzAllocWithData*) P; - - if (Private->BufferSize >= Size) { - Addr = Private->Buffer; - Private->Buffer = (VOID*) ((UINT8*)Addr + Size); - Private->BufferSize -= Size; - return Addr; - } else { - ASSERT (FALSE); - return NULL; - } -} - -/** - Free routine used by LZMA decompression. - - @param P Pointer to the ISzAlloc instance - @param Address The address to be freed -**/ -VOID -SzFree ( - VOID *P, - VOID *Address - ) -{ - // - // We use the 'scratch buffer' for allocations, so there is no free - // operation required. The scratch buffer will be freed by the caller - // of the decompression code. - // -} - -#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) - -/** - Get the size of the uncompressed buffer by parsing EncodeData header. - - @param EncodedData Pointer to the compressed data. - - @return The size of the uncompressed buffer. -**/ -UINT64 -GetDecodedSizeOfBuf( - UINT8 *EncodedData - ) -{ - UINT64 DecodedSize; - INTN Index; - - /* Parse header */ - DecodedSize = 0; - for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--) - DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index]; - - return DecodedSize; -} - -// -// LZMA functions and data as defined in local LzmaDecompressLibInternal.h -// - -/** - Given a Lzma compressed source buffer, this function retrieves the size of - the uncompressed buffer and the size of the scratch buffer required - to decompress the compressed source buffer. - - Retrieves the size of the uncompressed buffer and the temporary scratch buffer - required to decompress the buffer specified by Source and SourceSize. - The size of the uncompressed buffer is returned in DestinationSize, - the size of the scratch buffer is returned in ScratchSize, and RETURN_SUCCESS is returned. - This function does not have scratch buffer available to perform a thorough - checking of the validity of the source data. It just retrieves the "Original Size" - field from the LZMA_HEADER_SIZE beginning bytes of the source data and output it as DestinationSize. - And ScratchSize is specific to the decompression implementation. - - If SourceSize is less than LZMA_HEADER_SIZE, then ASSERT(). - - @param Source The source buffer containing the compressed data. - @param SourceSize The size, in bytes, of the source buffer. - @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer - that will be generated when the compressed buffer specified - by Source and SourceSize is decompressed. - @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that - is required to decompress the compressed buffer specified - by Source and SourceSize. - - @retval RETURN_SUCCESS The size of the uncompressed data was returned - in DestinationSize and the size of the scratch - buffer was returned in ScratchSize. - -**/ -RETURN_STATUS -EFIAPI -LzmaUefiDecompressGetInfo ( - IN CONST VOID *Source, - IN UINT32 SourceSize, - OUT UINT32 *DestinationSize, - OUT UINT32 *ScratchSize - ) -{ - UInt64 DecodedSize; - - ASSERT(SourceSize >= LZMA_HEADER_SIZE); - - DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source); - - *DestinationSize = (UINT32)DecodedSize; - *ScratchSize = SCRATCH_BUFFER_REQUEST_SIZE; - return RETURN_SUCCESS; -} - -/** - Decompresses a Lzma compressed source buffer. - - Extracts decompressed data to its original form. - If the compressed source data specified by Source is successfully decompressed - into Destination, then RETURN_SUCCESS is returned. If the compressed source data - specified by Source is not in a valid compressed data format, - then RETURN_INVALID_PARAMETER is returned. - - @param Source The source buffer containing the compressed data. - @param SourceSize The size of source buffer. - @param Destination The destination buffer to store the decompressed data - @param Scratch A temporary scratch buffer that is used to perform the decompression. - This is an optional parameter that may be NULL if the - required scratch buffer size is 0. - - @retval RETURN_SUCCESS Decompression completed successfully, and - the uncompressed buffer is returned in Destination. - @retval RETURN_INVALID_PARAMETER - The source buffer specified by Source is corrupted - (not in a valid compressed format). -**/ -RETURN_STATUS -EFIAPI -LzmaUefiDecompress ( - IN CONST VOID *Source, - IN UINTN SourceSize, - IN OUT VOID *Destination, - IN OUT VOID *Scratch - ) -{ - SRes LzmaResult; - ELzmaStatus Status; - SizeT DecodedBufSize; - SizeT EncodedDataSize; - ISzAllocWithData AllocFuncs; - - AllocFuncs.Functions.Alloc = SzAlloc; - AllocFuncs.Functions.Free = SzFree; - AllocFuncs.Buffer = Scratch; - AllocFuncs.BufferSize = SCRATCH_BUFFER_REQUEST_SIZE; - - DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source); - EncodedDataSize = (SizeT) (SourceSize - LZMA_HEADER_SIZE); - - LzmaResult = LzmaDecode( - Destination, - &DecodedBufSize, - (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE), - &EncodedDataSize, - Source, - LZMA_PROPS_SIZE, - LZMA_FINISH_END, - &Status, - &(AllocFuncs.Functions) - ); - - if (LzmaResult == SZ_OK) { - return RETURN_SUCCESS; - } else { - return RETURN_INVALID_PARAMETER; - } -} - diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLib.uni b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLib.uni deleted file mode 100644 index 498e4e1088..0000000000 Binary files a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h deleted file mode 100644 index 3096e91dbe..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h +++ /dev/null @@ -1,96 +0,0 @@ -/** @file - LZMA Decompress Library internal header file declares Lzma decompress interfaces. - - Copyright (c) 2009 - 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 __LZMADECOMPRESSLIB_INTERNAL_H__ -#define __LZMADECOMPRESSLIB_INTERNAL_H__ - -#include -#include -#include -#include -#include -#include - -/** - Given a Lzma compressed source buffer, this function retrieves the size of - the uncompressed buffer and the size of the scratch buffer required - to decompress the compressed source buffer. - - Retrieves the size of the uncompressed buffer and the temporary scratch buffer - required to decompress the buffer specified by Source and SourceSize. - The size of the uncompressed buffer is returned in DestinationSize, - the size of the scratch buffer is returned in ScratchSize, and RETURN_SUCCESS is returned. - This function does not have scratch buffer available to perform a thorough - checking of the validity of the source data. It just retrieves the "Original Size" - field from the LZMA_HEADER_SIZE beginning bytes of the source data and output it as DestinationSize. - And ScratchSize is specific to the decompression implementation. - - If SourceSize is less than LZMA_HEADER_SIZE, then ASSERT(). - - @param Source The source buffer containing the compressed data. - @param SourceSize The size, in bytes, of the source buffer. - @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer - that will be generated when the compressed buffer specified - by Source and SourceSize is decompressed. - @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that - is required to decompress the compressed buffer specified - by Source and SourceSize. - - @retval RETURN_SUCCESS The size of the uncompressed data was returned - in DestinationSize and the size of the scratch - buffer was returned in ScratchSize. - -**/ -RETURN_STATUS -EFIAPI -LzmaUefiDecompressGetInfo ( - IN CONST VOID *Source, - IN UINT32 SourceSize, - OUT UINT32 *DestinationSize, - OUT UINT32 *ScratchSize - ); - -/** - Decompresses a Lzma compressed source buffer. - - Extracts decompressed data to its original form. - If the compressed source data specified by Source is successfully decompressed - into Destination, then RETURN_SUCCESS is returned. If the compressed source data - specified by Source is not in a valid compressed data format, - then RETURN_INVALID_PARAMETER is returned. - - @param Source The source buffer containing the compressed data. - @param SourceSize The size of source buffer. - @param Destination The destination buffer to store the decompressed data - @param Scratch A temporary scratch buffer that is used to perform the decompression. - This is an optional parameter that may be NULL if the - required scratch buffer size is 0. - - @retval RETURN_SUCCESS Decompression completed successfully, and - the uncompressed buffer is returned in Destination. - @retval RETURN_INVALID_PARAMETER - The source buffer specified by Source is corrupted - (not in a valid compressed format). -**/ -RETURN_STATUS -EFIAPI -LzmaUefiDecompress ( - IN CONST VOID *Source, - IN UINTN SourceSize, - IN OUT VOID *Destination, - IN OUT VOID *Scratch - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h deleted file mode 100644 index 5a6bcadac6..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h +++ /dev/null @@ -1,7 +0,0 @@ -#define MY_VER_MAJOR 4 -#define MY_VER_MINOR 65 -#define MY_VER_BUILD 0 -#define MY_VERSION "4.65" -#define MY_DATE "2009-02-03" -#define MY_COPYRIGHT ": Igor Pavlov : Public domain" -#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h deleted file mode 100644 index b9018eb991..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Bra.h -- Branch converters for executables -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __BRA_H -#define __BRA_H - -#include "Types.h" - -/* -These functions convert relative addresses to absolute addresses -in CALL instructions to increase the compression ratio. - - In: - data - data buffer - size - size of data - ip - current virtual Instruction Pinter (IP) value - state - state variable for x86 converter - encoding - 0 (for decoding), 1 (for encoding) - - Out: - state - state variable for x86 converter - - Returns: - The number of processed bytes. If you call these functions with multiple calls, - you must start next call with first byte after block of processed bytes. - - Type Endian Alignment LookAhead - - x86 little 1 4 - ARMT little 2 2 - ARM little 4 0 - PPC big 4 0 - SPARC big 4 0 - IA64 little 16 0 - - size must be >= Alignment + LookAhead, if it's not last block. - If (size < Alignment + LookAhead), converter returns 0. - - Example: - - UInt32 ip = 0; - for () - { - ; size must be >= Alignment + LookAhead, if it's not last block - SizeT processed = Convert(data, size, ip, 1); - data += processed; - size -= processed; - ip += processed; - } -*/ - -#define x86_Convert_Init(state) { state = 0; } -SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); -SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); - -#endif diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c deleted file mode 100644 index 93566cb212..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Bra86.c -- Converter for x86 code (BCJ) -2008-10-04 : Igor Pavlov : Public domain */ - -#include "Bra.h" - -#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) - -const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; -const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; - -SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) -{ - SizeT bufferPos = 0, prevPosT; - UInt32 prevMask = *state & 0x7; - if (size < 5) - return 0; - ip += 5; - prevPosT = (SizeT)0 - 1; - - for (;;) - { - Byte *p = data + bufferPos; - Byte *limit = data + size - 4; - for (; p < limit; p++) - if ((*p & 0xFE) == 0xE8) - break; - bufferPos = (SizeT)(p - data); - if (p >= limit) - break; - prevPosT = bufferPos - prevPosT; - if (prevPosT > 3) - prevMask = 0; - else - { - prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; - if (prevMask != 0) - { - Byte b = p[4 - kMaskToBitNumber[prevMask]]; - if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) - { - prevPosT = bufferPos; - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; - continue; - } - } - } - prevPosT = bufferPos; - - if (Test86MSByte(p[4])) - { - UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); - UInt32 dest; - for (;;) - { - Byte b; - int index; - if (encoding) - dest = (ip + (UInt32)bufferPos) + src; - else - dest = src - (ip + (UInt32)bufferPos); - if (prevMask == 0) - break; - index = kMaskToBitNumber[prevMask] * 8; - b = (Byte)(dest >> (24 - index)); - if (!Test86MSByte(b)) - break; - src = dest ^ ((1 << (32 - index)) - 1); - } - p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); - p[3] = (Byte)(dest >> 16); - p[2] = (Byte)(dest >> 8); - p[1] = (Byte)dest; - bufferPos += 5; - } - else - { - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; - } - } - prevPosT = bufferPos - prevPosT; - *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); - return bufferPos; -} diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h deleted file mode 100644 index 006361f2f2..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h +++ /dev/null @@ -1,69 +0,0 @@ -/* CpuArch.h -2008-08-05 -Igor Pavlov -Public domain */ - -#ifndef __CPUARCH_H -#define __CPUARCH_H - -/* -LITTLE_ENDIAN_UNALIGN means: - 1) CPU is LITTLE_ENDIAN - 2) it's allowed to make unaligned memory accesses -if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know -about these properties of platform. -*/ - -#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) -#define LITTLE_ENDIAN_UNALIGN -#endif - -#ifdef LITTLE_ENDIAN_UNALIGN - -#define GetUi16(p) (*(const UInt16 *)(p)) -#define GetUi32(p) (*(const UInt32 *)(p)) -#define GetUi64(p) (*(const UInt64 *)(p)) -#define SetUi32(p, d) *(UInt32 *)(p) = (d); - -#else - -#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) - -#define GetUi32(p) ( \ - ((const Byte *)(p))[0] | \ - ((UInt32)((const Byte *)(p))[1] << 8) | \ - ((UInt32)((const Byte *)(p))[2] << 16) | \ - ((UInt32)((const Byte *)(p))[3] << 24)) - -#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) - -#define SetUi32(p, d) { UInt32 _x_ = (d); \ - ((Byte *)(p))[0] = (Byte)_x_; \ - ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ - ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ - ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } - -#endif - -#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) - -#pragma intrinsic(_byteswap_ulong) -#pragma intrinsic(_byteswap_uint64) -#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) -#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) - -#else - -#define GetBe32(p) ( \ - ((UInt32)((const Byte *)(p))[0] << 24) | \ - ((UInt32)((const Byte *)(p))[1] << 16) | \ - ((UInt32)((const Byte *)(p))[2] << 8) | \ - ((const Byte *)(p))[3] ) - -#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) - -#endif - -#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) - -#endif diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c deleted file mode 100644 index 492cea2e41..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c +++ /dev/null @@ -1,770 +0,0 @@ -/** @file - LzFind.c - - Based on LZMA SDK 4.65: - LzFind.c -- Match finder for LZ algorithms - 2008-10-04 : Igor Pavlov : Public domain - - Copyright (c) 2009, Intel 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 EFIAPI - -#include - -#endif // !EFIAPI - -#include "LzFind.h" -#include "LzHash.h" - -#define kEmptyHashValue 0 -#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) -#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ -#define kNormalizeMask (~(kNormalizeStepMin - 1)) -#define kMaxHistorySize ((UInt32)3 << 30) - -#define kStartMaxLen 3 - -static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) -{ - if (!p->directInput) - { - alloc->Free(alloc, p->bufferBase); - p->bufferBase = 0; - } -} - -/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ - -static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) -{ - UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; - if (p->directInput) - { - p->blockSize = blockSize; - return 1; - } - if (p->bufferBase == 0 || p->blockSize != blockSize) - { - LzInWindow_Free(p, alloc); - p->blockSize = blockSize; - p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); - } - return (p->bufferBase != 0); -} - -Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } -Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } - -UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } - -void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) -{ - p->posLimit -= subValue; - p->pos -= subValue; - p->streamPos -= subValue; -} - -static void MatchFinder_ReadBlock(CMatchFinder *p) -{ - if (p->streamEndWasReached || p->result != SZ_OK) - return; - for (;;) - { - Byte *dest = p->buffer + (p->streamPos - p->pos); - size_t size = (p->bufferBase + p->blockSize - dest); - if (size == 0) - return; - p->result = p->stream->Read(p->stream, dest, &size); - if (p->result != SZ_OK) - return; - if (size == 0) - { - p->streamEndWasReached = 1; - return; - } - p->streamPos += (UInt32)size; - if (p->streamPos - p->pos > p->keepSizeAfter) - return; - } -} - -void MatchFinder_MoveBlock(CMatchFinder *p) -{ - memmove(p->bufferBase, - p->buffer - p->keepSizeBefore, - (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); - p->buffer = p->bufferBase + p->keepSizeBefore; -} - -int MatchFinder_NeedMove(CMatchFinder *p) -{ - /* if (p->streamEndWasReached) return 0; */ - return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); -} - -void MatchFinder_ReadIfRequired(CMatchFinder *p) -{ - if (p->streamEndWasReached) - return; - if (p->keepSizeAfter >= p->streamPos - p->pos) - MatchFinder_ReadBlock(p); -} - -static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) -{ - if (MatchFinder_NeedMove(p)) - MatchFinder_MoveBlock(p); - MatchFinder_ReadBlock(p); -} - -static void MatchFinder_SetDefaultSettings(CMatchFinder *p) -{ - p->cutValue = 32; - p->btMode = 1; - p->numHashBytes = 4; - /* p->skipModeBits = 0; */ - p->directInput = 0; - p->bigHash = 0; -} - -#define kCrcPoly 0xEDB88320 - -void MatchFinder_Construct(CMatchFinder *p) -{ - UInt32 i; - p->bufferBase = 0; - p->directInput = 0; - p->hash = 0; - MatchFinder_SetDefaultSettings(p); - - for (i = 0; i < 256; i++) - { - UInt32 r = i; - int j; - for (j = 0; j < 8; j++) - r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); - p->crc[i] = r; - } -} - -static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->hash); - p->hash = 0; -} - -void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) -{ - MatchFinder_FreeThisClassMemory(p, alloc); - LzInWindow_Free(p, alloc); -} - -static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) -{ - size_t sizeInBytes = (size_t)num * sizeof(CLzRef); - if (sizeInBytes / sizeof(CLzRef) != num) - return 0; - return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); -} - -int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, - UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, - ISzAlloc *alloc) -{ - UInt32 sizeReserv; - if (historySize > kMaxHistorySize) - { - MatchFinder_Free(p, alloc); - return 0; - } - sizeReserv = historySize >> 1; - if (historySize > ((UInt32)2 << 30)) - sizeReserv = historySize >> 2; - sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); - - p->keepSizeBefore = historySize + keepAddBufferBefore + 1; - p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; - /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ - if (LzInWindow_Create(p, sizeReserv, alloc)) - { - UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; - UInt32 hs; - p->matchMaxLen = matchMaxLen; - { - p->fixedHashSize = 0; - if (p->numHashBytes == 2) - hs = (1 << 16) - 1; - else - { - hs = historySize - 1; - hs |= (hs >> 1); - hs |= (hs >> 2); - hs |= (hs >> 4); - hs |= (hs >> 8); - hs >>= 1; - /* hs >>= p->skipModeBits; */ - hs |= 0xFFFF; /* don't change it! It's required for Deflate */ - if (hs > (1 << 24)) - { - if (p->numHashBytes == 3) - hs = (1 << 24) - 1; - else - hs >>= 1; - } - } - p->hashMask = hs; - hs++; - if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; - if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; - if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; - hs += p->fixedHashSize; - } - - { - UInt32 prevSize = p->hashSizeSum + p->numSons; - UInt32 newSize; - p->historySize = historySize; - p->hashSizeSum = hs; - p->cyclicBufferSize = newCyclicBufferSize; - p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); - newSize = p->hashSizeSum + p->numSons; - if (p->hash != 0 && prevSize == newSize) - return 1; - MatchFinder_FreeThisClassMemory(p, alloc); - p->hash = AllocRefs(newSize, alloc); - if (p->hash != 0) - { - p->son = p->hash + p->hashSizeSum; - return 1; - } - } - } - MatchFinder_Free(p, alloc); - return 0; -} - -static void MatchFinder_SetLimits(CMatchFinder *p) -{ - UInt32 limit = kMaxValForNormalize - p->pos; - UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; - if (limit2 < limit) - limit = limit2; - limit2 = p->streamPos - p->pos; - if (limit2 <= p->keepSizeAfter) - { - if (limit2 > 0) - limit2 = 1; - } - else - limit2 -= p->keepSizeAfter; - if (limit2 < limit) - limit = limit2; - { - UInt32 lenLimit = p->streamPos - p->pos; - if (lenLimit > p->matchMaxLen) - lenLimit = p->matchMaxLen; - p->lenLimit = lenLimit; - } - p->posLimit = p->pos + limit; -} - -void MatchFinder_Init(CMatchFinder *p) -{ - UInt32 i; - for (i = 0; i < p->hashSizeSum; i++) - p->hash[i] = kEmptyHashValue; - p->cyclicBufferPos = 0; - p->buffer = p->bufferBase; - p->pos = p->streamPos = p->cyclicBufferSize; - p->result = SZ_OK; - p->streamEndWasReached = 0; - MatchFinder_ReadBlock(p); - MatchFinder_SetLimits(p); -} - -static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) -{ - return (p->pos - p->historySize - 1) & kNormalizeMask; -} - -void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) -{ - UInt32 i; - for (i = 0; i < numItems; i++) - { - UInt32 value = items[i]; - if (value <= subValue) - value = kEmptyHashValue; - else - value -= subValue; - items[i] = value; - } -} - -static void MatchFinder_Normalize(CMatchFinder *p) -{ - UInt32 subValue = MatchFinder_GetSubValue(p); - MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); - MatchFinder_ReduceOffsets(p, subValue); -} - -static void MatchFinder_CheckLimits(CMatchFinder *p) -{ - if (p->pos == kMaxValForNormalize) - MatchFinder_Normalize(p); - if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) - MatchFinder_CheckAndMoveAndRead(p); - if (p->cyclicBufferPos == p->cyclicBufferSize) - p->cyclicBufferPos = 0; - MatchFinder_SetLimits(p); -} - -static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, - UInt32 *distances, UInt32 maxLen) -{ - son[_cyclicBufferPos] = curMatch; - for (;;) - { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - return distances; - { - const Byte *pb = cur - delta; - curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; - if (pb[maxLen] == cur[maxLen] && *pb == *cur) - { - UInt32 len = 0; - while (++len != lenLimit) - if (pb[len] != cur[len]) - break; - if (maxLen < len) - { - *distances++ = maxLen = len; - *distances++ = delta - 1; - if (len == lenLimit) - return distances; - } - } - } - } -} - -UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, - UInt32 *distances, UInt32 maxLen) -{ - CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; - CLzRef *ptr1 = son + (_cyclicBufferPos << 1); - UInt32 len0 = 0, len1 = 0; - for (;;) - { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - return distances; - } - { - CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); - const Byte *pb = cur - delta; - UInt32 len = (len0 < len1 ? len0 : len1); - if (pb[len] == cur[len]) - { - if (++len != lenLimit && pb[len] == cur[len]) - while (++len != lenLimit) - if (pb[len] != cur[len]) - break; - if (maxLen < len) - { - *distances++ = maxLen = len; - *distances++ = delta - 1; - if (len == lenLimit) - { - *ptr1 = pair[0]; - *ptr0 = pair[1]; - return distances; - } - } - } - if (pb[len] < cur[len]) - { - *ptr1 = curMatch; - ptr1 = pair + 1; - curMatch = *ptr1; - len1 = len; - } - else - { - *ptr0 = curMatch; - ptr0 = pair; - curMatch = *ptr0; - len0 = len; - } - } - } -} - -static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) -{ - CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; - CLzRef *ptr1 = son + (_cyclicBufferPos << 1); - UInt32 len0 = 0, len1 = 0; - for (;;) - { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - return; - } - { - CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); - const Byte *pb = cur - delta; - UInt32 len = (len0 < len1 ? len0 : len1); - if (pb[len] == cur[len]) - { - while (++len != lenLimit) - if (pb[len] != cur[len]) - break; - { - if (len == lenLimit) - { - *ptr1 = pair[0]; - *ptr0 = pair[1]; - return; - } - } - } - if (pb[len] < cur[len]) - { - *ptr1 = curMatch; - ptr1 = pair + 1; - curMatch = *ptr1; - len1 = len; - } - else - { - *ptr0 = curMatch; - ptr0 = pair; - curMatch = *ptr0; - len0 = len; - } - } - } -} - -#define MOVE_POS \ - ++p->cyclicBufferPos; \ - p->buffer++; \ - if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); - -#define MOVE_POS_RET MOVE_POS return offset; - -static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } - -#define GET_MATCHES_HEADER2(minLen, ret_op) \ - UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ - lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ - cur = p->buffer; - -#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) -#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) - -#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue - -#define GET_MATCHES_FOOTER(offset, maxLen) \ - offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ - distances + offset, maxLen) - distances); MOVE_POS_RET; - -#define SKIP_FOOTER \ - SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; - -static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 offset; - GET_MATCHES_HEADER(2) - HASH2_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - offset = 0; - GET_MATCHES_FOOTER(offset, 1) -} - -UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 offset; - GET_MATCHES_HEADER(3) - HASH_ZIP_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - offset = 0; - GET_MATCHES_FOOTER(offset, 2) -} - -static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 hash2Value, delta2, maxLen, offset; - GET_MATCHES_HEADER(3) - - HASH3_CALC; - - delta2 = p->pos - p->hash[hash2Value]; - curMatch = p->hash[kFix3HashSize + hashValue]; - - p->hash[hash2Value] = - p->hash[kFix3HashSize + hashValue] = p->pos; - - - maxLen = 2; - offset = 0; - if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) - { - for (; maxLen != lenLimit; maxLen++) - if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) - break; - distances[0] = maxLen; - distances[1] = delta2 - 1; - offset = 2; - if (maxLen == lenLimit) - { - SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); - MOVE_POS_RET; - } - } - GET_MATCHES_FOOTER(offset, maxLen) -} - -static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; - GET_MATCHES_HEADER(4) - - HASH4_CALC; - - delta2 = p->pos - p->hash[ hash2Value]; - delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; - curMatch = p->hash[kFix4HashSize + hashValue]; - - p->hash[ hash2Value] = - p->hash[kFix3HashSize + hash3Value] = - p->hash[kFix4HashSize + hashValue] = p->pos; - - maxLen = 1; - offset = 0; - if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) - { - distances[0] = maxLen = 2; - distances[1] = delta2 - 1; - offset = 2; - } - if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) - { - maxLen = 3; - distances[offset + 1] = delta3 - 1; - offset += 2; - delta2 = delta3; - } - if (offset != 0) - { - for (; maxLen != lenLimit; maxLen++) - if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) - break; - distances[offset - 2] = maxLen; - if (maxLen == lenLimit) - { - SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); - MOVE_POS_RET; - } - } - if (maxLen < 3) - maxLen = 3; - GET_MATCHES_FOOTER(offset, maxLen) -} - -static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; - GET_MATCHES_HEADER(4) - - HASH4_CALC; - - delta2 = p->pos - p->hash[ hash2Value]; - delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; - curMatch = p->hash[kFix4HashSize + hashValue]; - - p->hash[ hash2Value] = - p->hash[kFix3HashSize + hash3Value] = - p->hash[kFix4HashSize + hashValue] = p->pos; - - maxLen = 1; - offset = 0; - if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) - { - distances[0] = maxLen = 2; - distances[1] = delta2 - 1; - offset = 2; - } - if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) - { - maxLen = 3; - distances[offset + 1] = delta3 - 1; - offset += 2; - delta2 = delta3; - } - if (offset != 0) - { - for (; maxLen != lenLimit; maxLen++) - if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) - break; - distances[offset - 2] = maxLen; - if (maxLen == lenLimit) - { - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS_RET; - } - } - if (maxLen < 3) - maxLen = 3; - offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances + offset, maxLen) - (distances)); - MOVE_POS_RET -} - -UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 offset; - GET_MATCHES_HEADER(3) - HASH_ZIP_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances, 2) - (distances)); - MOVE_POS_RET -} - -static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - SKIP_HEADER(2) - HASH2_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - SKIP_FOOTER - } - while (--num != 0); -} - -void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - SKIP_HEADER(3) - HASH_ZIP_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - SKIP_FOOTER - } - while (--num != 0); -} - -static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - UInt32 hash2Value; - SKIP_HEADER(3) - HASH3_CALC; - curMatch = p->hash[kFix3HashSize + hashValue]; - p->hash[hash2Value] = - p->hash[kFix3HashSize + hashValue] = p->pos; - SKIP_FOOTER - } - while (--num != 0); -} - -static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - UInt32 hash2Value, hash3Value; - SKIP_HEADER(4) - HASH4_CALC; - curMatch = p->hash[kFix4HashSize + hashValue]; - p->hash[ hash2Value] = - p->hash[kFix3HashSize + hash3Value] = p->pos; - p->hash[kFix4HashSize + hashValue] = p->pos; - SKIP_FOOTER - } - while (--num != 0); -} - -static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - UInt32 hash2Value, hash3Value; - SKIP_HEADER(4) - HASH4_CALC; - curMatch = p->hash[kFix4HashSize + hashValue]; - p->hash[ hash2Value] = - p->hash[kFix3HashSize + hash3Value] = - p->hash[kFix4HashSize + hashValue] = p->pos; - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS - } - while (--num != 0); -} - -void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - SKIP_HEADER(3) - HASH_ZIP_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS - } - while (--num != 0); -} - -void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) -{ - vTable->Init = (Mf_Init_Func)MatchFinder_Init; - vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; - vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; - vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; - if (!p->btMode) - { - vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; - vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; - } - else if (p->numHashBytes == 2) - { - vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; - vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; - } - else if (p->numHashBytes == 3) - { - vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; - vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; - } - else - { - vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; - vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; - } -} diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h deleted file mode 100644 index 423d67e0c3..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.h +++ /dev/null @@ -1,107 +0,0 @@ -/* LzFind.h -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZFIND_H -#define __LZFIND_H - -#include "Types.h" - -typedef UInt32 CLzRef; - -typedef struct _CMatchFinder -{ - Byte *buffer; - UInt32 pos; - UInt32 posLimit; - UInt32 streamPos; - UInt32 lenLimit; - - UInt32 cyclicBufferPos; - UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ - - UInt32 matchMaxLen; - CLzRef *hash; - CLzRef *son; - UInt32 hashMask; - UInt32 cutValue; - - Byte *bufferBase; - ISeqInStream *stream; - int streamEndWasReached; - - UInt32 blockSize; - UInt32 keepSizeBefore; - UInt32 keepSizeAfter; - - UInt32 numHashBytes; - int directInput; - int btMode; - /* int skipModeBits; */ - int bigHash; - UInt32 historySize; - UInt32 fixedHashSize; - UInt32 hashSizeSum; - UInt32 numSons; - SRes result; - UInt32 crc[256]; -} CMatchFinder; - -#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) -#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) - -#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) - -int MatchFinder_NeedMove(CMatchFinder *p); -Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); -void MatchFinder_MoveBlock(CMatchFinder *p); -void MatchFinder_ReadIfRequired(CMatchFinder *p); - -void MatchFinder_Construct(CMatchFinder *p); - -/* Conditions: - historySize <= 3 GB - keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB -*/ -int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, - UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, - ISzAlloc *alloc); -void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); -void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); -void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); - -UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, - UInt32 *distances, UInt32 maxLen); - -/* -Conditions: - Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. - Mf_GetPointerToCurrentPos_Func's result must be used only before any other function -*/ - -typedef void (*Mf_Init_Func)(void *object); -typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); -typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); -typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); -typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); -typedef void (*Mf_Skip_Func)(void *object, UInt32); - -typedef struct _IMatchFinder -{ - Mf_Init_Func Init; - Mf_GetIndexByte_Func GetIndexByte; - Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; - Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; - Mf_GetMatches_Func GetMatches; - Mf_Skip_Func Skip; -} IMatchFinder; - -void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); - -void MatchFinder_Init(CMatchFinder *p); -UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); -UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); -void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); -void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); - -#endif diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h deleted file mode 100644 index c923417501..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzHash.h +++ /dev/null @@ -1,54 +0,0 @@ -/* LzHash.h -- HASH functions for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZHASH_H -#define __LZHASH_H - -#define kHash2Size (1 << 10) -#define kHash3Size (1 << 16) -#define kHash4Size (1 << 20) - -#define kFix3HashSize (kHash2Size) -#define kFix4HashSize (kHash2Size + kHash3Size) -#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) - -#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); - -#define HASH3_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } - -#define HASH4_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ - hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } - -#define HASH5_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ - hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ - hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ - hash4Value &= (kHash4Size - 1); } - -/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ -#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; - - -#define MT_HASH2_CALC \ - hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); - -#define MT_HASH3_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } - -#define MT_HASH4_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ - hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } - -#endif diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c deleted file mode 100644 index e3db4edbb4..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c +++ /dev/null @@ -1,1026 +0,0 @@ -/** @file - LzmaDec.c - - Based on LZMA SDK 4.65: - LzmaDec.c -- LZMA Decoder - 2008-11-06 : Igor Pavlov : Public domain - - Copyright (c) 2009, Intel 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 "LzmaDec.h" - -#ifndef EFIAPI - -#include - -#endif // !EFIAPI - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_INIT_SIZE 5 - -#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } - -#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); -#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); -#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ - { UPDATE_0(p); i = (i + i); A0; } else \ - { UPDATE_1(p); i = (i + i) + 1; A1; } -#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) - -#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } -#define TREE_DECODE(probs, limit, i) \ - { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } - -/* #define _LZMA_SIZE_OPT */ - -#ifdef _LZMA_SIZE_OPT -#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) -#else -#define TREE_6_DECODE(probs, i) \ - { i = 1; \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - i -= 0x40; } -#endif - -#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } - -#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0_CHECK range = bound; -#define UPDATE_1_CHECK range -= bound; code -= bound; -#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ - { UPDATE_0_CHECK; i = (i + i); A0; } else \ - { UPDATE_1_CHECK; i = (i + i) + 1; A1; } -#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) -#define TREE_DECODE_CHECK(probs, limit, i) \ - { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } - - -#define kNumPosBitsMax 4 -#define kNumPosStatesMax (1 << kNumPosBitsMax) - -#define kLenNumLowBits 3 -#define kLenNumLowSymbols (1 << kLenNumLowBits) -#define kLenNumMidBits 3 -#define kLenNumMidSymbols (1 << kLenNumMidBits) -#define kLenNumHighBits 8 -#define kLenNumHighSymbols (1 << kLenNumHighBits) - -#define LenChoice 0 -#define LenChoice2 (LenChoice + 1) -#define LenLow (LenChoice2 + 1) -#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) -#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) -#define kNumLenProbs (LenHigh + kLenNumHighSymbols) - - -#define kNumStates 12 -#define kNumLitStates 7 - -#define kStartPosModelIndex 4 -#define kEndPosModelIndex 14 -#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) - -#define kNumPosSlotBits 6 -#define kNumLenToPosStates 4 - -#define kNumAlignBits 4 -#define kAlignTableSize (1 << kNumAlignBits) - -#define kMatchMinLen 2 -#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) - -#define IsMatch 0 -#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) -#define IsRepG0 (IsRep + kNumStates) -#define IsRepG1 (IsRepG0 + kNumStates) -#define IsRepG2 (IsRepG1 + kNumStates) -#define IsRep0Long (IsRepG2 + kNumStates) -#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) -#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) -#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) -#define LenCoder (Align + kAlignTableSize) -#define RepLenCoder (LenCoder + kNumLenProbs) -#define Literal (RepLenCoder + kNumLenProbs) - -#define LZMA_BASE_SIZE 1846 -#define LZMA_LIT_SIZE 768 - -#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) - -#if Literal != LZMA_BASE_SIZE -StopCompilingDueBUG -#endif - -static const Byte kLiteralNextStates[kNumStates * 2] = -{ - 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, - 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 -}; - -#define LZMA_DIC_MIN (1 << 12) - -/* First LZMA-symbol is always decoded. -And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization -Out: - Result: - SZ_OK - OK - SZ_ERROR_DATA - Error - p->remainLen: - < kMatchSpecLenStart : normal remain - = kMatchSpecLenStart : finished - = kMatchSpecLenStart + 1 : Flush marker - = kMatchSpecLenStart + 2 : State Init Marker -*/ - -static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) -{ - CLzmaProb *probs = p->probs; - - unsigned state = p->state; - UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; - unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; - unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; - unsigned lc = p->prop.lc; - - Byte *dic = p->dic; - SizeT dicBufSize = p->dicBufSize; - SizeT dicPos = p->dicPos; - - UInt32 processedPos = p->processedPos; - UInt32 checkDicSize = p->checkDicSize; - unsigned len = 0; - - const Byte *buf = p->buf; - UInt32 range = p->range; - UInt32 code = p->code; - - do - { - CLzmaProb *prob; - UInt32 bound; - unsigned ttt; - unsigned posState = processedPos & pbMask; - - prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; - IF_BIT_0(prob) - { - unsigned symbol; - UPDATE_0(prob); - prob = probs + Literal; - if (checkDicSize != 0 || processedPos != 0) - prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + - (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); - - if (state < kNumLitStates) - { - symbol = 1; - do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); - } - else - { - unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - unsigned offs = 0x100; - symbol = 1; - do - { - unsigned bit; - CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) - } - while (symbol < 0x100); - } - dic[dicPos++] = (Byte)symbol; - processedPos++; - - state = kLiteralNextStates[state]; - /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ - continue; - } - else - { - UPDATE_1(prob); - prob = probs + IsRep + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - state += kNumStates; - prob = probs + LenCoder; - } - else - { - UPDATE_1(prob); - if (checkDicSize == 0 && processedPos == 0) - return SZ_ERROR_DATA; - prob = probs + IsRepG0 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; - IF_BIT_0(prob) - { - UPDATE_0(prob); - dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - dicPos++; - processedPos++; - state = state < kNumLitStates ? 9 : 11; - continue; - } - UPDATE_1(prob); - } - else - { - UInt32 distance; - UPDATE_1(prob); - prob = probs + IsRepG1 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - distance = rep1; - } - else - { - UPDATE_1(prob); - prob = probs + IsRepG2 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - distance = rep2; - } - else - { - UPDATE_1(prob); - distance = rep3; - rep3 = rep2; - } - rep2 = rep1; - } - rep1 = rep0; - rep0 = distance; - } - state = state < kNumLitStates ? 8 : 11; - prob = probs + RepLenCoder; - } - { - unsigned limit2, offset; - CLzmaProb *probLen = prob + LenChoice; - IF_BIT_0(probLen) - { - UPDATE_0(probLen); - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - limit2 = (1 << kLenNumLowBits); - } - else - { - UPDATE_1(probLen); - probLen = prob + LenChoice2; - IF_BIT_0(probLen) - { - UPDATE_0(probLen); - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - limit2 = (1 << kLenNumMidBits); - } - else - { - UPDATE_1(probLen); - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit2 = (1 << kLenNumHighBits); - } - } - TREE_DECODE(probLen, limit2, len); - len += offset; - } - - if (state >= kNumStates) - { - UInt32 distance; - prob = probs + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); - TREE_6_DECODE(prob, distance); - if (distance >= kStartPosModelIndex) - { - unsigned posSlot = (unsigned)distance; - int numDirectBits = (int)(((distance >> 1) - 1)); - distance = (2 | (distance & 1)); - if (posSlot < kEndPosModelIndex) - { - distance <<= numDirectBits; - prob = probs + SpecPos + distance - posSlot - 1; - { - UInt32 mask = 1; - unsigned i = 1; - do - { - GET_BIT2(prob + i, i, ; , distance |= mask); - mask <<= 1; - } - while (--numDirectBits != 0); - } - } - else - { - numDirectBits -= kNumAlignBits; - do - { - NORMALIZE - range >>= 1; - - { - UInt32 t; - code -= range; - t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ - distance = (distance << 1) + (t + 1); - code += range & t; - } - /* - distance <<= 1; - if (code >= range) - { - code -= range; - distance |= 1; - } - */ - } - while (--numDirectBits != 0); - prob = probs + Align; - distance <<= kNumAlignBits; - { - unsigned i = 1; - GET_BIT2(prob + i, i, ; , distance |= 1); - GET_BIT2(prob + i, i, ; , distance |= 2); - GET_BIT2(prob + i, i, ; , distance |= 4); - GET_BIT2(prob + i, i, ; , distance |= 8); - } - if (distance == (UInt32)0xFFFFFFFF) - { - len += kMatchSpecLenStart; - state -= kNumStates; - break; - } - } - } - rep3 = rep2; - rep2 = rep1; - rep1 = rep0; - rep0 = distance + 1; - if (checkDicSize == 0) - { - if (distance >= processedPos) - return SZ_ERROR_DATA; - } - else if (distance >= checkDicSize) - return SZ_ERROR_DATA; - state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; - /* state = kLiteralNextStates[state]; */ - } - - len += kMatchMinLen; - - if (limit == dicPos) - return SZ_ERROR_DATA; - { - SizeT rem = limit - dicPos; - unsigned curLen = ((rem < len) ? (unsigned)rem : len); - SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); - - processedPos += curLen; - - len -= curLen; - if (pos + curLen <= dicBufSize) - { - Byte *dest = dic + dicPos; - ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; - const Byte *lim = dest + curLen; - dicPos += curLen; - do - *((volatile Byte *)dest) = (Byte)*(dest + src); - while (++dest != lim); - } - else - { - do - { - dic[dicPos++] = dic[pos]; - if (++pos == dicBufSize) - pos = 0; - } - while (--curLen != 0); - } - } - } - } - while (dicPos < limit && buf < bufLimit); - NORMALIZE; - p->buf = buf; - p->range = range; - p->code = code; - p->remainLen = len; - p->dicPos = dicPos; - p->processedPos = processedPos; - p->reps[0] = rep0; - p->reps[1] = rep1; - p->reps[2] = rep2; - p->reps[3] = rep3; - p->state = state; - - return SZ_OK; -} - -static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) -{ - if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) - { - Byte *dic = p->dic; - SizeT dicPos = p->dicPos; - SizeT dicBufSize = p->dicBufSize; - unsigned len = p->remainLen; - UInt32 rep0 = p->reps[0]; - if (limit - dicPos < len) - len = (unsigned)(limit - dicPos); - - if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) - p->checkDicSize = p->prop.dicSize; - - p->processedPos += len; - p->remainLen -= len; - while (len-- != 0) - { - dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - dicPos++; - } - p->dicPos = dicPos; - } -} - -static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) -{ - do - { - SizeT limit2 = limit; - if (p->checkDicSize == 0) - { - UInt32 rem = p->prop.dicSize - p->processedPos; - if (limit - p->dicPos > rem) - limit2 = p->dicPos + rem; - } - RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); - if (p->processedPos >= p->prop.dicSize) - p->checkDicSize = p->prop.dicSize; - LzmaDec_WriteRem(p, limit); - } - while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); - - if (p->remainLen > kMatchSpecLenStart) - { - p->remainLen = kMatchSpecLenStart; - } - return 0; -} - -typedef enum -{ - DUMMY_ERROR, /* unexpected end of input stream */ - DUMMY_LIT, - DUMMY_MATCH, - DUMMY_REP -} ELzmaDummy; - -static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) -{ - UInt32 range = p->range; - UInt32 code = p->code; - const Byte *bufLimit = buf + inSize; - CLzmaProb *probs = p->probs; - unsigned state = p->state; - ELzmaDummy res; - - { - CLzmaProb *prob; - UInt32 bound; - unsigned ttt; - unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); - - prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK - - /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ - - prob = probs + Literal; - if (p->checkDicSize != 0 || p->processedPos != 0) - prob += (LZMA_LIT_SIZE * - ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + - (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); - - if (state < kNumLitStates) - { - unsigned symbol = 1; - do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); - } - else - { - unsigned matchByte = p->dic[p->dicPos - p->reps[0] + - ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; - unsigned offs = 0x100; - unsigned symbol = 1; - do - { - unsigned bit; - CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) - } - while (symbol < 0x100); - } - res = DUMMY_LIT; - } - else - { - unsigned len; - UPDATE_1_CHECK; - - prob = probs + IsRep + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - state = 0; - prob = probs + LenCoder; - res = DUMMY_MATCH; - } - else - { - UPDATE_1_CHECK; - res = DUMMY_REP; - prob = probs + IsRepG0 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - NORMALIZE_CHECK; - return DUMMY_REP; - } - else - { - UPDATE_1_CHECK; - } - } - else - { - UPDATE_1_CHECK; - prob = probs + IsRepG1 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - } - else - { - UPDATE_1_CHECK; - prob = probs + IsRepG2 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - } - else - { - UPDATE_1_CHECK; - } - } - } - state = kNumStates; - prob = probs + RepLenCoder; - } - { - unsigned limit, offset; - CLzmaProb *probLen = prob + LenChoice; - IF_BIT_0_CHECK(probLen) - { - UPDATE_0_CHECK; - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - limit = 1 << kLenNumLowBits; - } - else - { - UPDATE_1_CHECK; - probLen = prob + LenChoice2; - IF_BIT_0_CHECK(probLen) - { - UPDATE_0_CHECK; - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - limit = 1 << kLenNumMidBits; - } - else - { - UPDATE_1_CHECK; - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit = 1 << kLenNumHighBits; - } - } - TREE_DECODE_CHECK(probLen, limit, len); - len += offset; - } - - if (state < 4) - { - unsigned posSlot; - prob = probs + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << - kNumPosSlotBits); - TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); - if (posSlot >= kStartPosModelIndex) - { - int numDirectBits = ((posSlot >> 1) - 1); - - /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ - - if (posSlot < kEndPosModelIndex) - { - prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; - } - else - { - numDirectBits -= kNumAlignBits; - do - { - NORMALIZE_CHECK - range >>= 1; - code -= range & (((code - range) >> 31) - 1); - /* if (code >= range) code -= range; */ - } - while (--numDirectBits != 0); - prob = probs + Align; - numDirectBits = kNumAlignBits; - } - { - unsigned i = 1; - do - { - GET_BIT_CHECK(prob + i, i); - } - while (--numDirectBits != 0); - } - } - } - } - } - NORMALIZE_CHECK; - return res; -} - -static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) -{ - p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); - p->range = 0xFFFFFFFF; - p->needFlush = 0; -} - -void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) -{ - p->needFlush = 1; - p->remainLen = 0; - p->tempBufSize = 0; - - if (initDic) - { - p->processedPos = 0; - p->checkDicSize = 0; - p->needInitState = 1; - } - if (initState) - p->needInitState = 1; -} - -void LzmaDec_Init(CLzmaDec *p) -{ - p->dicPos = 0; - LzmaDec_InitDicAndState(p, True, True); -} - -static void LzmaDec_InitStateReal(CLzmaDec *p) -{ - UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); - UInt32 i; - CLzmaProb *probs = p->probs; - for (i = 0; i < numProbs; i++) - probs[i] = kBitModelTotal >> 1; - p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; - p->state = 0; - p->needInitState = 0; -} - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, - ELzmaFinishMode finishMode, ELzmaStatus *status) -{ - SizeT inSize = *srcLen; - (*srcLen) = 0; - LzmaDec_WriteRem(p, dicLimit); - - *status = LZMA_STATUS_NOT_SPECIFIED; - - while (p->remainLen != kMatchSpecLenStart) - { - int checkEndMarkNow; - - if (p->needFlush != 0) - { - for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) - p->tempBuf[p->tempBufSize++] = *src++; - if (p->tempBufSize < RC_INIT_SIZE) - { - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (p->tempBuf[0] != 0) - return SZ_ERROR_DATA; - - LzmaDec_InitRc(p, p->tempBuf); - p->tempBufSize = 0; - } - - checkEndMarkNow = 0; - if (p->dicPos >= dicLimit) - { - if (p->remainLen == 0 && p->code == 0) - { - *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; - return SZ_OK; - } - if (finishMode == LZMA_FINISH_ANY) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_OK; - } - if (p->remainLen != 0) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - checkEndMarkNow = 1; - } - - if (p->needInitState) - LzmaDec_InitStateReal(p); - - if (p->tempBufSize == 0) - { - SizeT processed; - const Byte *bufLimit; - if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) - { - int dummyRes = LzmaDec_TryDummy(p, src, inSize); - if (dummyRes == DUMMY_ERROR) - { - memcpy(p->tempBuf, src, inSize); - p->tempBufSize = (unsigned)inSize; - (*srcLen) += inSize; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - bufLimit = src; - } - else - bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; - p->buf = src; - if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) - return SZ_ERROR_DATA; - processed = (SizeT)(p->buf - src); - (*srcLen) += processed; - src += processed; - inSize -= processed; - } - else - { - unsigned rem = p->tempBufSize, lookAhead = 0; - while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) - p->tempBuf[rem++] = src[lookAhead++]; - p->tempBufSize = rem; - if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) - { - int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); - if (dummyRes == DUMMY_ERROR) - { - (*srcLen) += lookAhead; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - } - p->buf = p->tempBuf; - if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) - return SZ_ERROR_DATA; - lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); - (*srcLen) += lookAhead; - src += lookAhead; - inSize -= lookAhead; - p->tempBufSize = 0; - } - } - if (p->code == 0) - *status = LZMA_STATUS_FINISHED_WITH_MARK; - return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; -} - -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) -{ - SizeT outSize = *destLen; - SizeT inSize = *srcLen; - *srcLen = *destLen = 0; - for (;;) - { - SizeT inSizeCur = inSize, outSizeCur, dicPos; - ELzmaFinishMode curFinishMode; - SRes res; - if (p->dicPos == p->dicBufSize) - p->dicPos = 0; - dicPos = p->dicPos; - if (outSize > p->dicBufSize - dicPos) - { - outSizeCur = p->dicBufSize; - curFinishMode = LZMA_FINISH_ANY; - } - else - { - outSizeCur = dicPos + outSize; - curFinishMode = finishMode; - } - - res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); - src += inSizeCur; - inSize -= inSizeCur; - *srcLen += inSizeCur; - outSizeCur = p->dicPos - dicPos; - memcpy(dest, p->dic + dicPos, outSizeCur); - dest += outSizeCur; - outSize -= outSizeCur; - *destLen += outSizeCur; - if (res != 0) - return res; - if (outSizeCur == 0 || outSize == 0) - return SZ_OK; - } -} - -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->probs); - p->probs = 0; -} - -static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->dic); - p->dic = 0; -} - -void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) -{ - LzmaDec_FreeProbs(p, alloc); - LzmaDec_FreeDict(p, alloc); -} - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) -{ - UInt32 dicSize; - Byte d; - - if (size < LZMA_PROPS_SIZE) - return SZ_ERROR_UNSUPPORTED; - else - dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); - - if (dicSize < LZMA_DIC_MIN) - dicSize = LZMA_DIC_MIN; - p->dicSize = dicSize; - - d = data[0]; - if (d >= (9 * 5 * 5)) - return SZ_ERROR_UNSUPPORTED; - - p->lc = d % 9; - d /= 9; - p->pb = d / 5; - p->lp = d % 5; - - return SZ_OK; -} - -static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) -{ - UInt32 numProbs = LzmaProps_GetNumProbs(propNew); - if (p->probs == 0 || numProbs != p->numProbs) - { - LzmaDec_FreeProbs(p, alloc); - p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); - p->numProbs = numProbs; - if (p->probs == 0) - return SZ_ERROR_MEM; - } - return SZ_OK; -} - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -{ - CLzmaProps propNew; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); - p->prop = propNew; - return SZ_OK; -} - -SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -{ - CLzmaProps propNew; - SizeT dicBufSize; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); - dicBufSize = propNew.dicSize; - if (p->dic == 0 || dicBufSize != p->dicBufSize) - { - LzmaDec_FreeDict(p, alloc); - p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); - if (p->dic == 0) - { - LzmaDec_FreeProbs(p, alloc); - return SZ_ERROR_MEM; - } - } - p->dicBufSize = dicBufSize; - p->prop = propNew; - return SZ_OK; -} - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc) -{ - CLzmaDec p; - SRes res; - SizeT inSize = *srcLen; - SizeT outSize = *destLen; - *srcLen = *destLen = 0; - if (inSize < RC_INIT_SIZE) - return SZ_ERROR_INPUT_EOF; - - LzmaDec_Construct(&p); - res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); - if (res != 0) - return res; - p.dic = dest; - p.dicBufSize = outSize; - - LzmaDec_Init(&p); - - *srcLen = inSize; - res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); - - if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) - res = SZ_ERROR_INPUT_EOF; - - (*destLen) = p.dicPos; - LzmaDec_FreeProbs(&p, alloc); - return res; -} - diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.h deleted file mode 100644 index ad7d7057a4..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.h +++ /dev/null @@ -1,223 +0,0 @@ -/* LzmaDec.h -- LZMA Decoder -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZMADEC_H -#define __LZMADEC_H - -#include "Types.h" - -/* #define _LZMA_PROB32 */ -/* _LZMA_PROB32 can increase the speed on some CPUs, - but memory usage for CLzmaDec::probs will be doubled in that case */ - -#ifdef _LZMA_PROB32 -#define CLzmaProb UInt32 -#else -#define CLzmaProb UInt16 -#endif - - -/* ---------- LZMA Properties ---------- */ - -#define LZMA_PROPS_SIZE 5 - -typedef struct _CLzmaProps -{ - unsigned lc, lp, pb; - UInt32 dicSize; -} CLzmaProps; - -/* LzmaProps_Decode - decodes properties -Returns: - SZ_OK - SZ_ERROR_UNSUPPORTED - Unsupported properties -*/ - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); - - -/* ---------- LZMA Decoder state ---------- */ - -/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. - Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ - -#define LZMA_REQUIRED_INPUT_MAX 20 - -typedef struct -{ - CLzmaProps prop; - CLzmaProb *probs; - Byte *dic; - const Byte *buf; - UInt32 range, code; - SizeT dicPos; - SizeT dicBufSize; - UInt32 processedPos; - UInt32 checkDicSize; - unsigned state; - UInt32 reps[4]; - unsigned remainLen; - int needFlush; - int needInitState; - UInt32 numProbs; - unsigned tempBufSize; - Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; -} CLzmaDec; - -#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } - -void LzmaDec_Init(CLzmaDec *p); - -/* There are two types of LZMA streams: - 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. - 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ - -typedef enum -{ - LZMA_FINISH_ANY, /* finish at any point */ - LZMA_FINISH_END /* block must be finished at the end */ -} ELzmaFinishMode; - -/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! - - You must use LZMA_FINISH_END, when you know that current output buffer - covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. - - If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, - and output value of destLen will be less than output buffer size limit. - You can check status result also. - - You can use multiple checks to test data integrity after full decompression: - 1) Check Result and "status" variable. - 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. - 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. - You must use correct finish mode in that case. */ - -typedef enum -{ - LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ - LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ - LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ - LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ -} ELzmaStatus; - -/* ELzmaStatus is used only as output value for function call */ - - -/* ---------- Interfaces ---------- */ - -/* There are 3 levels of interfaces: - 1) Dictionary Interface - 2) Buffer Interface - 3) One Call Interface - You can select any of these interfaces, but don't mix functions from different - groups for same object. */ - - -/* There are two variants to allocate state for Dictionary Interface: - 1) LzmaDec_Allocate / LzmaDec_Free - 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs - You can use variant 2, if you set dictionary buffer manually. - For Buffer Interface you must always use variant 1. - -LzmaDec_Allocate* can return: - SZ_OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties -*/ - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); - -SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); - -/* ---------- Dictionary Interface ---------- */ - -/* You can use it, if you want to eliminate the overhead for data copying from - dictionary to some other external buffer. - You must work with CLzmaDec variables directly in this interface. - - STEPS: - LzmaDec_Constr() - LzmaDec_Allocate() - for (each new stream) - { - LzmaDec_Init() - while (it needs more decompression) - { - LzmaDec_DecodeToDic() - use data from CLzmaDec::dic and update CLzmaDec::dicPos - } - } - LzmaDec_Free() -*/ - -/* LzmaDec_DecodeToDic - - The decoding to internal dictionary buffer (CLzmaDec::dic). - You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! - -finishMode: - It has meaning only if the decoding reaches output limit (dicLimit). - LZMA_FINISH_ANY - Decode just dicLimit bytes. - LZMA_FINISH_END - Stream must be finished after dicLimit. - -Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_NEEDS_MORE_INPUT - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error -*/ - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- Buffer Interface ---------- */ - -/* It's zlib-like interface. - See LzmaDec_DecodeToDic description for information about STEPS and return results, - but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need - to work with CLzmaDec variables manually. - -finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). -*/ - -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- One Call Interface ---------- */ - -/* LzmaDecode - -finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - -Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). -*/ - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc); - -#endif diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Types.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Types.h deleted file mode 100644 index 30b16e3bb0..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Types.h +++ /dev/null @@ -1,231 +0,0 @@ -/** @file - Types.h - - Based on LZMA SDK 4.65: - Types.h -- Basic types - 2008-11-23 : Igor Pavlov : Public domain - - Copyright (c) 2009, Intel 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 __7Z_TYPES_H -#define __7Z_TYPES_H - -#ifdef EFIAPI - -#include "UefiLzma.h" - -#else - -#include - -#ifdef _WIN32 -#include -#endif - -#endif - -#define SZ_OK 0 - -#define SZ_ERROR_DATA 1 -#define SZ_ERROR_MEM 2 -#define SZ_ERROR_CRC 3 -#define SZ_ERROR_UNSUPPORTED 4 -#define SZ_ERROR_PARAM 5 -#define SZ_ERROR_INPUT_EOF 6 -#define SZ_ERROR_OUTPUT_EOF 7 -#define SZ_ERROR_READ 8 -#define SZ_ERROR_WRITE 9 -#define SZ_ERROR_PROGRESS 10 -#define SZ_ERROR_FAIL 11 -#define SZ_ERROR_THREAD 12 - -#define SZ_ERROR_ARCHIVE 16 -#define SZ_ERROR_NO_ARCHIVE 17 - -typedef int SRes; - -#ifdef _WIN32 -typedef DWORD WRes; -#else -typedef int WRes; -#endif - -#ifndef RINOK -#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } -#endif - -typedef unsigned char Byte; -typedef short Int16; -typedef unsigned short UInt16; - -#ifdef _LZMA_UINT32_IS_ULONG -typedef long Int32; -typedef unsigned long UInt32; -#else -typedef int Int32; -typedef unsigned int UInt32; -#endif - -#ifdef _SZ_NO_INT_64 - -/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. - NOTES: Some code will work incorrectly in that case! */ - -typedef long Int64; -typedef unsigned long UInt64; - -#else - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else -typedef long long int Int64; -typedef unsigned long long int UInt64; -#endif - -#endif - -#ifdef _LZMA_NO_SYSTEM_SIZE_T -typedef UInt32 SizeT; -#else -typedef size_t SizeT; -#endif - -typedef int Bool; -#define True 1 -#define False 0 - - -#ifdef _MSC_VER - -#if _MSC_VER >= 1300 -#define MY_NO_INLINE __declspec(noinline) -#else -#define MY_NO_INLINE -#endif - -#define MY_CDECL __cdecl -#define MY_STD_CALL __stdcall -#define MY_FAST_CALL MY_NO_INLINE __fastcall - -#else - -#define MY_CDECL -#define MY_STD_CALL -#define MY_FAST_CALL - -#endif - - -/* The following interfaces use first parameter as pointer to structure */ - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) < input(*size)) is allowed */ -} ISeqInStream; - -/* it can return SZ_ERROR_INPUT_EOF */ -SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); -SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); -SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); - -typedef struct -{ - size_t (*Write)(void *p, const void *buf, size_t size); - /* Returns: result - the number of actually written bytes. - (result < size) means error */ -} ISeqOutStream; - -typedef enum -{ - SZ_SEEK_SET = 0, - SZ_SEEK_CUR = 1, - SZ_SEEK_END = 2 -} ESzSeek; - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ISeekInStream; - -typedef struct -{ - SRes (*Look)(void *p, void **buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) > input(*size)) is not allowed - (output(*size) < input(*size)) is allowed */ - SRes (*Skip)(void *p, size_t offset); - /* offset must be <= output(*size) of Look */ - - SRes (*Read)(void *p, void *buf, size_t *size); - /* reads directly (without buffer). It's same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ILookInStream; - -SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); -SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); - -/* reads via ILookInStream::Read */ -SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); -SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); - -#define LookToRead_BUF_SIZE (1 << 14) - -typedef struct -{ - ILookInStream s; - ISeekInStream *realStream; - size_t pos; - size_t size; - Byte buf[LookToRead_BUF_SIZE]; -} CLookToRead; - -void LookToRead_CreateVTable(CLookToRead *p, int lookahead); -void LookToRead_Init(CLookToRead *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToLook; - -void SecToLook_CreateVTable(CSecToLook *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToRead; - -void SecToRead_CreateVTable(CSecToRead *p); - -typedef struct -{ - SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); - /* Returns: result. (result != SZ_OK) means break. - Value (UInt64)(Int64)-1 for size means unknown value. */ -} ICompressProgress; - -typedef struct -{ - void *(*Alloc)(void *p, size_t size); - void (*Free)(void *p, void *address); /* address can be 0 */ -} ISzAlloc; - -#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) -#define IAlloc_Free(p, a) (p)->Free((p), a) - -#endif diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/history.txt b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/history.txt deleted file mode 100644 index 9bed5ebbef..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/history.txt +++ /dev/null @@ -1,236 +0,0 @@ -HISTORY of the LZMA SDK ------------------------ - -4.65 2009-02-03 -------------------------- -- Some minor fixes - - -4.63 2008-12-31 -------------------------- -- Some minor fixes - - -4.61 beta 2008-11-23 -------------------------- -- The bug in ANSI-C LZMA Decoder was fixed: - If encoded stream was corrupted, decoder could access memory - outside of allocated range. -- Some changes in ANSI-C 7z Decoder interfaces. -- LZMA SDK is placed in the public domain. - - -4.60 beta 2008-08-19 -------------------------- -- Some minor fixes. - - -4.59 beta 2008-08-13 -------------------------- -- The bug was fixed: - LZMA Encoder in fast compression mode could access memory outside of - allocated range in some rare cases. - - -4.58 beta 2008-05-05 -------------------------- -- ANSI-C LZMA Decoder was rewritten for speed optimizations. -- ANSI-C LZMA Encoder was included to LZMA SDK. -- C++ LZMA code now is just wrapper over ANSI-C code. - - -4.57 2007-12-12 -------------------------- -- Speed optimizations in Ñ++ LZMA Decoder. -- Small changes for more compatibility with some C/C++ compilers. - - -4.49 beta 2007-07-05 -------------------------- -- .7z ANSI-C Decoder: - - now it supports BCJ and BCJ2 filters - - now it supports files larger than 4 GB. - - now it supports "Last Write Time" field for files. -- C++ code for .7z archives compressing/decompressing from 7-zip - was included to LZMA SDK. - - -4.43 2006-06-04 -------------------------- -- Small changes for more compatibility with some C/C++ compilers. - - -4.42 2006-05-15 -------------------------- -- Small changes in .h files in ANSI-C version. - - -4.39 beta 2006-04-14 -------------------------- -- The bug in versions 4.33b:4.38b was fixed: - C++ version of LZMA encoder could not correctly compress - files larger than 2 GB with HC4 match finder (-mfhc4). - - -4.37 beta 2005-04-06 -------------------------- -- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. - - -4.35 beta 2005-03-02 -------------------------- -- The bug was fixed in C++ version of LZMA Decoder: - If encoded stream was corrupted, decoder could access memory - outside of allocated range. - - -4.34 beta 2006-02-27 -------------------------- -- Compressing speed and memory requirements for compressing were increased -- LZMA now can use only these match finders: HC4, BT2, BT3, BT4 - - -4.32 2005-12-09 -------------------------- -- Java version of LZMA SDK was included - - -4.30 2005-11-20 -------------------------- -- Compression ratio was improved in -a2 mode -- Speed optimizations for compressing in -a2 mode -- -fb switch now supports values up to 273 -- The bug in 7z_C (7zIn.c) was fixed: - It used Alloc/Free functions from different memory pools. - So if program used two memory pools, it worked incorrectly. -- 7z_C: .7z format supporting was improved -- LZMA# SDK (C#.NET version) was included - - -4.27 (Updated) 2005-09-21 -------------------------- -- Some GUIDs/interfaces in C++ were changed. - IStream.h: - ISequentialInStream::Read now works as old ReadPart - ISequentialOutStream::Write now works as old WritePart - - -4.27 2005-08-07 -------------------------- -- The bug in LzmaDecodeSize.c was fixed: - if _LZMA_IN_CB and _LZMA_OUT_READ were defined, - decompressing worked incorrectly. - - -4.26 2005-08-05 -------------------------- -- Fixes in 7z_C code and LzmaTest.c: - previous versions could work incorrectly, - if malloc(0) returns 0 - - -4.23 2005-06-29 -------------------------- -- Small fixes in C++ code - - -4.22 2005-06-10 -------------------------- -- Small fixes - - -4.21 2005-06-08 -------------------------- -- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed -- New additional version of ANSI-C LZMA Decoder with zlib-like interface: - - LzmaStateDecode.h - - LzmaStateDecode.c - - LzmaStateTest.c -- ANSI-C LZMA Decoder now can decompress files larger than 4 GB - - -4.17 2005-04-18 -------------------------- -- New example for RAM->RAM compressing/decompressing: - LZMA + BCJ (filter for x86 code): - - LzmaRam.h - - LzmaRam.cpp - - LzmaRamDecode.h - - LzmaRamDecode.c - - -f86 switch for lzma.exe - - -4.16 2005-03-29 -------------------------- -- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): - If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, - decoder could access memory outside of allocated range. -- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). - Old version of LZMA Decoder now is in file LzmaDecodeSize.c. - LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c -- Small speed optimization in LZMA C++ code -- filter for SPARC's code was added -- Simplified version of .7z ANSI-C Decoder was included - - -4.06 2004-09-05 -------------------------- -- The bug in v4.05 was fixed: - LZMA-Encoder didn't release output stream in some cases. - - -4.05 2004-08-25 -------------------------- -- Source code of filters for x86, IA-64, ARM, ARM-Thumb - and PowerPC code was included to SDK -- Some internal minor changes - - -4.04 2004-07-28 -------------------------- -- More compatibility with some C++ compilers - - -4.03 2004-06-18 -------------------------- -- "Benchmark" command was added. It measures compressing - and decompressing speed and shows rating values. - Also it checks hardware errors. - - -4.02 2004-06-10 -------------------------- -- C++ LZMA Encoder/Decoder code now is more portable - and it can be compiled by GCC on Linux. - - -4.01 2004-02-15 -------------------------- -- Some detection of data corruption was enabled. - LzmaDecode.c / RangeDecoderReadByte - ..... - { - rd->ExtraBytes = 1; - return 0xFF; - } - - -4.00 2004-02-13 -------------------------- -- Original version of LZMA SDK - - - -HISTORY of the LZMA -------------------- - 2001-2008: Improvements to LZMA compressing/decompressing code, - keeping compatibility with original LZMA format - 1996-2001: Development of LZMA compression format - - Some milestones: - - 2001-08-30: LZMA compression was added to 7-Zip - 1999-01-02: First version of 7-Zip was released - - -End of document diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/lzma.txt b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/lzma.txt deleted file mode 100644 index d4f4af929a..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/lzma.txt +++ /dev/null @@ -1,594 +0,0 @@ -LZMA SDK 4.65 -------------- - -LZMA SDK provides the documentation, samples, header files, libraries, -and tools you need to develop applications that use LZMA compression. - -LZMA is default and general compression method of 7z format -in 7-Zip compression program (www.7-zip.org). LZMA provides high -compression ratio and very fast decompression. - -LZMA is an improved version of famous LZ77 compression algorithm. -It was improved in way of maximum increasing of compression ratio, -keeping high decompression speed and low memory requirements for -decompressing. - - - -LICENSE -------- - -LZMA SDK is written and placed in the public domain by Igor Pavlov. - - -LZMA SDK Contents ------------------ - -LZMA SDK includes: - - - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing - - Compiled file->file LZMA compressing/decompressing program for Windows system - - -UNIX/Linux version ------------------- -To compile C++ version of file->file LZMA encoding, go to directory -C++/7zip/Compress/LZMA_Alone -and call make to recompile it: - make -f makefile.gcc clean all - -In some UNIX/Linux versions you must compile LZMA with static libraries. -To compile with static libraries, you can use -LIB = -lm -static - - -Files ---------------------- -lzma.txt - LZMA SDK description (this file) -7zFormat.txt - 7z Format description -7zC.txt - 7z ANSI-C Decoder description -methods.txt - Compression method IDs for .7z -lzma.exe - Compiled file->file LZMA encoder/decoder for Windows -history.txt - history of the LZMA SDK - - -Source code structure ---------------------- - -C/ - C files - 7zCrc*.* - CRC code - Alloc.* - Memory allocation functions - Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code - LzFind.* - Match finder for LZ (LZMA) encoders - LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding - LzHash.h - Additional file for LZ match finder - LzmaDec.* - LZMA decoding - LzmaEnc.* - LZMA encoding - LzmaLib.* - LZMA Library for DLL calling - Types.h - Basic types for another .c files - Threads.* - The code for multithreading. - - LzmaLib - LZMA Library (.DLL for Windows) - - LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). - - Archive - files related to archiving - 7z - 7z ANSI-C Decoder - -CPP/ -- CPP files - - Common - common files for C++ projects - Windows - common files for Windows related code - - 7zip - files related to 7-Zip Project - - Common - common files for 7-Zip - - Compress - files related to compression/decompression - - Copy - Copy coder - RangeCoder - Range Coder (special code of compression/decompression) - LZMA - LZMA compression/decompression on C++ - LZMA_Alone - file->file LZMA compression/decompression - Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code - - Archive - files related to archiving - - Common - common files for archive handling - 7z - 7z C++ Encoder/Decoder - - Bundles - Modules that are bundles of other modules - - Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 - Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 - Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. - - UI - User Interface files - - Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll - Common - Common UI files - Console - Code for console archiver - - - -CS/ - C# files - 7zip - Common - some common files for 7-Zip - Compress - files related to compression/decompression - LZ - files related to LZ (Lempel-Ziv) compression algorithm - LZMA - LZMA compression/decompression - LzmaAlone - file->file LZMA compression/decompression - RangeCoder - Range Coder (special code of compression/decompression) - -Java/ - Java files - SevenZip - Compression - files related to compression/decompression - LZ - files related to LZ (Lempel-Ziv) compression algorithm - LZMA - LZMA compression/decompression - RangeCoder - Range Coder (special code of compression/decompression) - - -C/C++ source code of LZMA SDK is part of 7-Zip project. -7-Zip source code can be downloaded from 7-Zip's SourceForge page: - - http://sourceforge.net/projects/sevenzip/ - - - -LZMA features -------------- - - Variable dictionary size (up to 1 GB) - - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - - Estimated decompressing speed: - - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 - - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC - - Small memory requirements for decompressing (16 KB + DictionarySize) - - Small code size for decompressing: 5-8 KB - -LZMA decoder uses only integer operations and can be -implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). - -Some critical operations that affect the speed of LZMA decompression: - 1) 32*16 bit integer multiply - 2) Misspredicted branches (penalty mostly depends from pipeline length) - 3) 32-bit shift and arithmetic operations - -The speed of LZMA decompressing mostly depends from CPU speed. -Memory speed has no big meaning. But if your CPU has small data cache, -overall weight of memory speed will slightly increase. - - -How To Use ----------- - -Using LZMA encoder/decoder executable --------------------------------------- - -Usage: LZMA inputFile outputFile [...] - - e: encode file - - d: decode file - - b: Benchmark. There are two tests: compressing and decompressing - with LZMA method. Benchmark shows rating in MIPS (million - instructions per second). Rating value is calculated from - measured speed and it is normalized with Intel's Core 2 results. - Also Benchmark checks possible hardware errors (RAM - errors in most cases). Benchmark uses these settings: - (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. - Also you can change the number of iterations. Example for 30 iterations: - LZMA b 30 - Default number of iterations is 10. - - - - - -a{N}: set compression mode 0 = fast, 1 = normal - default: 1 (normal) - - d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) - The maximum value for dictionary size is 1 GB = 2^30 bytes. - Dictionary size is calculated as DictionarySize = 2^N bytes. - For decompressing file compressed by LZMA method with dictionary - size D = 2^N you need about D bytes of memory (RAM). - - -fb{N}: set number of fast bytes - [5, 273], default: 128 - Usually big number gives a little bit better compression ratio - and slower compression process. - - -lc{N}: set number of literal context bits - [0, 8], default: 3 - Sometimes lc=4 gives gain for big files. - - -lp{N}: set number of literal pos bits - [0, 4], default: 0 - lp switch is intended for periodical data when period is - equal 2^N. For example, for 32-bit (4 bytes) - periodical data you can use lp=2. Often it's better to set lc0, - if you change lp switch. - - -pb{N}: set number of pos bits - [0, 4], default: 2 - pb switch is intended for periodical data - when period is equal 2^N. - - -mf{MF_ID}: set Match Finder. Default: bt4. - Algorithms from hc* group doesn't provide good compression - ratio, but they often works pretty fast in combination with - fast mode (-a0). - - Memory requirements depend from dictionary size - (parameter "d" in table below). - - MF_ID Memory Description - - bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. - bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. - bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. - hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. - - -eos: write End Of Stream marker. By default LZMA doesn't write - eos marker, since LZMA decoder knows uncompressed size - stored in .lzma file header. - - -si: Read data from stdin (it will write End Of Stream marker). - -so: Write data to stdout - - -Examples: - -1) LZMA e file.bin file.lzma -d16 -lc0 - -compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) -and 0 literal context bits. -lc0 allows to reduce memory requirements -for decompression. - - -2) LZMA e file.bin file.lzma -lc0 -lp2 - -compresses file.bin to file.lzma with settings suitable -for 32-bit periodical data (for example, ARM or MIPS code). - -3) LZMA d file.lzma file.bin - -decompresses file.lzma to file.bin. - - -Compression ratio hints ------------------------ - -Recommendations ---------------- - -To increase the compression ratio for LZMA compressing it's desirable -to have aligned data (if it's possible) and also it's desirable to locate -data in such order, where code is grouped in one place and data is -grouped in other place (it's better than such mixing: code, data, code, -data, ...). - - -Filters -------- -You can increase the compression ratio for some data types, using -special filters before compressing. For example, it's possible to -increase the compression ratio on 5-10% for code for those CPU ISAs: -x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. - -You can find C source code of such filters in C/Bra*.* files - -You can check the compression ratio gain of these filters with such -7-Zip commands (example for ARM code): -No filter: - 7z a a1.7z a.bin -m0=lzma - -With filter for little-endian ARM code: - 7z a a2.7z a.bin -m0=arm -m1=lzma - -It works in such manner: -Compressing = Filter_encoding + LZMA_encoding -Decompressing = LZMA_decoding + Filter_decoding - -Compressing and decompressing speed of such filters is very high, -so it will not increase decompressing time too much. -Moreover, it reduces decompression time for LZMA_decoding, -since compression ratio with filtering is higher. - -These filters convert CALL (calling procedure) instructions -from relative offsets to absolute addresses, so such data becomes more -compressible. - -For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. - - -LZMA compressed file format ---------------------------- -Offset Size Description - 0 1 Special LZMA properties (lc,lp, pb in encoded form) - 1 4 Dictionary size (little endian) - 5 8 Uncompressed size (little endian). -1 means unknown size - 13 Compressed data - - -ANSI-C LZMA Decoder -~~~~~~~~~~~~~~~~~~~ - -Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. -If you want to use old interfaces you can download previous version of LZMA SDK -from sourceforge.net site. - -To use ANSI-C LZMA Decoder you need the following files: -1) LzmaDec.h + LzmaDec.c + Types.h -LzmaUtil/LzmaUtil.c is example application that uses these files. - - -Memory requirements for LZMA decoding -------------------------------------- - -Stack usage of LZMA decoding function for local variables is not -larger than 200-400 bytes. - -LZMA Decoder uses dictionary buffer and internal state structure. -Internal state structure consumes - state_size = (4 + (1.5 << (lc + lp))) KB -by default (lc=3, lp=0), state_size = 16 KB. - - -How To decompress data ----------------------- - -LZMA Decoder (ANSI-C version) now supports 2 interfaces: -1) Single-call Decompressing -2) Multi-call State Decompressing (zlib-like interface) - -You must use external allocator: -Example: -void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } -void SzFree(void *p, void *address) { p = p; free(address); } -ISzAlloc alloc = { SzAlloc, SzFree }; - -You can use p = p; operator to disable compiler warnings. - - -Single-call Decompressing -------------------------- -When to use: RAM->RAM decompressing -Compile files: LzmaDec.h + LzmaDec.c + Types.h -Compile defines: no defines -Memory Requirements: - - Input buffer: compressed size - - Output buffer: uncompressed size - - LZMA Internal Structures: state_size (16 KB for default settings) - -Interface: - int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc); - In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size - propData - LZMA properties (5 bytes) - propSize - size of propData buffer (5 bytes) - finishMode - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - You can use LZMA_FINISH_END, when you know that - current output buffer covers last bytes of stream. - alloc - Memory allocator. - - Out: - destLen - processed output size - srcLen - processed input size - - Output: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). - - If LZMA decoder sees end_marker before reaching output limit, it returns OK result, - and output value of destLen will be less than output buffer size limit. - - You can use multiple checks to test data integrity after full decompression: - 1) Check Result and "status" variable. - 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. - 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. - You must use correct finish mode in that case. */ - - -Multi-call State Decompressing (zlib-like interface) ----------------------------------------------------- - -When to use: file->file decompressing -Compile files: LzmaDec.h + LzmaDec.c + Types.h - -Memory Requirements: - - Buffer for input stream: any size (for example, 16 KB) - - Buffer for output stream: any size (for example, 16 KB) - - LZMA Internal Structures: state_size (16 KB for default settings) - - LZMA dictionary (dictionary size is encoded in LZMA properties header) - -1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: - unsigned char header[LZMA_PROPS_SIZE + 8]; - ReadFile(inFile, header, sizeof(header) - -2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties - - CLzmaDec state; - LzmaDec_Constr(&state); - res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); - if (res != SZ_OK) - return res; - -3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop - - LzmaDec_Init(&state); - for (;;) - { - ... - int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); - ... - } - - -4) Free all allocated structures - LzmaDec_Free(&state, &g_Alloc); - -For full code example, look at C/LzmaUtil/LzmaUtil.c code. - - -How To compress data --------------------- - -Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + -LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h - -Memory Requirements: - - (dictSize * 11.5 + 6 MB) + state_size - -Lzma Encoder can use two memory allocators: -1) alloc - for small arrays. -2) allocBig - for big arrays. - -For example, you can use Large RAM Pages (2 MB) in allocBig allocator for -better compression speed. Note that Windows has bad implementation for -Large RAM Pages. -It's OK to use same allocator for alloc and allocBig. - - -Single-call Compression with callbacks --------------------------------------- - -Check C/LzmaUtil/LzmaUtil.c as example, - -When to use: file->file decompressing - -1) you must implement callback structures for interfaces: -ISeqInStream -ISeqOutStream -ICompressProgress -ISzAlloc - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - - CFileSeqInStream inStream; - CFileSeqOutStream outStream; - - inStream.funcTable.Read = MyRead; - inStream.file = inFile; - outStream.funcTable.Write = MyWrite; - outStream.file = outFile; - - -2) Create CLzmaEncHandle object; - - CLzmaEncHandle enc; - - enc = LzmaEnc_Create(&g_Alloc); - if (enc == 0) - return SZ_ERROR_MEM; - - -3) initialize CLzmaEncProps properties; - - LzmaEncProps_Init(&props); - - Then you can change some properties in that structure. - -4) Send LZMA properties to LZMA Encoder - - res = LzmaEnc_SetProps(enc, &props); - -5) Write encoded properties to header - - Byte header[LZMA_PROPS_SIZE + 8]; - size_t headerSize = LZMA_PROPS_SIZE; - UInt64 fileSize; - int i; - - res = LzmaEnc_WriteProperties(enc, header, &headerSize); - fileSize = MyGetFileLength(inFile); - for (i = 0; i < 8; i++) - header[headerSize++] = (Byte)(fileSize >> (8 * i)); - MyWriteFileAndCheck(outFile, header, headerSize) - -6) Call encoding function: - res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, - NULL, &g_Alloc, &g_Alloc); - -7) Destroy LZMA Encoder Object - LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); - - -If callback function return some error code, LzmaEnc_Encode also returns that code. - - -Single-call RAM->RAM Compression --------------------------------- - -Single-call RAM->RAM Compression is similar to Compression with callbacks, -but you provide pointers to buffers instead of pointers to stream callbacks: - -HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, - ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); - -Return code: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) - - - -LZMA Defines ------------- - -_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. - -_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for - some structures will be doubled in that case. - -_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. - -_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. - - -C++ LZMA Encoder/Decoder -~~~~~~~~~~~~~~~~~~~~~~~~ -C++ LZMA code use COM-like interfaces. So if you want to use it, -you can study basics of COM/OLE. -C++ LZMA code is just wrapper over ANSI-C code. - - -C++ Notes -~~~~~~~~~~~~~~~~~~~~~~~~ -If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), -you must check that you correctly work with "new" operator. -7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. -So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: -operator new(size_t size) -{ - void *p = ::malloc(size); - if (p == 0) - throw CNewException(); - return p; -} -If you use MSCV that throws exception for "new" operator, you can compile without -"NewHandler.cpp". So standard exception will be used. Actually some code of -7-Zip catches any exception in internal code and converts it to HRESULT code. -So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. - ---- - -http://www.7-zip.org -http://www.7-zip.org/sdk.html -http://www.7-zip.org/support.html diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/UefiLzma.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/UefiLzma.h deleted file mode 100644 index 863b3ef66b..0000000000 --- a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/UefiLzma.h +++ /dev/null @@ -1,47 +0,0 @@ -/** @file - LZMA UEFI header file - - Allows LZMA code to build under UEFI (edk2) build environment - - Copyright (c) 2009, Intel 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 __UEFILZMA_H__ -#define __UEFILZMA_H__ - -#include -#include - -#ifdef _WIN32 -#undef _WIN32 -#endif - -#ifndef _SIZE_T_DEFINED -#if !defined(_WIN64) || defined(__GNUC__) -typedef unsigned int size_t; -#endif -#endif - -#ifdef _WIN64 -#undef _WIN64 -#endif - -#ifndef _PTRDIFF_T_DEFINED -typedef int ptrdiff_t; -#endif - -#define memcpy CopyMem -#define memmove CopyMem - -#define _LZMA_SIZE_OPT - -#endif // __UEFILZMA_H__ - diff --git a/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c b/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c deleted file mode 100644 index cfdd2f50d5..0000000000 --- a/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c +++ /dev/null @@ -1,468 +0,0 @@ -/** @file - Debug Library based on report status code library. - - Note that if the debug message length is larger than the maximum allowable - record length, then the debug message will be ignored directly. - - Copyright (c) 2006 - 2015, Intel 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 - -/** - Prints a debug message to the debug output device if the specified error level is enabled. - - If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function - GetDebugPrintErrorLevel (), then print the message specified by Format and the - associated variable argument list to the debug output device. - - If Format is NULL, then ASSERT(). - - If the length of the message string specificed by Format is larger than the maximum allowable - record length, then directly return and not print it. - - @param ErrorLevel The error level of the debug message. - @param Format Format string for the debug message to print. - @param ... Variable argument list whose contents are accessed - based on the format string specified by Format. - -**/ -VOID -EFIAPI -DebugPrint ( - IN UINTN ErrorLevel, - IN CONST CHAR8 *Format, - ... - ) -{ - UINT64 Buffer[(EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof (UINT64)) + 1]; - EFI_DEBUG_INFO *DebugInfo; - UINTN TotalSize; - UINTN DestBufferSize; - VA_LIST VaListMarker; - BASE_LIST BaseListMarker; - CHAR8 *FormatString; - BOOLEAN Long; - - // - // If Format is NULL, then ASSERT(). - // - ASSERT (Format != NULL); - - // - // Check driver Debug Level value and global debug level - // - if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { - return; - } - - // - // Compute the total size of the record. - // Note that the passing-in format string and variable parameters will be constructed to - // the following layout: - // - // Buffer->|------------------------| - // | Padding | 4 bytes - // DebugInfo->|------------------------| - // | EFI_DEBUG_INFO | sizeof(EFI_DEBUG_INFO) - // BaseListMarker->|------------------------| - // | ... | - // | variable arguments | 12 * sizeof (UINT64) - // | ... | - // |------------------------| - // | Format String | - // |------------------------|<- (UINT8 *)Buffer + sizeof(Buffer) - // - TotalSize = 4 + sizeof (EFI_DEBUG_INFO) + 12 * sizeof (UINT64) + AsciiStrSize (Format); - - // - // If the TotalSize is larger than the maximum record size, then return - // - if (TotalSize > sizeof (Buffer)) { - return; - } - - // - // Fill in EFI_DEBUG_INFO - // - // Here we skip the first 4 bytes of Buffer, because we must ensure BaseListMarker is - // 64-bit aligned, otherwise retrieving 64-bit parameter from BaseListMarker will cause - // exception on IPF. Buffer starts at 64-bit aligned address, so skipping 4 types (sizeof(EFI_DEBUG_INFO)) - // just makes address of BaseListMarker, which follows DebugInfo, 64-bit aligned. - // - DebugInfo = (EFI_DEBUG_INFO *)(Buffer) + 1; - DebugInfo->ErrorLevel = (UINT32)ErrorLevel; - BaseListMarker = (BASE_LIST)(DebugInfo + 1); - FormatString = (CHAR8 *)((UINT64 *)(DebugInfo + 1) + 12); - - // - // Copy the Format string into the record - // - // According to the content structure of Buffer shown above, the size of - // the FormatString buffer is the size of Buffer minus the Padding - // (4 bytes), minus the size of EFI_DEBUG_INFO, minus the size of - // variable arguments (12 * sizeof (UINT64)). - // - DestBufferSize = sizeof (Buffer) - 4 - sizeof (EFI_DEBUG_INFO) - 12 * sizeof (UINT64); - AsciiStrCpyS (FormatString, DestBufferSize / sizeof (CHAR8), Format); - - // - // The first 12 * sizeof (UINT64) bytes following EFI_DEBUG_INFO are for variable arguments - // of format in DEBUG string, which is followed by the DEBUG format string. - // Here we will process the variable arguments and pack them in this area. - // - VA_START (VaListMarker, Format); - for (; *Format != '\0'; Format++) { - // - // Only format with prefix % is processed. - // - if (*Format != '%') { - continue; - } - Long = FALSE; - // - // Parse Flags and Width - // - for (Format++; TRUE; Format++) { - if (*Format == '.' || *Format == '-' || *Format == '+' || *Format == ' ') { - // - // These characters in format field are omitted. - // - continue; - } - if (*Format >= '0' && *Format <= '9') { - // - // These characters in format field are omitted. - // - continue; - } - if (*Format == 'L' || *Format == 'l') { - // - // 'L" or "l" in format field means the number being printed is a UINT64 - // - Long = TRUE; - continue; - } - if (*Format == '*') { - // - // '*' in format field means the precision of the field is specified by - // a UINTN argument in the argument list. - // - BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN); - continue; - } - if (*Format == '\0') { - // - // Make no output if Format string terminates unexpectedly when - // looking up for flag, width, precision and type. - // - Format--; - } - // - // When valid argument type detected or format string terminates unexpectedly, - // the inner loop is done. - // - break; - } - - // - // Pack variable arguments into the storage area following EFI_DEBUG_INFO. - // - if ((*Format == 'p') && (sizeof (VOID *) > 4)) { - Long = TRUE; - } - if (*Format == 'p' || *Format == 'X' || *Format == 'x' || *Format == 'd' || *Format == 'u') { - if (Long) { - BASE_ARG (BaseListMarker, INT64) = VA_ARG (VaListMarker, INT64); - } else { - BASE_ARG (BaseListMarker, int) = VA_ARG (VaListMarker, int); - } - } else if (*Format == 's' || *Format == 'S' || *Format == 'a' || *Format == 'g' || *Format == 't') { - BASE_ARG (BaseListMarker, VOID *) = VA_ARG (VaListMarker, VOID *); - } else if (*Format == 'c') { - BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN); - } else if (*Format == 'r') { - BASE_ARG (BaseListMarker, RETURN_STATUS) = VA_ARG (VaListMarker, RETURN_STATUS); - } - - // - // If the converted BASE_LIST is larger than the 12 * sizeof (UINT64) allocated bytes, then ASSERT() - // This indicates that the DEBUG() macro is passing in more argument than can be handled by - // the EFI_DEBUG_INFO record - // - ASSERT ((CHAR8 *)BaseListMarker <= FormatString); - - // - // If the converted BASE_LIST is larger than the 12 * sizeof (UINT64) allocated bytes, then return - // - if ((CHAR8 *)BaseListMarker > FormatString) { - VA_END (VaListMarker); - return; - } - } - VA_END (VaListMarker); - - // - // Send the DebugInfo record - // - REPORT_STATUS_CODE_EX ( - EFI_DEBUG_CODE, - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_DC_UNSPECIFIED), - 0, - NULL, - &gEfiStatusCodeDataTypeDebugGuid, - DebugInfo, - TotalSize - ); -} - -/** - Prints an assert message containing a filename, line number, and description. - This may be followed by a breakpoint or a dead loop. - - Print a message of the form "ASSERT (): \n" - to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of - PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if - DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then - CpuDeadLoop() is called. If neither of these bits are set, then this function - returns immediately after the message is printed to the debug output device. - DebugAssert() must actively prevent recursion. If DebugAssert() is called while - processing another DebugAssert(), then DebugAssert() must return immediately. - - If FileName is NULL, then a string of "(NULL) Filename" is printed. - If Description is NULL, then a string of "(NULL) Description" is printed. - - @param FileName Pointer to the name of the source file that generated the assert condition. - @param LineNumber The line number in the source file that generated the assert condition - @param Description Pointer to the description of the assert condition. - -**/ -VOID -EFIAPI -DebugAssert ( - IN CONST CHAR8 *FileName, - IN UINTN LineNumber, - IN CONST CHAR8 *Description - ) -{ - UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof(UINT64)]; - EFI_DEBUG_ASSERT_DATA *AssertData; - UINTN HeaderSize; - UINTN TotalSize; - CHAR8 *Temp; - UINTN FileNameSize; - UINTN DescriptionSize; - - // - // Get string size - // - HeaderSize = sizeof (EFI_DEBUG_ASSERT_DATA); - FileNameSize = AsciiStrSize (FileName); - DescriptionSize = AsciiStrSize (Description); - - // - // Make sure it will all fit in the passed in buffer. - // - if (HeaderSize + FileNameSize + DescriptionSize > sizeof (Buffer)) { - // - // FileName + Description is too long to be filled into buffer. - // - if (HeaderSize + FileNameSize < sizeof (Buffer)) { - // - // Description has enough buffer to be truncated. - // - DescriptionSize = sizeof (Buffer) - HeaderSize - FileNameSize; - } else { - // - // FileName is too long to be filled into buffer. - // FileName will be truncated. Reserved one byte for Description NULL terminator. - // - DescriptionSize = 1; - FileNameSize = sizeof (Buffer) - HeaderSize - DescriptionSize; - } - } - - // - // Fill in EFI_DEBUG_ASSERT_DATA - // - AssertData = (EFI_DEBUG_ASSERT_DATA *)Buffer; - AssertData->LineNumber = (UINT32)LineNumber; - TotalSize = sizeof (EFI_DEBUG_ASSERT_DATA); - - // - // Copy Ascii FileName including NULL terminator. - // - Temp = CopyMem (AssertData + 1, FileName, FileNameSize); - Temp[FileNameSize - 1] = 0; - TotalSize += FileNameSize; - - // - // Copy Ascii Description include NULL terminator. - // - Temp = CopyMem (Temp + FileNameSize, Description, DescriptionSize); - Temp[DescriptionSize - 1] = 0; - TotalSize += DescriptionSize; - - REPORT_STATUS_CODE_EX ( - (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE), - 0, - NULL, - NULL, - AssertData, - TotalSize - ); - - // - // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings - // - if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { - CpuBreakpoint (); - } else if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { - CpuDeadLoop (); - } -} - - -/** - Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. - - This function fills Length bytes of Buffer with the value specified by - PcdDebugClearMemoryValue, and returns Buffer. - - If Buffer is NULL, then ASSERT(). - If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). - - @param Buffer Pointer to the target buffer to be filled with PcdDebugClearMemoryValue. - @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. - - @return Buffer Pointer to the target buffer filled with PcdDebugClearMemoryValue. - -**/ -VOID * -EFIAPI -DebugClearMemory ( - OUT VOID *Buffer, - IN UINTN Length - ) -{ - ASSERT (Buffer != NULL); - - return SetMem (Buffer, Length, PcdGet8 (PcdDebugClearMemoryValue)); -} - - -/** - Returns TRUE if ASSERT() macros are enabled. - - This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of - PcdDebugProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. - @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -DebugAssertEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); -} - - -/** - Returns TRUE if DEBUG() macros are enabled. - - This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of - PcdDebugProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. - @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -DebugPrintEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); -} - - -/** - Returns TRUE if DEBUG_CODE() macros are enabled. - - This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of - PcdDebugProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. - @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -DebugCodeEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); -} - - -/** - Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled. - - This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of - PcdDebugProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. - @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -DebugClearMemoryEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); -} - -/** - Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel. - - This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel. - - @retval TRUE Current ErrorLevel is supported. - @retval FALSE Current ErrorLevel is not supported. - -**/ -BOOLEAN -EFIAPI -DebugPrintLevelEnabled ( - IN CONST UINTN ErrorLevel - ) -{ - return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0); -} diff --git a/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf b/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf deleted file mode 100644 index 55446672d7..0000000000 --- a/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf +++ /dev/null @@ -1,54 +0,0 @@ -## @file -# Debug Library based on report status code library -# -# Debug Library for PEIMs and DXE drivers that sends debug messages to ReportStatusCode -# Copyright (c) 2006 - 2015, Intel 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 = PeiDxeDebugLibReportStatusCode - MODULE_UNI_FILE = PeiDxeDebugLibReportStatusCode.uni - FILE_GUID = bda39d3a-451b-4350-8266-81ab10fa0523 - MODULE_TYPE = PEIM - VERSION_STRING = 1.0 - LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER SMM_CORE PEIM SEC PEI_CORE UEFI_APPLICATION UEFI_DRIVER - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - DebugLib.c - - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - PcdLib - ReportStatusCodeLib - BaseMemoryLib - BaseLib - DebugPrintErrorLevelLib - -[Pcd] - gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES - -[Guids] - gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## GUID - diff --git a/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.uni b/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.uni deleted file mode 100644 index fe2abee431..0000000000 Binary files a/IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.c b/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.c deleted file mode 100644 index fc729a899c..0000000000 --- a/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.c +++ /dev/null @@ -1,50 +0,0 @@ -/** @file - This Library uses Framework RecoveryModule PPI to do system recovery. - - This library instance is no longer used and module using this library - class should update to directly locate EFI_PEI_RECOVERY_MODULE_PPI defined - in PI 1.2 specification. - -Copyright (c) 2006 - 2009, Intel 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 - -/** - Calling this function causes the system do recovery. - - @retval EFI_SUCESS Sucess to do recovery. - @retval Others Fail to do recovery. -**/ -EFI_STATUS -EFIAPI -PeiRecoverFirmware ( - VOID - ) -{ - EFI_STATUS Status; - EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; - - Status = PeiServicesLocatePpi ( - &gEfiPeiRecoveryModulePpiGuid, - 0, - NULL, - (VOID **)&PeiRecovery - ); - ASSERT_EFI_ERROR (Status); - - return PeiRecovery->LoadRecoveryCapsule ((EFI_PEI_SERVICES **) GetPeiServicesTablePointer(), PeiRecovery); -} - diff --git a/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf b/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf deleted file mode 100644 index 9bd321e178..0000000000 --- a/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf +++ /dev/null @@ -1,50 +0,0 @@ -## @file -# PEIM Recovery Library supports system recovery boot. -# -# This library instance is no longer used and module using this library -# class should update to directly locate EFI_PEI_RECOVERY_MODULE_PPI defined -# in PI 1.2 specification. -# -# 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 -# 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 = PeiRecoveryLib - MODULE_UNI_FILE = PeiRecoveryLib.uni - FILE_GUID = C0227547-0811-4cbb-ABEA-DECD22829122 - MODULE_TYPE = PEIM - VERSION_STRING = 1.0 - LIBRARY_CLASS = RecoveryLib|PEIM - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - PeiRecoveryLib.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - BaseLib - PeiServicesTablePointerLib - DebugLib - -[Ppis] - gEfiPeiRecoveryModulePpiGuid ## CONSUMES - - \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.uni b/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.uni deleted file mode 100644 index 11891e58e0..0000000000 Binary files a/IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.c b/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.c deleted file mode 100644 index d16e3cac24..0000000000 --- a/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.c +++ /dev/null @@ -1,51 +0,0 @@ -/** @file - This library provides API to invoke the S3 resume vector in the APCI Table in S3 resume mode. - - This library instance is no longer used and module using this library - class should update to directly locate EFI_PEI_S3_RESUME_PPI defined - in PI 1.2 specification. - -Copyright (c) 2006 - 2008, Intel 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 function is responsible for calling the S3 resume vector in the ACPI Tables. - - @retval EFI_SUCESS Success to restore config from S3. - @retval Others Fail to restore config from S3. -**/ -EFI_STATUS -EFIAPI -AcpiS3ResumeOs ( - VOID - ) -{ - EFI_STATUS Status; - EFI_PEI_S3_RESUME_PPI *S3Resume; - - Status = PeiServicesLocatePpi ( - &gEfiPeiS3ResumePpiGuid, - 0, - NULL, - (VOID **)&S3Resume - ); - ASSERT_EFI_ERROR (Status); - - return S3Resume->S3RestoreConfig ((EFI_PEI_SERVICES **) GetPeiServicesTablePointer()); -} - diff --git a/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf b/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf deleted file mode 100644 index b01e1860f4..0000000000 --- a/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf +++ /dev/null @@ -1,49 +0,0 @@ -## @file -# This library provides API to invoke the S3 resume vector in the ACPI Table in S3 resume mode. -# -# This library instance is no longer used and module using this library -# class should update to directly locate EFI_PEI_S3_RESUME_PPI defined -# in PI 1.2 specification. -# -# 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 -# 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 = PeiS3Lib - MODULE_UNI_FILE = PeiS3Lib.uni - FILE_GUID = EFB7D3A8-DEB9-4bed-B6D6-3B09BEEB835A - MODULE_TYPE = PEIM - VERSION_STRING = 1.0 - LIBRARY_CLASS = S3Lib|PEIM - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - PeiS3Lib.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - -[LibraryClasses] - PeiServicesTablePointerLib - DebugLib - -[Ppis] - gEfiPeiS3ResumePpiGuid ## CONSUMES - diff --git a/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.uni b/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.uni deleted file mode 100644 index dceb0011c9..0000000000 Binary files a/IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c b/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c deleted file mode 100644 index 9fb3b23282..0000000000 --- a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c +++ /dev/null @@ -1,187 +0,0 @@ -/** @file - This file include all platform action which can be customized by IBV/OEM. - -Copyright (c) 2004 - 2008, Intel 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 "BdsPlatform.h" - -// -// BDS Platform Functions -// -/** - Platform Bds init. Include the platform firmware vendor, revision - and so crc check. - -**/ -VOID -EFIAPI -PlatformBdsInit ( - VOID - ) -{ -} - -/** - Connect the predefined platform default console device. Always try to find - and enable the vga device if have. - - @param PlatformConsole Predefined 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. - @return Return the status of BdsLibConnectAllDefaultConsoles () - -**/ -EFI_STATUS -PlatformBdsConnectConsole ( - IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole - ) -{ - return EFI_SUCCESS; -} - -/** - Connect with predefined platform connect sequence, - the OEM/IBV can customize with their own connect sequence. -**/ -VOID -PlatformBdsConnectSequence ( - VOID - ) -{ -} - -/** - 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. - -**/ -VOID -PlatformBdsGetDriverOption ( - IN OUT LIST_ENTRY *BdsDriverLists - ) -{ -} - -/** - Perform the platform diagnostic, such like test memory. OEM/IBV also - can customize this function 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() - -**/ -VOID -PlatformBdsDiagnostics ( - IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, - IN BOOLEAN QuietBoot, - IN BASEM_MEMORY_TEST BaseMemoryTest - ) -{ -} - -/** - The function will execute 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() - -**/ -VOID -EFIAPI -PlatformBdsPolicyBehavior ( - IN LIST_ENTRY *DriverOptionList, - IN LIST_ENTRY *BootOptionList, - IN PROCESS_CAPSULES ProcessCapsules, - IN BASEM_MEMORY_TEST BaseMemoryTest - ) -{ -} - -/** - 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 also a platform implementation and can be customized by IBV/OEM. - - @param Option Pointer to Boot Option that succeeded to boot. - -**/ -VOID -EFIAPI -PlatformBdsBootSuccess ( - IN BDS_COMMON_OPTION *Option - ) -{ -} - -/** - 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. - -**/ -VOID -EFIAPI -PlatformBdsBootFail ( - IN BDS_COMMON_OPTION *Option, - IN EFI_STATUS Status, - IN CHAR16 *ExitData, - IN UINTN ExitDataSize - ) -{ -} - -/** - This function locks platform flash that is not allowed to be updated during normal boot path. - The flash layout is platform specific. -**/ -VOID -EFIAPI -PlatformBdsLockNonUpdatableFlash ( - VOID - ) -{ - return ; -} - - -/** - 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; -} diff --git a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h b/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h deleted file mode 100644 index 38ea72ee6c..0000000000 --- a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h +++ /dev/null @@ -1,28 +0,0 @@ -/** @file - Head file for BDS Platform specific code - -Copyright (c) 2004 - 2008, Intel 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 _BDS_PLATFORM_H_ -#define _BDS_PLATFORM_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - - -#endif // _BDS_PLATFORM_H diff --git a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLib.uni b/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLib.uni deleted file mode 100644 index 3ec1a92f63..0000000000 Binary files a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLib.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf b/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf deleted file mode 100644 index 37c98cff00..0000000000 --- a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf +++ /dev/null @@ -1,47 +0,0 @@ -## @file -# NULL implementation for PlatformBdsLib library class interfaces. -# -# 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 -# 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 = PlatformBdsLib - MODULE_UNI_FILE = PlatformBdsLib.uni - FILE_GUID = 143B5044-7C1B-4904-9778-EA16F1F3D554 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - BdsPlatform.c - PlatformData.c - BdsPlatform.h - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - BaseLib - MemoryAllocationLib - UefiBootServicesTableLib - BaseMemoryLib - DebugLib - PcdLib - GenericBdsLib \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformData.c b/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformData.c deleted file mode 100644 index 131efab4d9..0000000000 --- a/IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformData.c +++ /dev/null @@ -1,21 +0,0 @@ -/** @file - Defined the platform specific device path which will be used by - platform Bbd to perform the platform policy connect. - -Copyright (c) 2004 - 2008, Intel 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 "BdsPlatform.h" - -/// -/// Predefined platform default time out value -/// -UINT16 gPlatformBootTimeOutDefault = 10; diff --git a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLib.c b/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLib.c deleted file mode 100644 index c49dacaeb1..0000000000 --- a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLib.c +++ /dev/null @@ -1,493 +0,0 @@ -/** @file - API implementation for instance of Report Status Code Library. - - Copyright (c) 2006 - 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 "ReportStatusCodeLibInternal.h" - -/** - Converts a status code to an 8-bit POST code value. - - Converts the status code specified by CodeType and Value to an 8-bit POST code - and returns the 8-bit POST code in PostCode. If CodeType is an - EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode - are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits - 24..26 of Value., and TRUE is returned. Otherwise, FALSE is returned. - - If PostCode is NULL, then ASSERT(). - - @param CodeType The type of status code being converted. - @param Value The status code value being converted. - @param PostCode A pointer to the 8-bit POST code value to return. - - @retval TRUE The status code specified by CodeType and Value was converted - to an 8-bit POST code and returned in PostCode. - @retval FALSE The status code specified by CodeType and Value could not be - converted to an 8-bit POST code value. - -**/ -BOOLEAN -EFIAPI -CodeTypeToPostCode ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - OUT UINT8 *PostCode - ) -{ - // - // If PostCode is NULL, then ASSERT() - // - ASSERT (PostCode != NULL); - - // - // Convert Value to an 8 bit post code - // - if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || - ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ) { - *PostCode = (UINT8) ((((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5) | - (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f)); - return TRUE; - } - return FALSE; -} - - -/** - Extracts ASSERT() information from a status code structure. - - Converts the status code specified by CodeType, Value, and Data to the ASSERT() - arguments specified by Filename, Description, and LineNumber. If CodeType is - an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and - Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract - Filename, Description, and LineNumber from the optional data area of the - status code buffer specified by Data. The optional data area of Data contains - a Null-terminated ASCII string for the FileName, followed by a Null-terminated - ASCII string for the Description, followed by a 32-bit LineNumber. If the - ASSERT() information could be extracted from Data, then return TRUE. - Otherwise, FALSE is returned. - - If Data is NULL, then ASSERT(). - If Filename is NULL, then ASSERT(). - If Description is NULL, then ASSERT(). - If LineNumber is NULL, then ASSERT(). - - @param CodeType The type of status code being converted. - @param Value The status code value being converted. - @param Data Pointer to status code data buffer. - @param Filename Pointer to the source file name that generated the ASSERT(). - @param Description Pointer to the description of the ASSERT(). - @param LineNumber Pointer to source line number that generated the ASSERT(). - - @retval TRUE The status code specified by CodeType, Value, and Data was - converted ASSERT() arguments specified by Filename, Description, - and LineNumber. - @retval FALSE The status code specified by CodeType, Value, and Data could - not be converted to ASSERT() arguments. - -**/ -BOOLEAN -EFIAPI -ReportStatusCodeExtractAssertInfo ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - IN CONST EFI_STATUS_CODE_DATA *Data, - OUT CHAR8 **Filename, - OUT CHAR8 **Description, - OUT UINT32 *LineNumber - ) -{ - EFI_DEBUG_ASSERT_DATA *AssertData; - - ASSERT (Data != NULL); - ASSERT (Filename != NULL); - ASSERT (Description != NULL); - ASSERT (LineNumber != NULL); - - if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && - ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) && - ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) { - AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1); - *Filename = (CHAR8 *)(AssertData + 1); - *Description = *Filename + AsciiStrLen (*Filename) + 1; - *LineNumber = AssertData->LineNumber; - return TRUE; - } - return FALSE; -} - - -/** - Extracts DEBUG() information from a status code structure. - - Converts the status code specified by Data to the DEBUG() arguments specified - by ErrorLevel, Marker, and Format. If type GUID in Data is - EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and - Format from the optional data area of the status code buffer specified by Data. - The optional data area of Data contains a 32-bit ErrorLevel followed by Marker - which is 12 UINTN parameters, followed by a Null-terminated ASCII string for - the Format. If the DEBUG() information could be extracted from Data, then - return TRUE. Otherwise, FALSE is returned. - - If Data is NULL, then ASSERT(). - If ErrorLevel is NULL, then ASSERT(). - If Marker is NULL, then ASSERT(). - If Format is NULL, then ASSERT(). - - @param Data Pointer to status code data buffer. - @param ErrorLevel Pointer to error level mask for a debug message. - @param Marker Pointer to the variable argument list associated with Format. - @param Format Pointer to a Null-terminated ASCII format string of a - debug message. - - @retval TRUE The status code specified by Data was converted DEBUG() arguments - specified by ErrorLevel, Marker, and Format. - @retval FALSE The status code specified by Data could not be converted to - DEBUG() arguments. - -**/ -BOOLEAN -EFIAPI -ReportStatusCodeExtractDebugInfo ( - IN CONST EFI_STATUS_CODE_DATA *Data, - OUT UINT32 *ErrorLevel, - OUT BASE_LIST *Marker, - OUT CHAR8 **Format - ) -{ - EFI_DEBUG_INFO *DebugInfo; - - ASSERT (Data != NULL); - ASSERT (ErrorLevel != NULL); - ASSERT (Marker != NULL); - ASSERT (Format != NULL); - - // - // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE - // - if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) { - return FALSE; - } - - // - // Retrieve the debug information from the status code record - // - DebugInfo = (EFI_DEBUG_INFO *)(Data + 1); - - *ErrorLevel = DebugInfo->ErrorLevel; - - // - // The first 12 * sizeof (UINT64) bytes following EFI_DEBUG_INFO are for variable arguments - // of format in DEBUG string. Its address is returned in Marker and has to be 64-bit aligned. - // It must be noticed that EFI_DEBUG_INFO follows EFI_STATUS_CODE_DATA, whose size is - // 20 bytes. The size of EFI_DEBUG_INFO is 4 bytes, so we can ensure that Marker - // returned is 64-bit aligned. - // 64-bit aligned is a must, otherwise retrieving 64-bit parameter from BASE_LIST will - // cause unalignment exception. - // - *Marker = (BASE_LIST) (DebugInfo + 1); - *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12); - - return TRUE; -} - - -/** - Reports a status code. - - Reports the status code specified by the parameters Type and Value. Status - code also require an instance, caller ID, and extended data. This function - passed in a zero instance, NULL extended data, and a caller ID of - gEfiCallerIdGuid, which is the GUID for the module. - - ReportStatusCode()must actively prevent recusrsion. If ReportStatusCode() - is called while processing another any other Report Status Code Library function, - then ReportStatusCode() must return immediately. - - @param Type Status code type. - @param Value Status code value. - - @retval EFI_SUCCESS The status code was reported. - @retval EFI_DEVICE_ERROR There status code could not be reported due to a - device error. - @retval EFI_UNSUPPORTED Report status code is not supported - -**/ -EFI_STATUS -EFIAPI -ReportStatusCode ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value - ) -{ - return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL); -} - - -/** - Reports a status code with a Device Path Protocol as the extended data. - - Allocates and fills in the extended data section of a status code with the - Device Path Protocol specified by DevicePath. This function is responsible - for allocating a buffer large enough for the standard header and the device - path. The standard header is filled in with a GUID of - gEfiStatusCodeSpecificDataGuid. The status code is reported with a zero - instance and a caller ID of gEfiCallerIdGuid. - - ReportStatusCodeWithDevicePath()must actively prevent recursion. If - ReportStatusCodeWithDevicePath() is called while processing another any other - Report Status Code Library function, then ReportStatusCodeWithDevicePath() - must return EFI_DEVICE_ERROR immediately. - - If DevicePath is NULL, then ASSERT(). - - @param Type Status code type. - @param Value Status code value. - @param DevicePath Pointer to the Device Path Protocol to be reported. - - @retval EFI_SUCCESS The status code was reported with the extended - data specified by DevicePath. - @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the - extended data section. - @retval EFI_UNSUPPORTED Report status code is not supported - -**/ -EFI_STATUS -EFIAPI -ReportStatusCodeWithDevicePath ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - ASSERT (DevicePath != NULL); - return ReportStatusCodeWithExtendedData ( - Type, - Value, - (VOID *)DevicePath, - GetDevicePathSize (DevicePath) - ); -} - - -/** - Reports a status code with an extended data buffer. - - Allocates and fills in the extended data section of a status code with the - extended data specified by ExtendedData and ExtendedDataSize. ExtendedData - is assumed to be one of the data structures specified in Related Definitions. - These data structure do not have the standard header, so this function is - responsible for allocating a buffer large enough for the standard header and - the extended data passed into this function. The standard header is filled - in with a GUID of gEfiStatusCodeSpecificDataGuid. The status code is reported - with a zero instance and a caller ID of gEfiCallerIdGuid. - - ReportStatusCodeWithExtendedData()must actively prevent recursion. If - ReportStatusCodeWithExtendedData() is called while processing another any other - Report Status Code Library function, then ReportStatusCodeWithExtendedData() - must return EFI_DEVICE_ERROR immediately. - - If ExtendedData is NULL, then ASSERT(). - If ExtendedDataSize is 0, then ASSERT(). - - @param Type Status code type. - @param Value Status code value. - @param ExtendedData Pointer to the extended data buffer to be reported. - @param ExtendedDataSize The size, in bytes, of the extended data buffer to - be reported. - - @retval EFI_SUCCESS The status code was reported with the extended - data specified by ExtendedData and ExtendedDataSize. - @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the - extended data section. - @retval EFI_UNSUPPORTED Report status code is not supported - -**/ -EFI_STATUS -EFIAPI -ReportStatusCodeWithExtendedData ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN CONST VOID *ExtendedData, - IN UINTN ExtendedDataSize - ) -{ - ASSERT (ExtendedData != NULL); - ASSERT (ExtendedDataSize != 0); - return ReportStatusCodeEx ( - Type, - Value, - 0, - NULL, - NULL, - ExtendedData, - ExtendedDataSize - ); -} - - -/** - Reports a status code with full parameters. - - The function reports a status code. If ExtendedData is NULL and ExtendedDataSize - is 0, then an extended data buffer is not reported. If ExtendedData is not - NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. - ExtendedData is assumed not have the standard status code header, so this function - is responsible for allocating a buffer large enough for the standard header and - the extended data passed into this function. The standard header is filled in - with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a - GUID of gEfiStatusCodeSpecificDataGuid is used. The status code is reported with - an instance specified by Instance and a caller ID specified by CallerId. If - CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. - - ReportStatusCodeEx()must actively prevent recursion. If - ReportStatusCodeEx() is called while processing another any - other Report Status Code Library function, then - ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. - - If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). - If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). - - @param Type Status code type. - @param Value Status code value. - @param Instance Status code instance number. - @param CallerId Pointer to a GUID that identifies the caller of this - function. If this parameter is NULL, then a caller - ID of gEfiCallerIdGuid is used. - @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. - If this parameter is NULL, then a the status code - standard header is filled in with - gEfiStatusCodeSpecificDataGuid. - @param ExtendedData Pointer to the extended data buffer. This is an - optional parameter that may be NULL. - @param ExtendedDataSize The size, in bytes, of the extended data buffer. - - @retval EFI_SUCCESS The status code was reported. - @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate - the extended data section if it was specified. - @retval EFI_UNSUPPORTED Report status code is not supported - -**/ -EFI_STATUS -EFIAPI -ReportStatusCodeEx ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance, - IN CONST EFI_GUID *CallerId OPTIONAL, - IN CONST EFI_GUID *ExtendedDataGuid OPTIONAL, - IN CONST VOID *ExtendedData OPTIONAL, - IN UINTN ExtendedDataSize - ) -{ - EFI_STATUS Status; - - ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); - ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); - - if (ExtendedDataSize > EFI_STATUS_CODE_DATA_MAX_SIZE) { - DEBUG ((EFI_D_ERROR, "Status code extended data is too large to be reported!\n")); - return EFI_OUT_OF_RESOURCES; - } - - // - // Fill in the extended data header - // - mStatusCodeData->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA); - mStatusCodeData->Size = (UINT16)ExtendedDataSize; - if (ExtendedDataGuid == NULL) { - ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid; - } - CopyGuid (&mStatusCodeData->Type, ExtendedDataGuid); - - // - // Fill in the extended data buffer - // - if (ExtendedData != NULL) { - CopyMem (mStatusCodeData + 1, ExtendedData, ExtendedDataSize); - } - - // - // Report the status code - // - if (CallerId == NULL) { - CallerId = &gEfiCallerIdGuid; - } - Status = InternalReportStatusCode (Type, Value, Instance, CallerId, mStatusCodeData); - - return Status; -} - - -/** - Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled - - This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED - bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is set. - @retval FALSE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -ReportProgressCodeEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0); -} - - -/** - Returns TRUE if status codes of type EFI_ERROR_CODE are enabled - - This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED - bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is set. - @retval FALSE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -ReportErrorCodeEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0); -} - - -/** - Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled - - This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED - bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. - - @retval TRUE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is set. - @retval FALSE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of - PcdReportStatusCodeProperyMask is clear. - -**/ -BOOLEAN -EFIAPI -ReportDebugCodeEnabled ( - VOID - ) -{ - return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0); -} diff --git a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLibInternal.h b/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLibInternal.h deleted file mode 100644 index 1f9a0c7e1d..0000000000 --- a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/ReportStatusCodeLibInternal.h +++ /dev/null @@ -1,73 +0,0 @@ -/** @file - Internal Header file of Report Status Code Library for RUNTIME - DXE Phase. - - Copyright (c) 2006 - 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 __REPORT_STATUS_CODE_LIB_INTERNAL__H__ -#define __REPORT_STATUS_CODE_LIB_INTERNAL__H__ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - - -extern EFI_STATUS_CODE_DATA *mStatusCodeData; - -/** - Internal worker function that reports a status code through the status code service. - - If status code service is not cached, then this function checks if status code service is - available in system. If status code service is not available, then EFI_UNSUPPORTED is - returned. If status code service is present, then it is cached in mReportStatusCode. - Finally this function reports status code through the status code service. - - @param Type Status code type. - @param Value Status code value. - @param Instance Status code instance number. - @param CallerId Pointer to a GUID that identifies the caller of this - function. This is an optional parameter that may be - NULL. - @param Data Pointer to the extended data buffer. This is an - optional parameter that may be NULL. - - @retval EFI_SUCCESS The status code was reported. - @retval EFI_UNSUPPORTED Status code service is not available. - @retval EFI_UNSUPPORTED Status code type is not supported. - -**/ -EFI_STATUS -InternalReportStatusCode ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance, - IN CONST EFI_GUID *CallerId OPTIONAL, - IN EFI_STATUS_CODE_DATA *Data OPTIONAL - ); - -#endif - diff --git a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf b/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf deleted file mode 100644 index 6964e44f34..0000000000 --- a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf +++ /dev/null @@ -1,73 +0,0 @@ -## @file -# Framework Report status code library instance which supports logging message in SMM, as well as DXE & runtime phase. -# -# This library instance supports status code report in SMM, as well as DXE & runtime phase. -# In SMM, it logs message via SMM Status Code Protocol. -# Otherwise, it logs message to ReportStatusCode() in framework runtime services table or runtime report status code 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 -# 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 = SmmRuntimeDxeReportStatusCodeLibFramework - MODULE_UNI_FILE = SmmRuntimeDxeReportStatusCodeLibFramework.uni - FILE_GUID = D65D9F72-7BCE-4f73-A673-47AF446A1A31 - MODULE_TYPE = DXE_RUNTIME_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = ReportStatusCodeLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER - - CONSTRUCTOR = ReportStatusCodeLibConstruct - DESTRUCTOR = ReportStatusCodeLibDestruct -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 EBC -# - -[Sources] - ReportStatusCodeLib.c - SmmRuntimeDxeSupport.c - ReportStatusCodeLibInternal.h - - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - PcdLib - BaseMemoryLib - BaseLib - DebugLib - UefiRuntimeServicesTableLib - UefiBootServicesTableLib - DevicePathLib - MemoryAllocationLib - -[Guids] - gEfiStatusCodeSpecificDataGuid ## SOMETIMES_CONSUMES ## UNDEFINED - gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## UNDEFINED - gEfiEventExitBootServicesGuid ## CONSUMES ## Event - gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event - - -[Protocols] - gEfiStatusCodeRuntimeProtocolGuid ## SOMETIMES_CONSUMES - gEfiSmmBaseProtocolGuid ## SOMETIMES_CONSUMES - gEfiSmmStatusCodeProtocolGuid ## SOMETIMES_CONSUMES - -[Pcd] - gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask ## CONSUMES - diff --git a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.uni b/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.uni deleted file mode 100644 index 2268a3c094..0000000000 Binary files a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c b/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c deleted file mode 100644 index 554be152b3..0000000000 --- a/IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c +++ /dev/null @@ -1,335 +0,0 @@ -/** @file - Library constructor & destructor, event handlers, and other internal worker functions. - - 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 "ReportStatusCodeLibInternal.h" - -EFI_EVENT mVirtualAddressChangeEvent; -EFI_EVENT mExitBootServicesEvent; -EFI_STATUS_CODE_DATA *mStatusCodeData; -BOOLEAN mInSmm; -EFI_SMM_BASE_PROTOCOL *mSmmBase; -EFI_RUNTIME_SERVICES *mInternalRT; -BOOLEAN mHaveExitedBootServices = FALSE; -EFI_REPORT_STATUS_CODE mReportStatusCode = NULL; -EFI_SMM_STATUS_CODE_PROTOCOL *mSmmStatusCodeProtocol; - -/** - Locates and caches SMM Status Code Protocol. - -**/ -VOID -SmmStatusCodeInitialize ( - VOID - ) -{ - EFI_STATUS Status; - - Status = gBS->LocateProtocol (&gEfiSmmStatusCodeProtocolGuid, NULL, (VOID **) &mSmmStatusCodeProtocol); - if (EFI_ERROR (Status)) { - mSmmStatusCodeProtocol = NULL; - } -} - -/** - Report status code via SMM Status Code Protocol. - - @param Type Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to classify the entity - as well as an operation. For progress codes, the operation is the current activity. - For error codes, it is the exception. For debug codes, it is not defined at this time. - @param Instance The enumeration of a hardware or software entity within the system. - A system may contain multiple entities that match a class/subclass pairing. - The instance differentiates between them. An instance of 0 indicates that instance information is unavailable, - not meaningful, or not relevant. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to different callers. - @param Data This optional parameter may be used to pass additional data - - @retval EFI_SUCCESS Always return EFI_SUCCESS. - -**/ -EFI_STATUS -SmmStatusCodeReport ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance, - IN EFI_GUID *CallerId OPTIONAL, - IN EFI_STATUS_CODE_DATA *Data OPTIONAL - ) -{ - if (mSmmStatusCodeProtocol != NULL) { - (mSmmStatusCodeProtocol->ReportStatusCode) (mSmmStatusCodeProtocol, Type, Value, Instance, CallerId, Data); - } - return EFI_SUCCESS; -} - -/** - Locate the report status code service. - - In SMM, it tries to retrieve SMM Status Code Protocol. - Otherwise, it first tries to retrieve ReportStatusCode() in Runtime Services Table. - If not found, it then tries to retrieve ReportStatusCode() API of Report Status Code Protocol. - - @return Function pointer to the report status code service. - NULL is returned if no status code service is available. - -**/ -EFI_REPORT_STATUS_CODE -InternalGetReportStatusCode ( - VOID - ) -{ - EFI_STATUS_CODE_PROTOCOL *StatusCodeProtocol; - EFI_STATUS Status; - - if (mInSmm) { - return (EFI_REPORT_STATUS_CODE) SmmStatusCodeReport; - } else if (mInternalRT != NULL && mInternalRT->Hdr.Revision < 0x20000) { - return ((FRAMEWORK_EFI_RUNTIME_SERVICES*)mInternalRT)->ReportStatusCode; - } else if (!mHaveExitedBootServices) { - // - // Check gBS just in case. ReportStatusCode is called before gBS is initialized. - // - if (gBS != NULL) { - Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol); - if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) { - return StatusCodeProtocol->ReportStatusCode; - } - } - } - - return NULL; -} - -/** - Internal worker function that reports a status code through the status code service. - - If status code service is not cached, then this function checks if status code service is - available in system. If status code service is not available, then EFI_UNSUPPORTED is - returned. If status code service is present, then it is cached in mReportStatusCode. - Finally this function reports status code through the status code service. - - @param Type Status code type. - @param Value Status code value. - @param Instance Status code instance number. - @param CallerId Pointer to a GUID that identifies the caller of this - function. This is an optional parameter that may be - NULL. - @param Data Pointer to the extended data buffer. This is an - optional parameter that may be NULL. - - @retval EFI_SUCCESS The status code was reported. - @retval EFI_UNSUPPORTED Status code service is not available. - @retval EFI_UNSUPPORTED Status code type is not supported. - -**/ -EFI_STATUS -InternalReportStatusCode ( - IN EFI_STATUS_CODE_TYPE Type, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance, - IN CONST EFI_GUID *CallerId OPTIONAL, - IN EFI_STATUS_CODE_DATA *Data OPTIONAL - ) -{ - if ((ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || - (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) || - (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)) { - // - // If mReportStatusCode is NULL, then check if status code service is available in system. - // - if (mReportStatusCode == NULL) { - mReportStatusCode = InternalGetReportStatusCode (); - if (mReportStatusCode == NULL) { - return EFI_UNSUPPORTED; - } - } - - // - // A status code service is present in system, so pass in all the parameters to the service. - // - return (*mReportStatusCode) (Type, Value, Instance, (EFI_GUID *)CallerId, Data); - } - - return EFI_UNSUPPORTED; -} - -/** - Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. - - @param Event Event whose notification function is being invoked. - @param Context Pointer to the notification function's context - -**/ -VOID -EFIAPI -ReportStatusCodeLibVirtualAddressChange ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - if (mReportStatusCode != NULL) { - mInternalRT->ConvertPointer (0, (VOID **) &mReportStatusCode); - } - mInternalRT->ConvertPointer (0, (VOID **) &mStatusCodeData); - mInternalRT->ConvertPointer (0, (VOID **) &mInternalRT); -} - -/** - Notification function of EVT_SIGNAL_EXIT_BOOT_SERVICES. - - @param Event Event whose notification function is being invoked. - @param Context Pointer to the notification function's context - -**/ -VOID -EFIAPI -ReportStatusCodeLibExitBootServices ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // If mReportStatusCode is NULL, then see if a Status Code Protocol instance is present - // in the handle database. - // - if (mReportStatusCode == NULL) { - mReportStatusCode = InternalGetReportStatusCode (); - } - - mHaveExitedBootServices = TRUE; -} - -/** - The constructor function of SMM Runtime DXE Report Status Code Lib. - - This function allocates memory for extended status code data, caches - the report status code service, and registers events. - - @param ImageHandle The firmware allocated handle for the EFI image. - @param SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. - -**/ -EFI_STATUS -EFIAPI -ReportStatusCodeLibConstruct ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // If in SMM mode, then allocates memory from SMRAM for extended status code data. - // - Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase); - if (!EFI_ERROR (Status)) { - mSmmBase->InSmm (mSmmBase, &mInSmm); - if (mInSmm) { - Status = mSmmBase->SmmAllocatePool ( - mSmmBase, - EfiRuntimeServicesData, - sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, - (VOID **) &mStatusCodeData - ); - ASSERT_EFI_ERROR (Status); - SmmStatusCodeInitialize (); - return EFI_SUCCESS; - } - } - - - // - // If not in SMM mode, then allocate runtime memory for extended status code data. - // - // Library should not use the gRT directly, for it may be converted by other library instance. - // - mInternalRT = gRT; - mInSmm = FALSE; - - mStatusCodeData = AllocateRuntimePool (sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE); - ASSERT (mStatusCodeData != NULL); - // - // Cache the report status code service - // - mReportStatusCode = InternalGetReportStatusCode (); - - // - // Register notify function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE - // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - ReportStatusCodeLibVirtualAddressChange, - NULL, - &gEfiEventVirtualAddressChangeGuid, - &mVirtualAddressChangeEvent - ); - ASSERT_EFI_ERROR (Status); - - // - // Register notify function for EVT_SIGNAL_EXIT_BOOT_SERVICES - // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - ReportStatusCodeLibExitBootServices, - NULL, - &gEfiEventExitBootServicesGuid, - &mExitBootServicesEvent - ); - ASSERT_EFI_ERROR (Status); - - return EFI_SUCCESS; -} - -/** - The destructor function of SMM Runtime DXE Report Status Code Lib. - - The destructor function frees memory allocated by constructor, and closes related events. - It will ASSERT() if that related 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 always returns EFI_SUCCESS. - -**/ -EFI_STATUS -EFIAPI -ReportStatusCodeLibDestruct ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - if (!mInSmm) { - ASSERT (gBS != NULL); - Status = gBS->CloseEvent (mVirtualAddressChangeEvent); - ASSERT_EFI_ERROR (Status); - Status = gBS->CloseEvent (mExitBootServicesEvent); - ASSERT_EFI_ERROR (Status); - - FreePool (mStatusCodeData); - } else { - mSmmBase->SmmFreePool (mSmmBase, mStatusCodeData); - } - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/License.txt b/IntelFrameworkModulePkg/License.txt deleted file mode 100644 index be68999be6..0000000000 --- a/IntelFrameworkModulePkg/License.txt +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2012, Intel Corporation. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c deleted file mode 100644 index 177a73bc78..0000000000 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c +++ /dev/null @@ -1,643 +0,0 @@ -/** @file - This is an implementation of the ACPI S3 Save protocol. This is defined in - S3 boot path specification 0.9. - -Copyright (c) 2006 - 2015, Intel 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 - -#include "AcpiS3Save.h" - -// -// 8 extra pages for PF handler. -// -#define EXTRA_PAGE_TABLE_PAGES 8 - -/** - Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save. -**/ -VOID -InstallAcpiS3SaveThunk ( - VOID - ); - -/** - Hook point for AcpiVariableThunkPlatform for S3Ready. - - @param AcpiS3Context ACPI s3 context -**/ -VOID -S3ReadyThunkPlatform ( - IN ACPI_S3_CONTEXT *AcpiS3Context - ); - -UINTN mLegacyRegionSize; - -EFI_ACPI_S3_SAVE_PROTOCOL mS3Save = { - LegacyGetS3MemorySize, - S3Ready, -}; - -EFI_GUID mAcpiS3IdtrProfileGuid = { - 0xdea652b0, 0xd587, 0x4c54, { 0xb5, 0xb4, 0xc6, 0x82, 0xe7, 0xa0, 0xaa, 0x3d } -}; - -/** - Allocate memory below 4G memory address. - - This function allocates memory below 4G memory address. - - @param MemoryType Memory type of memory to allocate. - @param Size Size of memory to allocate. - - @return Allocated address for output. - -**/ -VOID* -AllocateMemoryBelow4G ( - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Size - ) -{ - UINTN Pages; - EFI_PHYSICAL_ADDRESS Address; - EFI_STATUS Status; - VOID* Buffer; - - Pages = EFI_SIZE_TO_PAGES (Size); - Address = 0xffffffff; - - Status = gBS->AllocatePages ( - AllocateMaxAddress, - MemoryType, - Pages, - &Address - ); - ASSERT_EFI_ERROR (Status); - - Buffer = (VOID *) (UINTN) Address; - ZeroMem (Buffer, Size); - - return Buffer; -} - -/** - - This function scan ACPI table in RSDT. - - @param Rsdt ACPI RSDT - @param Signature ACPI table signature - - @return ACPI table - -**/ -VOID * -ScanTableInRSDT ( - IN EFI_ACPI_DESCRIPTION_HEADER *Rsdt, - IN UINT32 Signature - ) -{ - UINTN Index; - UINT32 EntryCount; - UINT32 *EntryPtr; - EFI_ACPI_DESCRIPTION_HEADER *Table; - - if (Rsdt == NULL) { - return NULL; - } - - EntryCount = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32); - - EntryPtr = (UINT32 *)(Rsdt + 1); - for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) { - Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(*EntryPtr)); - if (Table->Signature == Signature) { - return Table; - } - } - - return NULL; -} - -/** - - This function scan ACPI table in XSDT. - - @param Xsdt ACPI XSDT - @param Signature ACPI table signature - - @return ACPI table - -**/ -VOID * -ScanTableInXSDT ( - IN EFI_ACPI_DESCRIPTION_HEADER *Xsdt, - IN UINT32 Signature - ) -{ - UINTN Index; - UINT32 EntryCount; - UINT64 EntryPtr; - UINTN BasePtr; - EFI_ACPI_DESCRIPTION_HEADER *Table; - - if (Xsdt == NULL) { - return NULL; - } - - EntryCount = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64); - - BasePtr = (UINTN)(Xsdt + 1); - for (Index = 0; Index < EntryCount; Index ++) { - CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64)); - Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(EntryPtr)); - if (Table->Signature == Signature) { - return Table; - } - } - - return NULL; -} - -/** - To find Facs in FADT. - - @param Fadt FADT table pointer - - @return Facs table pointer. -**/ -EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * -FindAcpiFacsFromFadt ( - IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt - ) -{ - EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; - UINT64 Data64; - - if (Fadt == NULL) { - return NULL; - } - - if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { - Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl; - } else { - if (Fadt->FirmwareCtrl != 0) { - Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Fadt->FirmwareCtrl; - } else { - CopyMem (&Data64, &Fadt->XFirmwareCtrl, sizeof(UINT64)); - Facs = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Data64; - } - } - return Facs; -} - -/** - To find Facs in Acpi tables. - - To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored - in the table. - - @param AcpiTableGuid The guid used to find ACPI table in UEFI ConfigurationTable. - - @return Facs table pointer. -**/ -EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * -FindAcpiFacsTableByAcpiGuid ( - IN EFI_GUID *AcpiTableGuid - ) -{ - EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; - EFI_ACPI_DESCRIPTION_HEADER *Rsdt; - EFI_ACPI_DESCRIPTION_HEADER *Xsdt; - EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; - EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; - UINTN Index; - - Rsdp = NULL; - // - // found ACPI table RSD_PTR from system table - // - for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { - if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), AcpiTableGuid)) { - // - // A match was found. - // - Rsdp = gST->ConfigurationTable[Index].VendorTable; - break; - } - } - - if (Rsdp == NULL) { - return NULL; - } - - // - // Search XSDT - // - if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) { - Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->XsdtAddress; - Fadt = ScanTableInXSDT (Xsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE); - if (Fadt != NULL) { - Facs = FindAcpiFacsFromFadt (Fadt); - if (Facs != NULL) { - return Facs; - } - } - } - - // - // Search RSDT - // - Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress; - Fadt = ScanTableInRSDT (Rsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE); - if (Fadt != NULL) { - Facs = FindAcpiFacsFromFadt (Fadt); - if (Facs != NULL) { - return Facs; - } - } - - return NULL; -} - -/** - To find Facs in Acpi tables. - - To find Firmware ACPI control strutcure in Acpi Tables since the S3 waking vector is stored - in the table. - - @return Facs table pointer. -**/ -EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * -FindAcpiFacsTable ( - VOID - ) -{ - EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; - - Facs = FindAcpiFacsTableByAcpiGuid (&gEfiAcpi20TableGuid); - if (Facs != NULL) { - return Facs; - } - - return FindAcpiFacsTableByAcpiGuid (&gEfiAcpi10TableGuid); -} - -/** - The function will check if long mode waking vector is supported. - - @param[in] Facs Pointer to FACS table. - - @retval TRUE Long mode waking vector is supported. - @retval FALSE Long mode waking vector is not supported. - -**/ -BOOLEAN -IsLongModeWakingVectorSupport ( - IN EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs - ) -{ - if ((Facs == NULL) || - (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ) { - // - // Something wrong with FACS. - // - return FALSE; - } - if (Facs->XFirmwareWakingVector != 0) { - if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && - ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0)) { - // - // BIOS supports 64bit waking vector. - // - if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { - return TRUE; - } - } - } - return FALSE; -} - -/** - Allocates page table buffer. - - @param[in] LongModeWakingVectorSupport Support long mode waking vector or not. - - If BootScriptExector driver will run in 64-bit mode, this function will establish the 1:1 - virtual to physical mapping page table when long mode waking vector is supported, otherwise - create 4G page table when long mode waking vector is not supported and let PF handler to - handle > 4G request. - If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. - - @return Page table base address. - -**/ -EFI_PHYSICAL_ADDRESS -S3AllocatePageTablesBuffer ( - IN BOOLEAN LongModeWakingVectorSupport - ) -{ - if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { - UINTN ExtraPageTablePages; - UINT32 RegEax; - UINT32 RegEdx; - UINT8 PhysicalAddressBits; - UINT32 NumberOfPml4EntriesNeeded; - UINT32 NumberOfPdpEntriesNeeded; - EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress; - UINTN TotalPageTableSize; - VOID *Hob; - BOOLEAN Page1GSupport; - - Page1GSupport = FALSE; - if (PcdGetBool(PcdUse1GPageTable)) { - AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); - if (RegEax >= 0x80000001) { - AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); - if ((RegEdx & BIT26) != 0) { - Page1GSupport = TRUE; - } - } - } - - // - // Get physical address bits supported. - // - Hob = GetFirstHob (EFI_HOB_TYPE_CPU); - if (Hob != NULL) { - PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; - } else { - AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); - if (RegEax >= 0x80000008) { - AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); - PhysicalAddressBits = (UINT8) RegEax; - } else { - PhysicalAddressBits = 36; - } - } - - // - // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. - // - ASSERT (PhysicalAddressBits <= 52); - if (PhysicalAddressBits > 48) { - PhysicalAddressBits = 48; - } - - ExtraPageTablePages = 0; - if (!LongModeWakingVectorSupport) { - // - // Create 4G page table when BIOS does not support long mode waking vector, - // and let PF handler to handle > 4G request. - // - PhysicalAddressBits = 32; - ExtraPageTablePages = EXTRA_PAGE_TABLE_PAGES; - } - - // - // Calculate the table entries needed. - // - if (PhysicalAddressBits <= 39 ) { - NumberOfPml4EntriesNeeded = 1; - NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); - } else { - NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); - NumberOfPdpEntriesNeeded = 512; - } - - // - // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs. - // - if (!Page1GSupport) { - TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded); - } else { - TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded); - } - - TotalPageTableSize += ExtraPageTablePages; - DEBUG ((EFI_D_ERROR, "AcpiS3Save TotalPageTableSize - 0x%x pages\n", TotalPageTableSize)); - - // - // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. - // - S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGES_TO_SIZE(TotalPageTableSize)); - ASSERT (S3NvsPageTableAddress != 0); - return S3NvsPageTableAddress; - } else { - // - // If DXE is running 32-bit mode, no need to establish page table. - // - return (EFI_PHYSICAL_ADDRESS) 0; - } -} - -/** - Gets the buffer of legacy memory below 1 MB - This function is to get the buffer in legacy memory below 1MB that is required during S3 resume. - - @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. - @param Size The returned size of legacy memory below 1 MB. - - @retval EFI_SUCCESS Size is successfully returned. - @retval EFI_INVALID_PARAMETER The pointer Size is NULL. - -**/ -EFI_STATUS -EFIAPI -LegacyGetS3MemorySize ( - IN EFI_ACPI_S3_SAVE_PROTOCOL *This, - OUT UINTN *Size - ) -{ - if (Size == NULL) { - return EFI_INVALID_PARAMETER; - } - - *Size = mLegacyRegionSize; - return EFI_SUCCESS; -} - -/** - Prepares all information that is needed in the S3 resume boot path. - - Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path - - @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. - @param LegacyMemoryAddress The base address of legacy memory. - - @retval EFI_NOT_FOUND Some necessary information cannot be found. - @retval EFI_SUCCESS All information was saved successfully. - @retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information. - @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB. - -**/ -EFI_STATUS -EFIAPI -S3Ready ( - IN EFI_ACPI_S3_SAVE_PROTOCOL *This, - IN VOID *LegacyMemoryAddress - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS AcpiS3ContextBuffer; - ACPI_S3_CONTEXT *AcpiS3Context; - STATIC BOOLEAN AlreadyEntered; - IA32_DESCRIPTOR *Idtr; - IA32_IDT_GATE_DESCRIPTOR *IdtGate; - EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; - - DEBUG ((EFI_D_INFO, "S3Ready!\n")); - - // - // Platform may invoke AcpiS3Save->S3Save() before ExitPmAuth, because we need save S3 information there, while BDS ReadyToBoot may invoke it again. - // So if 2nd S3Save() is triggered later, we need ignore it. - // - if (AlreadyEntered) { - return EFI_SUCCESS; - } - AlreadyEntered = TRUE; - - AcpiS3Context = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(*AcpiS3Context)); - ASSERT (AcpiS3Context != NULL); - AcpiS3ContextBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context; - - // - // Get ACPI Table because we will save its position to variable - // - Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) FindAcpiFacsTable (); - AcpiS3Context->AcpiFacsTable = (EFI_PHYSICAL_ADDRESS) (UINTN) Facs; - ASSERT (AcpiS3Context->AcpiFacsTable != 0); - - IdtGate = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR)); - Idtr = (IA32_DESCRIPTOR *)(IdtGate + 0x100); - Idtr->Base = (UINTN)IdtGate; - Idtr->Limit = (UINT16)(sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 - 1); - AcpiS3Context->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)Idtr; - - Status = SaveLockBox ( - &mAcpiS3IdtrProfileGuid, - (VOID *)(UINTN)Idtr, - (UINTN)sizeof(IA32_DESCRIPTOR) - ); - ASSERT_EFI_ERROR (Status); - - Status = SetLockBoxAttributes (&mAcpiS3IdtrProfileGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); - ASSERT_EFI_ERROR (Status); - - // - // Allocate page table - // - AcpiS3Context->S3NvsPageTableAddress = S3AllocatePageTablesBuffer (IsLongModeWakingVectorSupport (Facs)); - - // - // Allocate stack - // - AcpiS3Context->BootScriptStackSize = PcdGet32 (PcdS3BootScriptStackSize); - AcpiS3Context->BootScriptStackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3BootScriptStackSize)); - ASSERT (AcpiS3Context->BootScriptStackBase != 0); - - // - // Allocate a code buffer < 4G for S3 debug to load external code, set invalid code instructions in it. - // - AcpiS3Context->S3DebugBufferAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGE_SIZE); - SetMem ((VOID *)(UINTN)AcpiS3Context->S3DebugBufferAddress, EFI_PAGE_SIZE, 0xff); - - DEBUG((EFI_D_INFO, "AcpiS3Context: AcpiFacsTable is 0x%8x\n", AcpiS3Context->AcpiFacsTable)); - DEBUG((EFI_D_INFO, "AcpiS3Context: IdtrProfile is 0x%8x\n", AcpiS3Context->IdtrProfile)); - DEBUG((EFI_D_INFO, "AcpiS3Context: S3NvsPageTableAddress is 0x%8x\n", AcpiS3Context->S3NvsPageTableAddress)); - DEBUG((EFI_D_INFO, "AcpiS3Context: S3DebugBufferAddress is 0x%8x\n", AcpiS3Context->S3DebugBufferAddress)); - DEBUG((EFI_D_INFO, "AcpiS3Context: BootScriptStackBase is 0x%8x\n", AcpiS3Context->BootScriptStackBase)); - DEBUG((EFI_D_INFO, "AcpiS3Context: BootScriptStackSize is 0x%8x\n", AcpiS3Context->BootScriptStackSize)); - - Status = SaveLockBox ( - &gEfiAcpiVariableGuid, - &AcpiS3ContextBuffer, - sizeof(AcpiS3ContextBuffer) - ); - ASSERT_EFI_ERROR (Status); - - Status = SaveLockBox ( - &gEfiAcpiS3ContextGuid, - (VOID *)(UINTN)AcpiS3Context, - (UINTN)sizeof(*AcpiS3Context) - ); - ASSERT_EFI_ERROR (Status); - - Status = SetLockBoxAttributes (&gEfiAcpiS3ContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); - ASSERT_EFI_ERROR (Status); - - if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) { - S3ReadyThunkPlatform (AcpiS3Context); - } - - return EFI_SUCCESS; -} - -/** - The Driver Entry Point. - - The function is the driver Entry point which will produce AcpiS3SaveProtocol. - - @param ImageHandle A handle for the image that is initializing this driver - @param 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 -InstallAcpiS3Save ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - if (!FeaturePcdGet(PcdPlatformCsmSupport)) { - // - // More memory for no CSM tip, because GDT need relocation - // - mLegacyRegionSize = 0x250; - } else { - mLegacyRegionSize = 0x100; - } - - if (FeaturePcdGet(PcdFrameworkCompatibilitySupport)) { - InstallAcpiS3SaveThunk (); - } - - Status = gBS->InstallProtocolInterface ( - &ImageHandle, - &gEfiAcpiS3SaveProtocolGuid, - EFI_NATIVE_INTERFACE, - &mS3Save - ); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h deleted file mode 100644 index 65974a3402..0000000000 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h +++ /dev/null @@ -1,59 +0,0 @@ -/** @file - This is an implementation of the ACPI S3 Save protocol. This is defined in - S3 boot path specification 0.9. - -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 _ACPI_S3_SAVE_H_ -#define _ACPI_S3_SAVE_H_ - -/** - Gets the buffer of legacy memory below 1 MB - This function is to get the buffer in legacy memory below 1MB that is required during S3 resume. - - @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. - @param Size The returned size of legacy memory below 1 MB. - - @retval EFI_SUCCESS Size is successfully returned. - @retval EFI_INVALID_PARAMETER The pointer Size is NULL. - -**/ -EFI_STATUS -EFIAPI -LegacyGetS3MemorySize ( - IN EFI_ACPI_S3_SAVE_PROTOCOL * This, - OUT UINTN * Size - ); - -/** - Prepares all information that is needed in the S3 resume boot path. - - Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path - - @param This A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance. - @param LegacyMemoryAddress The base address of legacy memory. - - @retval EFI_NOT_FOUND Some necessary information cannot be found. - @retval EFI_SUCCESS All information was saved successfully. - @retval EFI_OUT_OF_RESOURCES Resources were insufficient to save all the information. - @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB. - -**/ -EFI_STATUS -EFIAPI -S3Ready ( - IN EFI_ACPI_S3_SAVE_PROTOCOL *This, - IN VOID *LegacyMemoryAddress - ); -#endif diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf deleted file mode 100644 index 366eb147b7..0000000000 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf +++ /dev/null @@ -1,89 +0,0 @@ -## @file -# AcpiS3Save module installs ACPI S3 Save protocol to prepare S3 boot data. -# -# Copyright (c) 2006 - 2015, Intel 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 = AcpiS3SaveDxe - MODULE_UNI_FILE = AcpiS3SaveDxe.uni - FILE_GUID = 2BDED685-F733-455f-A840-43A22B791FB3 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - - ENTRY_POINT = InstallAcpiS3Save - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 -# - -[Sources] - AcpiS3Save.h - AcpiS3Save.c - AcpiVariableThunkPlatform.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - PcdLib - UefiRuntimeServicesTableLib - UefiBootServicesTableLib - UefiDriverEntryPoint - BaseMemoryLib - HobLib - UefiLib - LockBoxLib - DebugLib - DxeServicesLib - -[Guids] - gEfiAcpiVariableGuid ## PRODUCES ## UNDEFINED # LockBox Save Data. - gEfiAcpiS3ContextGuid ## PRODUCES ## UNDEFINED # LockBox Save Data. - gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable - gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable - ## SOMETIMES_CONSUMES ## Variable:L"AcpiGlobalVariable" - ## SOMETIMES_PRODUCES ## Variable:L"AcpiGlobalVariable" - gEfiAcpiVariableCompatiblityGuid - -[Protocols] - gEfiAcpiS3SaveProtocolGuid ## PRODUCES - gFrameworkEfiMpServiceProtocolGuid ## SOMETIMES_CONSUMES - ## NOTIFY - ## SOMETIMES_CONSUMES - gEdkiiVariableLockProtocolGuid - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformCsmSupport ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES - -[Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize ## SOMETIMES_CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3BootScriptStackSize ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## CONSUMES - -[Depex] - # - # Note: the extra dependency of gEfiMpServiceProtocolGuid is to ensure that ACPI variable is set by MpDxe driver before - # AcpiS3SaveDxe module is executed. - # - gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid AND gEfiMpServiceProtocolGuid - -[UserExtensions.TianoCore."ExtraFiles"] - AcpiS3SaveDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni deleted file mode 100644 index 05f1398985..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni deleted file mode 100644 index 7b89727292..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c deleted file mode 100644 index 7ad9eb4336..0000000000 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c +++ /dev/null @@ -1,224 +0,0 @@ -/** @file - This is an implementation of the AcpiVariable platform field for ECP platform. - -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 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. - -== - -typedef struct { - EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase; <<=== - UINT32 AcpiReservedMemorySize; <<=== - EFI_PHYSICAL_ADDRESS S3ReservedLowMemoryBase; - EFI_PHYSICAL_ADDRESS AcpiBootScriptTable; - EFI_PHYSICAL_ADDRESS RuntimeScriptTableBase; - EFI_PHYSICAL_ADDRESS AcpiFacsTable; - UINT64 SystemMemoryLength; <<=== - ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData; - EFI_PHYSICAL_ADDRESS VideoOpromAddress; - UINT32 VideoOpromSize; - EFI_PHYSICAL_ADDRESS S3DebugBufferAddress; - EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint; -} ACPI_VARIABLE_SET_COMPATIBILITY; - -**/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -GLOBAL_REMOVE_IF_UNREFERENCED -ACPI_VARIABLE_SET_COMPATIBILITY *mAcpiVariableSetCompatibility = NULL; - -/** - Allocate memory below 4G memory address. - - This function allocates memory below 4G memory address. - - @param MemoryType Memory type of memory to allocate. - @param Size Size of memory to allocate. - - @return Allocated address for output. - -**/ -VOID* -AllocateMemoryBelow4G ( - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Size - ); - -/** - Hook point for AcpiVariableThunkPlatform for S3Ready. - - @param AcpiS3Context ACPI s3 context -**/ -VOID -S3ReadyThunkPlatform ( - IN ACPI_S3_CONTEXT *AcpiS3Context - ) -{ - EFI_PHYSICAL_ADDRESS AcpiMemoryBase; - UINT32 AcpiMemorySize; - EFI_PEI_HOB_POINTERS Hob; - UINT64 MemoryLength; - - DEBUG ((EFI_D_INFO, "S3ReadyThunkPlatform\n")); - - if (mAcpiVariableSetCompatibility == NULL) { - return; - } - - // - // Allocate ACPI reserved memory under 4G - // - AcpiMemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3AcpiReservedMemorySize)); - ASSERT (AcpiMemoryBase != 0); - AcpiMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize); - - // - // Calculate the system memory length by memory hobs - // - MemoryLength = 0x100000; - Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); - ASSERT (Hob.Raw != NULL); - while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) { - if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { - // - // Skip the memory region below 1MB - // - if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) { - MemoryLength += Hob.ResourceDescriptor->ResourceLength; - } - } - Hob.Raw = GET_NEXT_HOB (Hob); - Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); - } - - mAcpiVariableSetCompatibility->AcpiReservedMemoryBase = AcpiMemoryBase; - mAcpiVariableSetCompatibility->AcpiReservedMemorySize = AcpiMemorySize; - mAcpiVariableSetCompatibility->SystemMemoryLength = MemoryLength; - - DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemoryBase is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemoryBase)); - DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemorySize is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemorySize)); - DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: SystemMemoryLength is 0x%8x\n", mAcpiVariableSetCompatibility->SystemMemoryLength)); - - return ; -} - -/** - Register callback function upon VariableLockProtocol - to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it. - - @param[in] Event Event whose notification function is being invoked. - @param[in] Context Pointer to the notification function's context. -**/ -VOID -EFIAPI -VariableLockAcpiGlobalVariable ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; - // - // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock protocol exists - // - Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); - if (!EFI_ERROR (Status)) { - Status = VariableLock->RequestToLock (VariableLock, ACPI_GLOBAL_VARIABLE, &gEfiAcpiVariableCompatiblityGuid); - ASSERT_EFI_ERROR (Status); - } -} - -/** - Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save. -**/ -VOID -InstallAcpiS3SaveThunk ( - VOID - ) -{ - EFI_STATUS Status; - FRAMEWORK_EFI_MP_SERVICES_PROTOCOL *FrameworkMpService; - UINTN VarSize; - VOID *Registration; - - Status = gBS->LocateProtocol ( - &gFrameworkEfiMpServiceProtocolGuid, - NULL, - (VOID**) &FrameworkMpService - ); - if (!EFI_ERROR (Status)) { - // - // On ECP platform, if framework CPU drivers are in use, The compatible version of ACPI variable set - // should be produced by CPU driver. - // - VarSize = sizeof (mAcpiVariableSetCompatibility); - Status = gRT->GetVariable ( - ACPI_GLOBAL_VARIABLE, - &gEfiAcpiVariableCompatiblityGuid, - NULL, - &VarSize, - &mAcpiVariableSetCompatibility - ); - if (EFI_ERROR (Status) || (VarSize != sizeof (mAcpiVariableSetCompatibility))) { - DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility was not saved by CPU driver correctly. OS S3 may fail!\n")); - mAcpiVariableSetCompatibility = NULL; - } - } else { - // - // Allocate/initialize the compatible version of Acpi Variable Set since Framework chipset/platform - // driver need this variable. ACPI_GLOBAL_VARIABLE variable is not used in runtime phase, - // so RT attribute is not needed for it. - // - mAcpiVariableSetCompatibility = AllocateMemoryBelow4G (EfiACPIMemoryNVS, sizeof(ACPI_VARIABLE_SET_COMPATIBILITY)); - Status = gRT->SetVariable ( - ACPI_GLOBAL_VARIABLE, - &gEfiAcpiVariableCompatiblityGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, - sizeof(mAcpiVariableSetCompatibility), - &mAcpiVariableSetCompatibility - ); - if (!EFI_ERROR (Status)) { - // - // Register callback function upon VariableLockProtocol - // to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it. - // - EfiCreateProtocolNotifyEvent ( - &gEdkiiVariableLockProtocolGuid, - TPL_CALLBACK, - VariableLockAcpiGlobalVariable, - NULL, - &Registration - ); - } else { - DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility cannot be saved: %r. OS S3 may fail!\n", Status)); - gBS->FreePages ( - (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiVariableSetCompatibility, - EFI_SIZE_TO_PAGES (sizeof (ACPI_VARIABLE_SET_COMPATIBILITY)) - ); - mAcpiVariableSetCompatibility = NULL; - } - } - - DEBUG((EFI_D_INFO, "AcpiVariableSetCompatibility is 0x%8x\n", mAcpiVariableSetCompatibility)); -} diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.c b/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.c deleted file mode 100644 index a8b1f06117..0000000000 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.c +++ /dev/null @@ -1,91 +0,0 @@ -/** @file - This is an implementation of the ACPI Support protocol. This is defined in - the Tiano ACPI External Product Specification, revision 0.3.6. - -Copyright (c) 2006 - 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. - -**/ - -// -// Includes -// -#include "AcpiSupport.h" - -// -// Handle to install ACPI Table Protocol (and ACPI Suppport protocol). -// -EFI_HANDLE mHandle = NULL; - -/** - Entry point of the ACPI support driver. This function creates and initializes an instance of the ACPI Support - Protocol and installs it on a new handle. - - @param ImageHandle A handle for the image that is initializing this driver - @param 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 -InstallAcpiSupport ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) - -{ - EFI_STATUS Status; - EFI_ACPI_SUPPORT_INSTANCE *PrivateData; - - // - // Initialize our protocol - // - PrivateData = AllocateZeroPool (sizeof (EFI_ACPI_SUPPORT_INSTANCE)); - ASSERT (PrivateData); - PrivateData->Signature = EFI_ACPI_SUPPORT_SIGNATURE; - - // - // Call all constructors per produced protocols - // - Status = AcpiSupportAcpiSupportConstructor (PrivateData); - if (EFI_ERROR (Status)) { - gBS->FreePool (PrivateData); - return EFI_LOAD_ERROR; - } - - // - // Install ACPI Table protocol and optional ACPI support protocol based on - // feature flag: PcdInstallAcpiSupportProtocol. - // - if (FeaturePcdGet (PcdInstallAcpiSupportProtocol)) { - Status = gBS->InstallMultipleProtocolInterfaces ( - &mHandle, - &gEfiAcpiTableProtocolGuid, - &PrivateData->AcpiTableProtocol, - &gEfiAcpiSupportProtocolGuid, - &PrivateData->AcpiSupport, - NULL - ); - ASSERT_EFI_ERROR (Status); - } else { - Status = gBS->InstallMultipleProtocolInterfaces ( - &mHandle, - &gEfiAcpiTableProtocolGuid, - &PrivateData->AcpiTableProtocol, - NULL - ); - ASSERT_EFI_ERROR (Status); - } - - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.h b/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.h deleted file mode 100644 index 1bcf1e6ee5..0000000000 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupport.h +++ /dev/null @@ -1,166 +0,0 @@ -/** @file - This is an implementation of the ACPI Support protocol. - It is in compliance with the 0.9 definition of the protocol. - -Copyright (c) 2006 - 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 _ACPI_SUPPORT_H_ -#define _ACPI_SUPPORT_H_ - - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Statements that include other files -// -#include - - -// -// Private Driver Data -// -// -// ACPI Table Linked List Signature. -// -#define EFI_ACPI_TABLE_LIST_SIGNATURE SIGNATURE_32 ('E', 'A', 'T', 'L') - -// -// ACPI Table Linked List Entry definition. -// -// Signature must be set to EFI_ACPI_TABLE_LIST_SIGNATURE -// Link is the linked list data. -// Version is the versions of the ACPI tables that this table belongs in. -// Table is a pointer to the table. -// PageAddress is the address of the pages allocated for the table. -// NumberOfPages is the number of pages allocated at PageAddress. -// Handle is used to identify a particular table. -// -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - EFI_ACPI_TABLE_VERSION Version; - EFI_ACPI_COMMON_HEADER *Table; - EFI_PHYSICAL_ADDRESS PageAddress; - UINTN NumberOfPages; - UINTN Handle; -} EFI_ACPI_TABLE_LIST; - -// -// Containment record for linked list. -// -#define EFI_ACPI_TABLE_LIST_FROM_LINK(_link) CR (_link, EFI_ACPI_TABLE_LIST, Link, EFI_ACPI_TABLE_LIST_SIGNATURE) - -// -// The maximum number of tables this driver supports -// -#define EFI_ACPI_MAX_NUM_TABLES 20 - -// -// Protocol private structure definition -// -// -// ACPI support protocol instance signature definition. -// -#define EFI_ACPI_SUPPORT_SIGNATURE SIGNATURE_32 ('S', 'S', 'A', 'E') - -// -// ACPI support protocol instance data structure -// -typedef struct { - UINTN Signature; - EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp1; // Pointer to RSD_PTR structure - EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp3; // Pointer to RSD_PTR structure - EFI_ACPI_DESCRIPTION_HEADER *Rsdt1; // Pointer to RSDT table header - EFI_ACPI_DESCRIPTION_HEADER *Rsdt3; // Pointer to RSDT table header - EFI_ACPI_DESCRIPTION_HEADER *Xsdt; // Pointer to XSDT table header - EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1; // Pointer to FADT table header - EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt3; // Pointer to FADT table header - EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1; // Pointer to FACS table header - EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs3; // Pointer to FACS table header - EFI_ACPI_DESCRIPTION_HEADER *Dsdt1; // Pointer to DSDT table header - EFI_ACPI_DESCRIPTION_HEADER *Dsdt3; // Pointer to DSDT table header - LIST_ENTRY TableList; - UINTN NumberOfTableEntries1; // Number of ACPI 1.0 tables - UINTN NumberOfTableEntries3; // Number of ACPI 3.0 tables - UINTN CurrentHandle; - BOOLEAN TablesInstalled1; // ACPI 1.0 tables published - BOOLEAN TablesInstalled3; // ACPI 3.0 tables published - EFI_ACPI_SUPPORT_PROTOCOL AcpiSupport; - EFI_ACPI_TABLE_PROTOCOL AcpiTableProtocol; -} EFI_ACPI_SUPPORT_INSTANCE; - -// -// ACPI support protocol instance containing record macro -// -#define EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS(a) \ - CR (a, \ - EFI_ACPI_SUPPORT_INSTANCE, \ - AcpiSupport, \ - EFI_ACPI_SUPPORT_SIGNATURE \ - ) -// -// ACPI table protocol instance containing record macro -// -#define EFI_ACPI_TABLE_INSTANCE_FROM_ACPI_SUPPORT_THIS(a) \ - CR (a, \ - EFI_ACPI_SUPPORT_INSTANCE, \ - AcpiTableProtocol, \ - EFI_ACPI_SUPPORT_SIGNATURE \ - ) - -/** - Constructor for the ACPI support protocol. - - Constructor for the ACPI support protocol to initializes instance data. - - @param AcpiSupportInstance Instance to construct - - @retval EFI_SUCCESS Instance initialized. - @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. -**/ -EFI_STATUS -AcpiSupportAcpiSupportConstructor ( - IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance - ); -/** - Entry point of the ACPI support driver. This function creates and initializes an instance of the ACPI Support - Protocol and installs it on a new handle. - - @param ImageHandle A handle for the image that is initializing this driver - @param 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 -InstallAcpiSupport ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); -#endif diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportAcpiSupportProtocol.c b/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportAcpiSupportProtocol.c deleted file mode 100644 index 6443c3acd0..0000000000 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportAcpiSupportProtocol.c +++ /dev/null @@ -1,1918 +0,0 @@ -/** @file - ACPI Support Protocol implementation - -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 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. - -**/ - -// -// Includes -// -#include "AcpiSupport.h" -// -// The maximum number of tables that pre-allocated. -// -UINTN mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES; -/** - This function adds an ACPI table to the table list. It will detect FACS and - allocate the correct type of memory and properly align the table. - - @param AcpiSupportInstance Instance of the protocol. - @param Table Table to add. - @param Checksum Does the table require checksumming. - @param Version The version of the list to add the table to. - @param Handle Pointer for returning the handle. - - @return EFI_SUCCESS The function completed successfully. - @return EFI_OUT_OF_RESOURCES Could not allocate a required resource. - @return EFI_ABORTED The table is a duplicate of a table that is required - to be unique. -**/ -EFI_STATUS -AddTableToList ( - IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, - IN VOID *Table, - IN BOOLEAN Checksum, - IN EFI_ACPI_TABLE_VERSION Version, - OUT UINTN *Handle - ); -/** - This function finds and removes the table specified by the handle. - - @param AcpiSupportInstance Instance of the protocol. - @param Version Bitmask of which versions to remove. - @param Handle Table to remove. - - @return EFI_SUCCESS The function completed successfully. - @return EFI_ABORTED An error occurred. - @return EFI_NOT_FOUND Handle not found in table list. -**/ -EFI_STATUS -RemoveTableFromList ( - IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, - IN EFI_ACPI_TABLE_VERSION Version, - IN UINTN Handle - ); -/** - This function calculates and updates an UINT8 checksum. - - @param Buffer Pointer to buffer to checksum - @param Size Number of bytes to checksum - @param ChecksumOffset Offset to place the checksum result in - - @return EFI_SUCCESS The function completed successfully. -**/ -EFI_STATUS -AcpiPlatformChecksum ( - IN VOID *Buffer, - IN UINTN Size, - IN UINTN ChecksumOffset - ); -/** - Checksum all versions of the common tables, RSDP, RSDT, XSDT. - - @param AcpiSupportInstance Protocol instance private data. - - @return EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -ChecksumCommonTables ( - IN OUT EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance - ); - -/** - This function returns a table specified by an index if it exists. - - The function returns a buffer containing the table that the caller must free. - The function also returns a handle used to identify the table for update or - deletion using the SetAcpiTable function. - - @param This Instance of the protocol. - @param Index Zero-based index of the table to retrieve. - @param Table Returned pointer to the table. - @param Version Versions that the table is currently used in. - @param Handle Handle of the table, used in updating tables. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_NOT_FOUND The requested table does not exist. - -**/ -EFI_STATUS -EFIAPI -GetAcpiTable ( - IN EFI_ACPI_SUPPORT_PROTOCOL *This, - IN INTN Index, - OUT VOID **Table, - OUT EFI_ACPI_TABLE_VERSION *Version, - OUT UINTN *Handle - ) - -{ - EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; - INTN TempIndex; - LIST_ENTRY *CurrentLink; - LIST_ENTRY *StartLink; - EFI_ACPI_TABLE_LIST *CurrentTable; - - // - // Check for invalid input parameters - // - ASSERT (This); - ASSERT (Table); - ASSERT (Handle); - - // - // Get the instance of the protocol - // - AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); - - // - // Find the table - // - CurrentLink = AcpiSupportInstance->TableList.ForwardLink; - StartLink = &AcpiSupportInstance->TableList; - for (TempIndex = 0; (TempIndex < Index) && (CurrentLink != StartLink) && (CurrentLink != NULL); TempIndex++) { - CurrentLink = CurrentLink->ForwardLink; - } - - if (TempIndex != Index || CurrentLink == StartLink) { - return EFI_NOT_FOUND; - } - // - // Get handle and version - // - CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink); - *Handle = CurrentTable->Handle; - *Version = CurrentTable->Version; - - // - // Copy the table - // - *Table = AllocateCopyPool (CurrentTable->Table->Length, CurrentTable->Table); - ASSERT (*Table); - - return EFI_SUCCESS; -} -/** - This function adds, removes, or updates ACPI tables. If the address is not - null and the handle value is null, the table is added. If both the address and - handle are not null, the table at handle is updated with the table at address. - If the address is null and the handle is not, the table at handle is deleted. - - @param This Pointer of the protocol. - @param Table Pointer to a table. - @param Checksum Boolean indicating if the checksum should be calculated. - @param Version Version(s) to set. - @param Handle Handle of the table. - - @return EFI_SUCCESS The function completed successfully. - @return EFI_INVALID_PARAMETER Both the Table and *Handle were NULL. - @return EFI_ABORTED Could not complete the desired request. - -**/ -EFI_STATUS -EFIAPI -SetAcpiTable ( - IN EFI_ACPI_SUPPORT_PROTOCOL *This, - IN VOID *Table OPTIONAL, - IN BOOLEAN Checksum, - IN EFI_ACPI_TABLE_VERSION Version, - IN OUT UINTN *Handle - ) -{ - EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; - UINTN SavedHandle; - EFI_STATUS Status; - - // - // Check for invalid input parameters - // - ASSERT (This); - ASSERT (Handle != NULL); - - // - // Get the instance of the protocol - // - AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); - - // - // Initialize locals - // - // - // Determine desired action - // - if (*Handle == 0) { - if (Table == NULL) { - // - // Invalid parameter combination - // - return EFI_INVALID_PARAMETER; - } else { - // - // Add table - // - Status = AddTableToList (AcpiSupportInstance, Table, Checksum, Version, Handle); - } - } else { - if (Table != NULL) { - // - // Update table - // - // - // Delete the table list entry - // - Status = RemoveTableFromList (AcpiSupportInstance, Version, *Handle); - if (EFI_ERROR (Status)) { - // - // Should not get an error here ever, but abort if we do. - // - return EFI_ABORTED; - } - // - // Set the handle to replace the table at the same handle - // - SavedHandle = AcpiSupportInstance->CurrentHandle; - AcpiSupportInstance->CurrentHandle = *Handle; - - // - // Add the table - // - Status = AddTableToList (AcpiSupportInstance, Table, Checksum, Version, Handle); - - // - // Restore the saved current handle - // - AcpiSupportInstance->CurrentHandle = SavedHandle; - } else { - // - // Delete table - // - Status = RemoveTableFromList (AcpiSupportInstance, Version, *Handle); - } - } - - if (EFI_ERROR (Status)) { - // - // Should not get an error here ever, but abort if we do. - // - return EFI_ABORTED; - } - // - // Done - // - return EFI_SUCCESS; -} -/** - This function publishes the specified versions of the ACPI tables by - installing EFI configuration table entries for them. Any combination of - table versions can be published. - - @param This Pointer of the protocol. - @param Version Version(s) to publish. - - @return EFI_SUCCESS The function completed successfully. - @return EFI_ABORTED The function could not complete successfully. - -**/ -EFI_STATUS -EFIAPI -PublishTables ( - IN EFI_ACPI_SUPPORT_PROTOCOL *This, - IN EFI_ACPI_TABLE_VERSION Version - ) -{ - EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; - EFI_STATUS Status; - UINT32 *CurrentRsdtEntry; - VOID *CurrentXsdtEntry; - UINT64 Buffer64; - - // - // Get the instance of the protocol - // - AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); - - // - // Reorder tables as some operating systems don't seem to find the - // FADT correctly if it is not in the first few entries - // - - // - // Add FADT as the first entry - // - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { - CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiSupportInstance->Rsdt1 + sizeof (EFI_ACPI_DESCRIPTION_HEADER)); - *CurrentRsdtEntry = (UINT32) (UINTN) AcpiSupportInstance->Fadt1; - } - if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { - CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiSupportInstance->Rsdt3 + sizeof (EFI_ACPI_DESCRIPTION_HEADER)); - *CurrentRsdtEntry = (UINT32) (UINTN) AcpiSupportInstance->Fadt3; - CurrentXsdtEntry = (VOID *) ((UINT8 *) AcpiSupportInstance->Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER)); - // - // Add entry to XSDT, XSDT expects 64 bit pointers, but - // the table pointers in XSDT are not aligned on 8 byte boundary. - // - Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Fadt3; - CopyMem ( - CurrentXsdtEntry, - &Buffer64, - sizeof (UINT64) - ); - } - - // - // Do checksum again because Dsdt/Xsdt is updated. - // - ChecksumCommonTables (AcpiSupportInstance); - - // - // Add the RSD_PTR to the system table and store that we have installed the - // tables. - // - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && !AcpiSupportInstance->TablesInstalled1) { - Status = gBS->InstallConfigurationTable (&gEfiAcpi10TableGuid, AcpiSupportInstance->Rsdp1); - if (EFI_ERROR (Status)) { - return EFI_ABORTED; - } - - AcpiSupportInstance->TablesInstalled1 = TRUE; - } - - if (((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) && - !AcpiSupportInstance->TablesInstalled3) { - Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, AcpiSupportInstance->Rsdp3); - if (EFI_ERROR (Status)) { - return EFI_ABORTED; - } - - AcpiSupportInstance->TablesInstalled3= TRUE; - } - - return EFI_SUCCESS; -} -/** - Installs an ACPI table into the RSDT/XSDT. - Note that the ACPI table should be checksumed before installing it. - Otherwise it will assert. - - @param This Protocol instance pointer. - @param AcpiTableBuffer A pointer to a buffer containing the ACPI table to be installed. - @param AcpiTableBufferSize Specifies the size, in bytes, of the AcpiTableBuffer buffer. - @param TableKey Reurns a key to refer to the ACPI table. - - @return EFI_SUCCESS The table was successfully inserted. - @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize - and the size field embedded in the ACPI table pointed to by AcpiTableBuffer - are not in sync. - @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request. - @retval EFI_ACCESS_DENIED The table signature matches a table already - present in the system and platform policy - does not allow duplicate tables of this type. - -**/ -EFI_STATUS -EFIAPI -InstallAcpiTable ( - IN EFI_ACPI_TABLE_PROTOCOL *This, - IN VOID *AcpiTableBuffer, - IN UINTN AcpiTableBufferSize, - OUT UINTN *TableKey - ) -{ - EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; - EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport; - EFI_STATUS Status; - VOID *AcpiTableBufferConst; - - // - // Check for invalid input parameters - // - if ((AcpiTableBuffer == NULL) || (TableKey == NULL) - || (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer)->Length != AcpiTableBufferSize)) { - return EFI_INVALID_PARAMETER; - } - - // - // Get the instance of the ACPI support protocol - // - AcpiSupportInstance = EFI_ACPI_TABLE_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); - AcpiSupport = &AcpiSupportInstance->AcpiSupport; - - // - // Install the ACPI table by using ACPI support protocol - // - AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize, AcpiTableBuffer); - *TableKey = 0; - Status = AddTableToList ( - AcpiSupportInstance, - AcpiTableBufferConst, - TRUE, - EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0, - TableKey - ); - if (!EFI_ERROR (Status)) { - Status = AcpiSupport->PublishTables ( - AcpiSupport, - EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0 - ); - } - FreePool (AcpiTableBufferConst); - - return Status; -} -/** - Removes an ACPI table from the RSDT/XSDT. - - @param This Protocol instance pointer. - @param TableKey Specifies the table to uninstall. The key was returned from InstallAcpiTable(). - - @return EFI_SUCCESS The table was successfully uninstalled. - @return EFI_NOT_FOUND TableKey does not refer to a valid key for a table entry. - -**/ -EFI_STATUS -EFIAPI -UninstallAcpiTable ( - IN EFI_ACPI_TABLE_PROTOCOL *This, - IN UINTN TableKey - ) -{ - EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance; - EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport; - EFI_STATUS Status; - - // - // Get the instance of the ACPI support protocol - // - AcpiSupportInstance = EFI_ACPI_TABLE_INSTANCE_FROM_ACPI_SUPPORT_THIS (This); - AcpiSupport = &AcpiSupportInstance->AcpiSupport; - - // - // Uninstall the ACPI table by using ACPI support protocol - // - Status = RemoveTableFromList ( - AcpiSupportInstance, - EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0, - TableKey - ); - if (!EFI_ERROR (Status)) { - Status = AcpiSupport->PublishTables ( - AcpiSupport, - EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0 - ); - } - - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } else { - return EFI_SUCCESS; - } -} -/** - If the number of APCI tables exceeds the preallocated max table number, enlarge the table buffer. - - @param AcpiSupportInstance ACPI support protocol instance data structure - - @return EFI_SUCCESS reallocate the table beffer successfully. - @return EFI_OUT_OF_RESOURCES Unable to allocate required resources. - -**/ -EFI_STATUS -ReallocateAcpiTableBuffer ( - IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance - ) -{ - UINTN NewMaxTableNumber; - UINTN TotalSize; - UINT8 *Pointer; - EFI_PHYSICAL_ADDRESS PageAddress; - EFI_ACPI_SUPPORT_INSTANCE TempPrivateData; - EFI_STATUS Status; - UINT64 CurrentData; - - CopyMem (&TempPrivateData, AcpiSupportInstance, sizeof (EFI_ACPI_SUPPORT_INSTANCE)); - // - // Enlarge the max table number from mEfiAcpiMaxNumTables to mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES - // - NewMaxTableNumber = mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES; - // - // Create RSDT, XSDT structures and allocate buffers. - // - TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT - NewMaxTableNumber * sizeof (UINT32) + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT - NewMaxTableNumber * sizeof (UINT32) + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT - NewMaxTableNumber * sizeof (UINT64); - - // - // Allocate memory in the lower 32 bit of address range for - // compatibility with ACPI 1.0 OS. - // - // This is done because ACPI 1.0 pointers are 32 bit values. - // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses. - // There is no architectural reason these should be below 4GB, it is purely - // for convenience of implementation that we force memory below 4GB. - // - PageAddress = 0xFFFFFFFF; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIReclaimMemory, - EFI_SIZE_TO_PAGES (TotalSize), - &PageAddress - ); - - if (EFI_ERROR (Status)) { - return EFI_OUT_OF_RESOURCES; - } - - Pointer = (UINT8 *) (UINTN) PageAddress; - ZeroMem (Pointer, TotalSize); - - AcpiSupportInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; - Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32)); - AcpiSupportInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; - Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32)); - AcpiSupportInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; - - // - // Update RSDP to point to the new Rsdt and Xsdt address. - // - AcpiSupportInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt1; - AcpiSupportInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt3; - CurrentData = (UINT64) (UINTN) AcpiSupportInstance->Xsdt; - CopyMem (&AcpiSupportInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64)); - - // - // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer - // - CopyMem (AcpiSupportInstance->Rsdt1, TempPrivateData.Rsdt1, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); - CopyMem (AcpiSupportInstance->Rsdt3, TempPrivateData.Rsdt3, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); - CopyMem (AcpiSupportInstance->Xsdt, TempPrivateData.Xsdt, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT64))); - - // - // Calculate orignal ACPI table buffer size - // - TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT - mEfiAcpiMaxNumTables * sizeof (UINT32) + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT - mEfiAcpiMaxNumTables * sizeof (UINT32) + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT - mEfiAcpiMaxNumTables * sizeof (UINT64); - gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize)); - - // - // Update the Max ACPI table number - // - mEfiAcpiMaxNumTables = NewMaxTableNumber; - return EFI_SUCCESS; -} -/** - This function adds an ACPI table to the table list. It will detect FACS and - allocate the correct type of memory and properly align the table. - - @param AcpiSupportInstance Instance of the protocol. - @param Table Table to add. - @param Checksum Does the table require checksumming. - @param Version The version of the list to add the table to. - @param Handle Pointer for returning the handle. - - @return EFI_SUCCESS The function completed successfully. - @return EFI_OUT_OF_RESOURCES Could not allocate a required resource. - @retval EFI_ACCESS_DENIED The table signature matches a table already - present in the system and platform policy - does not allow duplicate tables of this type. -**/ -EFI_STATUS -AddTableToList ( - IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, - IN VOID *Table, - IN BOOLEAN Checksum, - IN EFI_ACPI_TABLE_VERSION Version, - OUT UINTN *Handle - ) -{ - EFI_STATUS Status; - EFI_ACPI_TABLE_LIST *CurrentTableList; - UINT32 CurrentTableSignature; - UINT32 CurrentTableSize; - UINT32 *CurrentRsdtEntry; - VOID *CurrentXsdtEntry; - UINT64 Buffer64; - BOOLEAN AddToRsdt; - - // - // Check for invalid input parameters - // - ASSERT (AcpiSupportInstance); - ASSERT (Table); - ASSERT (Handle); - - // - // Init locals - // - AddToRsdt = TRUE; - - // - // Create a new list entry - // - CurrentTableList = AllocatePool (sizeof (EFI_ACPI_TABLE_LIST)); - ASSERT (CurrentTableList); - - // - // Determine table type and size - // - CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table)->Signature; - CurrentTableSize = ((EFI_ACPI_COMMON_HEADER *) Table)->Length; - - // - // Allocate a buffer for the table. All tables are allocated in the lower 32 bits of address space - // for backwards compatibility with ACPI 1.0 OS. - // - // This is done because ACPI 1.0 pointers are 32 bit values. - // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses. - // There is no architectural reason these should be below 4GB, it is purely - // for convenience of implementation that we force memory below 4GB. - // - CurrentTableList->PageAddress = 0xFFFFFFFF; - CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize); - - // - // Allocation memory type depends on the type of the table - // - if ((CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) || - (CurrentTableSignature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE)) { - // - // Allocate memory for the FACS. This structure must be aligned - // on a 64 byte boundary and must be ACPI NVS memory. - // Using AllocatePages should ensure that it is always aligned. - // Do not change signature for new ACPI version because they are same. - // - // UEFI table also need to be in ACPI NVS memory, because some data field - // could be updated by OS present agent. For example, BufferPtrAddress in - // SMM communication ACPI table. - // - ASSERT ((EFI_PAGE_SIZE % 64) == 0); - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - CurrentTableList->NumberOfPages, - &CurrentTableList->PageAddress - ); - } else { - // - // All other tables are ACPI reclaim memory, no alignment requirements. - // - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIReclaimMemory, - CurrentTableList->NumberOfPages, - &CurrentTableList->PageAddress - ); - } - // - // Check return value from memory alloc. - // - if (EFI_ERROR (Status)) { - gBS->FreePool (CurrentTableList); - return EFI_OUT_OF_RESOURCES; - } - // - // Update the table pointer with the allocated memory start - // - CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress; - - // - // Initialize the table contents - // - CurrentTableList->Signature = EFI_ACPI_TABLE_LIST_SIGNATURE; - CopyMem (CurrentTableList->Table, Table, CurrentTableSize); - CurrentTableList->Handle = AcpiSupportInstance->CurrentHandle++; - *Handle = CurrentTableList->Handle; - CurrentTableList->Version = Version; - - // - // Update internal pointers if this is a required table. If it is a required - // table and a table of that type already exists, return an error. - // - // Calculate the checksum if the table is not FACS. - // - switch (CurrentTableSignature) { - - case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: - // - // We don't add the FADT in the standard way because some - // OS expect the FADT to be early in the table list. - // So we always add it as the first element in the list. - // - AddToRsdt = FALSE; - - // - // Check that the table has not been previously added. - // - if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Fadt1 != NULL) || - ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiSupportInstance->Fadt3 != NULL) || - ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiSupportInstance->Fadt3 != NULL) - ) { - gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages); - gBS->FreePool (CurrentTableList); - return EFI_ACCESS_DENIED; - } - // - // Add the table to the appropriate table version - // - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { - // - // Save a pointer to the table - // - AcpiSupportInstance->Fadt1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table; - - // - // Update pointers in FADT. If tables don't exist this will put NULL pointers there. - // - AcpiSupportInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs1; - AcpiSupportInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt1; - - // - // RSDP OEM information is updated to match the FADT OEM information - // - CopyMem ( - &AcpiSupportInstance->Rsdp1->OemId, - &AcpiSupportInstance->Fadt1->Header.OemId, - 6 - ); - - // - // RSDT OEM information is updated to match the FADT OEM information. - // - CopyMem ( - &AcpiSupportInstance->Rsdt1->OemId, - &AcpiSupportInstance->Fadt1->Header.OemId, - 6 - ); - - CopyMem ( - &AcpiSupportInstance->Rsdt1->OemTableId, - &AcpiSupportInstance->Fadt1->Header.OemTableId, - sizeof (UINT64) - ); - AcpiSupportInstance->Rsdt1->OemRevision = AcpiSupportInstance->Fadt1->Header.OemRevision; - } - - if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || - (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { - // - // Save a pointer to the table - // - AcpiSupportInstance->Fadt3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table; - - // - // Update pointers in FADT. If tables don't exist this will put NULL pointers there. - // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and - // vice-versa. - // - if ((UINT64)(UINTN)AcpiSupportInstance->Facs3 < BASE_4GB) { - AcpiSupportInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs3; - ZeroMem ( - &AcpiSupportInstance->Fadt3->XFirmwareCtrl, - sizeof (UINT64) - ); - } else { - AcpiSupportInstance->Fadt3->FirmwareCtrl = 0; - Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Facs3; - CopyMem ( - &AcpiSupportInstance->Fadt3->XFirmwareCtrl, - &Buffer64, - sizeof (UINT64) - ); - } - AcpiSupportInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt3; - Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Dsdt3; - CopyMem ( - &AcpiSupportInstance->Fadt3->XDsdt, - &Buffer64, - sizeof (UINT64) - ); - - // - // RSDP OEM information is updated to match the FADT OEM information - // - CopyMem ( - &AcpiSupportInstance->Rsdp3->OemId, - &AcpiSupportInstance->Fadt3->Header.OemId, - 6 - ); - - // - // RSDT OEM information is updated to match FADT OEM information. - // - CopyMem ( - &AcpiSupportInstance->Rsdt3->OemId, - &AcpiSupportInstance->Fadt3->Header.OemId, - 6 - ); - CopyMem ( - &AcpiSupportInstance->Rsdt3->OemTableId, - &AcpiSupportInstance->Fadt3->Header.OemTableId, - sizeof (UINT64) - ); - AcpiSupportInstance->Rsdt3->OemRevision = AcpiSupportInstance->Fadt3->Header.OemRevision; - - // - // XSDT OEM information is updated to match FADT OEM information. - // - CopyMem ( - &AcpiSupportInstance->Xsdt->OemId, - &AcpiSupportInstance->Fadt3->Header.OemId, - 6 - ); - CopyMem ( - &AcpiSupportInstance->Xsdt->OemTableId, - &AcpiSupportInstance->Fadt3->Header.OemTableId, - sizeof (UINT64) - ); - AcpiSupportInstance->Xsdt->OemRevision = AcpiSupportInstance->Fadt3->Header.OemRevision; - } - - // - // Checksum the table - // - if (Checksum) { - AcpiPlatformChecksum ( - CurrentTableList->Table, - CurrentTableList->Table->Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - break; - - case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE: - // - // Check that the table has not been previously added. - // - if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Facs1 != NULL) || - ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiSupportInstance->Facs3 != NULL) || - ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiSupportInstance->Facs3 != NULL) - ) { - gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages); - gBS->FreePool (CurrentTableList); - return EFI_ACCESS_DENIED; - } - // - // FACS is referenced by FADT and is not part of RSDT - // - AddToRsdt = FALSE; - - // - // Add the table to the appropriate table version - // - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { - // - // Save a pointer to the table - // - AcpiSupportInstance->Facs1 = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table; - - // - // If FADT already exists, update table pointers. - // - if (AcpiSupportInstance->Fadt1 != NULL) { - AcpiSupportInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs1; - - // - // Checksum FADT table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Fadt1, - AcpiSupportInstance->Fadt1->Header.Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - } - - if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || - (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { - // - // Save a pointer to the table - // - AcpiSupportInstance->Facs3 = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table; - - // - // If FADT already exists, update table pointers. - // - if (AcpiSupportInstance->Fadt3 != NULL) { - // - // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and - // vice-versa. - // - if ((UINT64)(UINTN)AcpiSupportInstance->Facs3 < BASE_4GB) { - AcpiSupportInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs3; - } else { - Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Facs3; - CopyMem ( - &AcpiSupportInstance->Fadt3->XFirmwareCtrl, - &Buffer64, - sizeof (UINT64) - ); - } - - // - // Checksum FADT table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Fadt3, - AcpiSupportInstance->Fadt3->Header.Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - } - - break; - - case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: - // - // Check that the table has not been previously added. - // - if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Dsdt1 != NULL) || - ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiSupportInstance->Dsdt3 != NULL) || - ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiSupportInstance->Dsdt3 != NULL) - ) { - gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages); - gBS->FreePool (CurrentTableList); - return EFI_ACCESS_DENIED; - } - // - // DSDT is referenced by FADT and is not part of RSDT - // - AddToRsdt = FALSE; - - // - // Add the table to the appropriate table version - // - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { - // - // Save a pointer to the table - // - AcpiSupportInstance->Dsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table; - - // - // If FADT already exists, update table pointers. - // - if (AcpiSupportInstance->Fadt1 != NULL) { - AcpiSupportInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt1; - - // - // Checksum FADT table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Fadt1, - AcpiSupportInstance->Fadt1->Header.Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - } - - if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || - (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { - // - // Save a pointer to the table - // - AcpiSupportInstance->Dsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table; - - // - // If FADT already exists, update table pointers. - // - if (AcpiSupportInstance->Fadt3 != NULL) { - AcpiSupportInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt3; - Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Dsdt3; - CopyMem ( - &AcpiSupportInstance->Fadt3->XDsdt, - &Buffer64, - sizeof (UINT64) - ); - - // - // Checksum FADT table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Fadt3, - AcpiSupportInstance->Fadt3->Header.Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - } - // - // Checksum the table - // - if (Checksum) { - AcpiPlatformChecksum ( - CurrentTableList->Table, - CurrentTableList->Table->Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - break; - - default: - // - // Checksum the table - // - if (Checksum) { - AcpiPlatformChecksum ( - CurrentTableList->Table, - CurrentTableList->Table->Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - break; - } - // - // Add the table to the current list of tables - // - InsertTailList (&AcpiSupportInstance->TableList, &CurrentTableList->Link); - - // - // Add the table to RSDT and/or XSDT table entry lists. - // - // - // Add to ACPI 1.0b table tree - // - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { - if (AddToRsdt) { - // - // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer - // - if (AcpiSupportInstance->NumberOfTableEntries1 >= mEfiAcpiMaxNumTables) { - Status = ReallocateAcpiTableBuffer (AcpiSupportInstance); - ASSERT_EFI_ERROR (Status); - } - CurrentRsdtEntry = (UINT32 *) - ( - (UINT8 *) AcpiSupportInstance->Rsdt1 + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + - AcpiSupportInstance->NumberOfTableEntries1 * - sizeof (UINT32) - ); - - // - // Add entry to the RSDT unless its the FACS or DSDT - // - *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table; - - // - // Update RSDT length - // - AcpiSupportInstance->Rsdt1->Length = AcpiSupportInstance->Rsdt1->Length + sizeof (UINT32); - - AcpiSupportInstance->NumberOfTableEntries1++; - } - } - // - // Add to ACPI 2.0/3.0 table tree - // - if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { - if (AddToRsdt) { - // - // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer - // - if (AcpiSupportInstance->NumberOfTableEntries3 >= mEfiAcpiMaxNumTables) { - Status = ReallocateAcpiTableBuffer (AcpiSupportInstance); - ASSERT_EFI_ERROR (Status); - } - // - // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables. - // If it becomes necessary to maintain separate table lists, changes will be required. - // - CurrentRsdtEntry = (UINT32 *) - ( - (UINT8 *) AcpiSupportInstance->Rsdt3 + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + - AcpiSupportInstance->NumberOfTableEntries3 * - sizeof (UINT32) - ); - - // - // This pointer must not be directly dereferenced as the XSDT entries may not - // be 64 bit aligned resulting in a possible fault. Use CopyMem to update. - // - CurrentXsdtEntry = (VOID *) - ( - (UINT8 *) AcpiSupportInstance->Xsdt + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + - AcpiSupportInstance->NumberOfTableEntries3 * - sizeof (UINT64) - ); - - // - // Add entry to the RSDT - // - *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table; - - // - // Update RSDT length - // - AcpiSupportInstance->Rsdt3->Length = AcpiSupportInstance->Rsdt3->Length + sizeof (UINT32); - - // - // Add entry to XSDT, XSDT expects 64 bit pointers, but - // the table pointers in XSDT are not aligned on 8 byte boundary. - // - Buffer64 = (UINT64) (UINTN) CurrentTableList->Table; - CopyMem ( - CurrentXsdtEntry, - &Buffer64, - sizeof (UINT64) - ); - - // - // Update length - // - AcpiSupportInstance->Xsdt->Length = AcpiSupportInstance->Xsdt->Length + sizeof (UINT64); - - AcpiSupportInstance->NumberOfTableEntries3++; - } - } - - ChecksumCommonTables (AcpiSupportInstance); - return EFI_SUCCESS; -} -/** - This function finds the table specified by the handle and returns a pointer to it. - If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are - undefined. - - @param Handle Table to find. - @param TableList Table list to search - @param Table Pointer to table found. - - @return EFI_SUCCESS The function completed successfully. - @return EFI_NOT_FOUND No table found matching the handle specified. - -**/ -EFI_STATUS -FindTableByHandle ( - IN UINTN Handle, - IN LIST_ENTRY *TableList, - OUT EFI_ACPI_TABLE_LIST **Table - ) -{ - LIST_ENTRY *CurrentLink; - EFI_ACPI_TABLE_LIST *CurrentTable; - - // - // Check for invalid input parameters - // - ASSERT (Table); - - // - // Find the table - // - CurrentLink = TableList->ForwardLink; - - while (CurrentLink != TableList) { - CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink); - if (CurrentTable->Handle == Handle) { - // - // Found handle, so return this table. - // - *Table = CurrentTable; - return EFI_SUCCESS; - } - - CurrentLink = CurrentLink->ForwardLink; - } - // - // Table not found - // - return EFI_NOT_FOUND; -} -/** - This function removes a basic table from the RSDT and/or XSDT. - For Acpi 1.0 tables, pass in the Rsdt. - For Acpi 2.0 tables, pass in both Rsdt and Xsdt. - - @param Table Pointer to table found. - @param NumberOfTableEntries Current number of table entries in the RSDT/XSDT - @param Rsdt Pointer to the RSDT to remove from - @param Xsdt Pointer to the Xsdt to remove from - - @return EFI_SUCCESS The function completed successfully. - @return EFI_INVALID_PARAMETER The table was not found in both Rsdt and Xsdt. - -**/ -EFI_STATUS -RemoveTableFromRsdt ( - IN OUT EFI_ACPI_TABLE_LIST * Table, - IN OUT UINTN *NumberOfTableEntries, - IN OUT EFI_ACPI_DESCRIPTION_HEADER * Rsdt, - IN OUT EFI_ACPI_DESCRIPTION_HEADER * Xsdt OPTIONAL - ) -{ - UINT32 *CurrentRsdtEntry; - VOID *CurrentXsdtEntry; - UINT64 CurrentTablePointer64; - UINTN TempIndex; - - // - // Check for invalid input parameters - // - ASSERT (Table); - ASSERT (NumberOfTableEntries); - ASSERT (Rsdt); - - // - // Find the table entry in the RSDT and XSDT - // - for (TempIndex = 0; TempIndex < *NumberOfTableEntries; TempIndex++) { - // - // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables. - // If it becomes necessary to maintain separate table lists, changes will be required. - // - CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + TempIndex * sizeof (UINT32)); - if (Xsdt != NULL) { - // - // This pointer must not be directly dereferenced as the XSDT entries may not - // be 64 bit aligned resulting in a possible fault. Use CopyMem to update. - // - CurrentXsdtEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + TempIndex * sizeof (UINT64)); - - // - // Read the entry value out of the XSDT - // - CopyMem (&CurrentTablePointer64, CurrentXsdtEntry, sizeof (UINT64)); - } else { - // - // Initialize to NULL - // - CurrentXsdtEntry = 0; - CurrentTablePointer64 = 0; - } - // - // Check if we have found the corresponding entry in both RSDT and XSDT - // - if (*CurrentRsdtEntry == (UINT32) (UINTN) Table->Table && - ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table) - ) { - // - // Found entry, so copy all following entries and shrink table - // We actually copy all + 1 to copy the initialized value of memory over - // the last entry. - // - CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - TempIndex) * sizeof (UINT32)); - Rsdt->Length = Rsdt->Length - sizeof (UINT32); - if (Xsdt != NULL) { - CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - TempIndex) * sizeof (UINT64)); - Xsdt->Length = Xsdt->Length - sizeof (UINT64); - } - break; - } else if (TempIndex + 1 == *NumberOfTableEntries) { - // - // At the last entry, and table not found - // - return EFI_INVALID_PARAMETER; - } - } - // - // Checksum the tables - // - AcpiPlatformChecksum ( - Rsdt, - Rsdt->Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - - if (Xsdt != NULL) { - AcpiPlatformChecksum ( - Xsdt, - Xsdt->Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - // - // Decrement the number of tables - // - (*NumberOfTableEntries)--; - - return EFI_SUCCESS; -} -/** - This function removes a table and frees any associated memory. - - @param AcpiSupportInstance Instance of the protocol. - @param Version Version(s) to delete. - @param Table Pointer to table found. - - @return EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -DeleteTable ( - IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, - IN EFI_ACPI_TABLE_VERSION Version, - IN OUT EFI_ACPI_TABLE_LIST *Table - ) -{ - UINT32 CurrentTableSignature; - BOOLEAN RemoveFromRsdt; - - // - // Check for invalid input parameters - // - ASSERT (AcpiSupportInstance); - ASSERT (Table); - - // - // Init locals - // - RemoveFromRsdt = TRUE; - - if (Table->Table != NULL) { - CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table->Table)->Signature; - - // - // Basic tasks to accomplish delete are: - // Determine removal requirements (in RSDT/XSDT or not) - // Remove entry from RSDT/XSDT - // Remove any table references to the table - // If no one is using the table - // Free the table (removing pointers from private data and tables) - // Remove from list - // Free list structure - // - // - // Determine if this table is in the RSDT or XSDT - // - if ((CurrentTableSignature == EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) || - (CurrentTableSignature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) || - (CurrentTableSignature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) - ) { - RemoveFromRsdt = FALSE; - } - // - // We don't remove the FADT in the standard way because some - // OS expect the FADT to be early in the table list. - // So we always put it as the first element in the list. - // - if (CurrentTableSignature == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { - RemoveFromRsdt = FALSE; - } - - // - // Remove the table from RSDT and XSDT - // - - // - // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt - // - if (Version & EFI_ACPI_TABLE_VERSION_NONE & Table->Version) { - // - // Remove this version from the table - // - Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_NONE; - } - - if (Version & EFI_ACPI_TABLE_VERSION_1_0B & Table->Version) { - // - // Remove this version from the table - // - Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_1_0B; - - // - // Remove from Rsdt. We don't care about the return value because it is - // acceptable for the table to not exist in Rsdt. - // We didn't add some tables so we don't remove them. - // - if (RemoveFromRsdt) { - RemoveTableFromRsdt ( - Table, - &AcpiSupportInstance->NumberOfTableEntries1, - AcpiSupportInstance->Rsdt1, - NULL - ); - } - } - - if ((Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) || - (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version)) { - // - // Remove this version from the table - // - if (Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) { - Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_2_0; - } - if (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version) { - Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_3_0; - } - - // - // Remove from Rsdt and Xsdt. We don't care about the return value - // because it is acceptable for the table to not exist in Rsdt/Xsdt. - // We didn't add some tables so we don't remove them. - // - if (RemoveFromRsdt) { - RemoveTableFromRsdt ( - Table, - &AcpiSupportInstance->NumberOfTableEntries3, - AcpiSupportInstance->Rsdt3, - AcpiSupportInstance->Xsdt - ); - } - } - // - // Free the table, clean up any dependent tables and our private data pointers. - // - switch (Table->Table->Signature) { - - case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { - AcpiSupportInstance->Fadt1 = NULL; - } - - if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || - (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { - AcpiSupportInstance->Fadt3 = NULL; - } - break; - - case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE: - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { - AcpiSupportInstance->Facs1 = NULL; - - // - // Update FADT table pointers - // - if (AcpiSupportInstance->Fadt1 != NULL) { - AcpiSupportInstance->Fadt1->FirmwareCtrl = 0; - - // - // Checksum table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Fadt1, - AcpiSupportInstance->Fadt1->Header.Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - } - - if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || - (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { - AcpiSupportInstance->Facs3 = NULL; - - // - // Update FADT table pointers - // - if (AcpiSupportInstance->Fadt3 != NULL) { - AcpiSupportInstance->Fadt3->FirmwareCtrl = 0; - ZeroMem (&AcpiSupportInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64)); - - // - // Checksum table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Fadt3, - AcpiSupportInstance->Fadt3->Header.Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - } - break; - - case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: - if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) { - AcpiSupportInstance->Dsdt1 = NULL; - - // - // Update FADT table pointers - // - if (AcpiSupportInstance->Fadt1 != NULL) { - AcpiSupportInstance->Fadt1->Dsdt = 0; - - // - // Checksum table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Fadt1, - AcpiSupportInstance->Fadt1->Header.Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - } - - - if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || - (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) { - AcpiSupportInstance->Dsdt3 = NULL; - - // - // Update FADT table pointers - // - if (AcpiSupportInstance->Fadt3 != NULL) { - AcpiSupportInstance->Fadt3->Dsdt = 0; - ZeroMem (&AcpiSupportInstance->Fadt3->XDsdt, sizeof (UINT64)); - - // - // Checksum table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Fadt3, - AcpiSupportInstance->Fadt3->Header.Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - } - } - break; - - default: - // - // Do nothing - // - break; - } - } - // - // If no version is using this table anymore, remove and free list entry. - // - if (Table->Version == 0) { - // - // Free the Table - // - gBS->FreePages (Table->PageAddress, Table->NumberOfPages); - RemoveEntryList (&(Table->Link)); - gBS->FreePool (Table); - } - // - // Done - // - return EFI_SUCCESS; -} -/** - This function finds and removes the table specified by the handle. - - @param AcpiSupportInstance Instance of the protocol. - @param Version Bitmask of which versions to remove. - @param Handle Table to remove. - - @return EFI_SUCCESS The function completed successfully. - @return EFI_ABORTED An error occurred. - @return EFI_NOT_FOUND Handle not found in table list. -**/ -EFI_STATUS -RemoveTableFromList ( - IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance, - IN EFI_ACPI_TABLE_VERSION Version, - IN UINTN Handle - ) -{ - EFI_ACPI_TABLE_LIST *Table; - EFI_STATUS Status; - - Table = NULL; - - // - // Check for invalid input parameters - // - ASSERT (AcpiSupportInstance); - - // - // Find the table - // - Status = FindTableByHandle ( - Handle, - &AcpiSupportInstance->TableList, - &Table - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - // - // Remove the table - // - Status = DeleteTable (AcpiSupportInstance, Version, Table); - if (EFI_ERROR (Status)) { - return EFI_ABORTED; - } - // - // Completed successfully - // - return EFI_SUCCESS; -} -/** - This function calculates and updates an UINT8 checksum. - - @param Buffer Pointer to buffer to checksum - @param Size Number of bytes to checksum - @param ChecksumOffset Offset to place the checksum result in - - @return EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -AcpiPlatformChecksum ( - IN VOID *Buffer, - IN UINTN Size, - IN UINTN ChecksumOffset - ) -{ - UINT8 Sum; - UINT8 *Ptr; - - Sum = 0; - // - // Initialize pointer - // - Ptr = Buffer; - - // - // set checksum to 0 first - // - Ptr[ChecksumOffset] = 0; - - // - // add all content of buffer - // - while ((Size--) != 0) { - Sum = (UINT8) (Sum + (*Ptr++)); - } - // - // set checksum - // - Ptr = Buffer; - Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1); - - return EFI_SUCCESS; -} -/** - Checksum all versions of the common tables, RSDP, RSDT, XSDT. - - @param AcpiSupportInstance Protocol instance private data. - - @return EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -ChecksumCommonTables ( - IN OUT EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance - ) -{ - // - // RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Rsdp1, - sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER), - OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER, - Checksum) - ); - - // - // RSDP ACPI 1.0 checksum for 2.0/3.0 table. This is only the first 20 bytes of the structure - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Rsdp3, - sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER), - OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER, - Checksum) - ); - - // - // RSDP ACPI 2.0/3.0 checksum, this is the entire table - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Rsdp3, - sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER), - OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER, - ExtendedChecksum) - ); - - // - // RSDT checksums - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Rsdt1, - AcpiSupportInstance->Rsdt1->Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - - AcpiPlatformChecksum ( - AcpiSupportInstance->Rsdt3, - AcpiSupportInstance->Rsdt3->Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - - // - // XSDT checksum - // - AcpiPlatformChecksum ( - AcpiSupportInstance->Xsdt, - AcpiSupportInstance->Xsdt->Length, - OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, - Checksum) - ); - - return EFI_SUCCESS; -} -/** - Constructor for the ACPI support protocol to initializes instance data. - - @param AcpiSupportInstance Instance to construct - - @retval EFI_SUCCESS Instance initialized. - @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. -**/ -EFI_STATUS -AcpiSupportAcpiSupportConstructor ( - IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance - ) -{ - EFI_STATUS Status; - UINT64 CurrentData; - UINTN TotalSize; - UINTN RsdpTableSize; - UINT8 *Pointer; - EFI_PHYSICAL_ADDRESS PageAddress; - - // - // Check for invalid input parameters - // - ASSERT (AcpiSupportInstance); - - InitializeListHead (&AcpiSupportInstance->TableList); - AcpiSupportInstance->CurrentHandle = 1; - AcpiSupportInstance->AcpiSupport.GetAcpiTable = GetAcpiTable; - AcpiSupportInstance->AcpiSupport.SetAcpiTable = SetAcpiTable; - AcpiSupportInstance->AcpiSupport.PublishTables = PublishTables; - - AcpiSupportInstance->AcpiTableProtocol.InstallAcpiTable = InstallAcpiTable; - AcpiSupportInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable; - - // - // Create RSDP table - // - RsdpTableSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) + - sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER); - - PageAddress = 0xFFFFFFFF; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIReclaimMemory, - EFI_SIZE_TO_PAGES (RsdpTableSize), - &PageAddress - ); - - if (EFI_ERROR (Status)) { - return EFI_OUT_OF_RESOURCES; - } - - Pointer = (UINT8 *) (UINTN) PageAddress; - ZeroMem (Pointer, RsdpTableSize); - - AcpiSupportInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer; - Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER); - AcpiSupportInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer; - - // - // Create RSDT, XSDT structures - // - TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT - mEfiAcpiMaxNumTables * sizeof (UINT32) + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT - mEfiAcpiMaxNumTables * sizeof (UINT32) + - sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT - mEfiAcpiMaxNumTables * sizeof (UINT64); - - // - // Allocate memory in the lower 32 bit of address range for - // compatibility with ACPI 1.0 OS. - // - // This is done because ACPI 1.0 pointers are 32 bit values. - // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses. - // There is no architectural reason these should be below 4GB, it is purely - // for convenience of implementation that we force memory below 4GB. - // - PageAddress = 0xFFFFFFFF; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIReclaimMemory, - EFI_SIZE_TO_PAGES (TotalSize), - &PageAddress - ); - - if (EFI_ERROR (Status)) { - gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiSupportInstance->Rsdp1, EFI_SIZE_TO_PAGES (RsdpTableSize)); - return EFI_OUT_OF_RESOURCES; - } - - Pointer = (UINT8 *) (UINTN) PageAddress; - ZeroMem (Pointer, TotalSize); - - AcpiSupportInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; - Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32)); - AcpiSupportInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; - Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32)); - AcpiSupportInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer; - - // - // Initialize RSDP - // - CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE; - CopyMem (&AcpiSupportInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64)); - CopyMem (AcpiSupportInstance->Rsdp1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdp1->OemId)); - AcpiSupportInstance->Rsdp1->Reserved = EFI_ACPI_RESERVED_BYTE; - AcpiSupportInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt1; - - CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE; - CopyMem (&AcpiSupportInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64)); - CopyMem (AcpiSupportInstance->Rsdp3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdp3->OemId)); - AcpiSupportInstance->Rsdp3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION; - AcpiSupportInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt3; - AcpiSupportInstance->Rsdp3->Length = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER); - CurrentData = (UINT64) (UINTN) AcpiSupportInstance->Xsdt; - CopyMem (&AcpiSupportInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64)); - SetMem (AcpiSupportInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE); - - // - // Initialize Rsdt - // - // Note that we "reserve" one entry for the FADT so it can always be - // at the beginning of the list of tables. Some OS don't seem - // to find it correctly if it is too far down the list. - // - AcpiSupportInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE; - AcpiSupportInstance->Rsdt1->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER); - AcpiSupportInstance->Rsdt1->Revision = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION; - CopyMem (AcpiSupportInstance->Rsdt1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdt1->OemId)); - CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId); - CopyMem (&AcpiSupportInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64)); - AcpiSupportInstance->Rsdt1->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); - AcpiSupportInstance->Rsdt1->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); - AcpiSupportInstance->Rsdt1->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); - // - // We always reserve first one for FADT - // - AcpiSupportInstance->NumberOfTableEntries1 = 1; - AcpiSupportInstance->Rsdt1->Length = AcpiSupportInstance->Rsdt1->Length + sizeof(UINT32); - - AcpiSupportInstance->Rsdt3->Signature = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE; - AcpiSupportInstance->Rsdt3->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER); - AcpiSupportInstance->Rsdt3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION; - CopyMem (AcpiSupportInstance->Rsdt3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdt3->OemId)); - CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId); - CopyMem (&AcpiSupportInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64)); - AcpiSupportInstance->Rsdt3->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); - AcpiSupportInstance->Rsdt3->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); - AcpiSupportInstance->Rsdt3->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); - // - // We always reserve first one for FADT - // - AcpiSupportInstance->NumberOfTableEntries3 = 1; - AcpiSupportInstance->Rsdt3->Length = AcpiSupportInstance->Rsdt3->Length + sizeof(UINT32); - - // - // Initialize Xsdt - // - AcpiSupportInstance->Xsdt->Signature = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE; - AcpiSupportInstance->Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER); - AcpiSupportInstance->Xsdt->Revision = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION; - CopyMem (AcpiSupportInstance->Xsdt->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Xsdt->OemId)); - CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId); - CopyMem (&AcpiSupportInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64)); - AcpiSupportInstance->Xsdt->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); - AcpiSupportInstance->Xsdt->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); - AcpiSupportInstance->Xsdt->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); - // - // We always reserve first one for FADT - // - AcpiSupportInstance->Xsdt->Length = AcpiSupportInstance->Xsdt->Length + sizeof(UINT64); - - ChecksumCommonTables (AcpiSupportInstance); - - // - // Completed successfully - // - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf b/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf deleted file mode 100644 index 32ca4f648f..0000000000 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf +++ /dev/null @@ -1,81 +0,0 @@ -## @file -# Acpi Support Dirver to install Framework Acpi Support Protocol. -# -# This driver initializes ACPI support protocol instance data structure and intstall -# ACPI support protocol to provide Get, Set and Publish Table services. -# -# 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 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 = AcpiSupportDxe - MODULE_UNI_FILE = AcpiSupportDxe.uni - FILE_GUID = 506533a6-e626-4500-b14f-17939c0e5b60 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - - ENTRY_POINT = InstallAcpiSupport - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - AcpiSupportAcpiSupportProtocol.c - AcpiSupport.h - AcpiSupport.c - - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - UefiBootServicesTableLib - MemoryAllocationLib - UefiDriverEntryPoint - BaseMemoryLib - UefiLib - DebugLib - BaseLib - PcdLib - - -[Guids] - gEfiAcpi10TableGuid ## PRODUCES ## SystemTable - gEfiAcpiTableGuid ## PRODUCES ## SystemTable - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdInstallAcpiSupportProtocol ## CONSUMES - -[Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES - -[Protocols] - gEfiAcpiTableProtocolGuid ## PRODUCES - gEfiAcpiSupportProtocolGuid ## SOMETIMES_PRODUCES - -[Depex] - TRUE - -[UserExtensions.TianoCore."ExtraFiles"] - AcpiSupportDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.uni b/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.uni deleted file mode 100644 index 7916f6b9a2..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni b/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni deleted file mode 100644 index 13539ce1be..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h deleted file mode 100644 index 93bafd2dd8..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h +++ /dev/null @@ -1,237 +0,0 @@ -/** @file - Head file for BDS Architectural Protocol implementation - -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 -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 _BDS_MODULE_H_ -#define _BDS_MODULE_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 -#include -#include - -#include -#include - -#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() - -/** - - Show progress bar with title above it. It only works in Graphics mode. - - @param TitleForeground Foreground color for Title. - @param TitleBackground Background color for Title. - @param Title Title above progress bar. - @param ProgressColor Progress bar color. - @param Progress Progress (0-100) - @param PreviousValue The previous value of the progress. - - @retval EFI_STATUS Success update the progress bar - -**/ -EFI_STATUS -PlatformBdsShowProgress ( - IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, - IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, - IN CHAR16 *Title, - IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, - IN UINTN Progress, - IN UINTN PreviousValue - ); - -// -// Prototypes -// - -/** - - Install Boot Device Selection Protocol - - @param ImageHandle The image handle. - @param SystemTable The system table. - - @retval EFI_SUCEESS BDS has finished initializing. - Return the dispatcher and recall BDS.Entry - @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface - -**/ -EFI_STATUS -EFIAPI -BdsInitialize ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); - -/** - - Service routine for BdsInstance->Entry(). Devices are connected, the - consoles are initialized, and the boot options are tried. - - @param This Protocol Instance structure. - -**/ -VOID -EFIAPI -BdsEntry ( - IN EFI_BDS_ARCH_PROTOCOL *This - ); - - -/** - Perform the memory test base on the memory test intensive level, - and update the memory resource. - - @param Level The memory test intensive level. - - @retval EFI_STATUS Success test all the system memory and update - the memory resource - -**/ -EFI_STATUS -EFIAPI -BdsMemoryTest ( - IN EXTENDMEM_COVERAGE_LEVEL Level - ); - -/** - - This routine is called to see if there are any capsules we need to process. - If the boot mode is not UPDATE, then we do nothing. Otherwise find the - capsule HOBS and produce firmware volumes for them via the DXE service. - Then call the dispatcher to dispatch drivers from them. Finally, check - the status of the updates. - - This function should be called by BDS in case we need to do some - sort of processing even if there is no capsule to process. We - need to do this if an earlier update went away and we need to - clear the capsule variable so on the next reset PEI does not see it and - think there is a capsule available. - - @param BootMode the current boot mode - - @retval EFI_INVALID_PARAMETER boot mode is not correct for an update - @retval EFI_SUCCESS There is no error when processing capsule - -**/ -EFI_STATUS -EFIAPI -BdsProcessCapsules ( - EFI_BOOT_MODE BootMode - ); - -/** - Set the variable and report the error through status code upon failure. - - @param VariableName A Null-terminated string that is the name of the vendor's variable. - Each VariableName is unique for each VendorGuid. VariableName must - contain 1 or more characters. If VariableName is an empty string, - then EFI_INVALID_PARAMETER is returned. - @param VendorGuid A unique identifier for the vendor. - @param Attributes Attributes bitmask to set for the variable. - @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero - causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is - set, then a SetVariable() call with a DataSize of zero will not cause any change to - the variable value (the timestamp associated with the variable may be updated however - even if no new data value is provided,see the description of the - EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not - be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). - @param Data The contents for the variable. - - @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as - defined by the Attributes. - @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the - DataSize exceeds the maximum allowed. - @retval EFI_INVALID_PARAMETER VariableName is an empty string. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. - @retval EFI_WRITE_PROTECTED The variable in question is read-only. - @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. - @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS - or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo - does NOT pass the validation check carried out by the firmware. - - @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. -**/ -EFI_STATUS -BdsDxeSetVariableAndReportStatusCodeOnError ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN UINT32 Attributes, - IN UINTN DataSize, - IN VOID *Data - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf deleted file mode 100644 index 6afb8a09df..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf +++ /dev/null @@ -1,228 +0,0 @@ -## @file -# BDSDxe module is core driver for BDS phase. -# -# When DxeCore dispatching all DXE driver, this module will produce architecture protocol -# gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry -# interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered. -# -# Generally, this module take reposiblity to connect all necessary devices for platform boot, -# these boot device path are hold in PlatformBdsLib library instance produced by platform. -# For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is select. -# For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI, -# EFI\BOOT\BOOTIA64.EFI file from selected boot device and transfer control to boot loader. -# -# BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, Device Manager" which -# is used for user to configure boot option or maintain hardware device. -# -# Copyright (c) 2008 - 2015, Intel 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 = BdsDxe - MODULE_UNI_FILE = BdsDxe.uni - FILE_GUID = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = BdsInitialize - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - FrontPage.h - Language.h - Bds.h - Hotkey.h - BootMaint/BBSsupport.h - BootMngr/BootManager.h - BootMaint/BootMaint.h - String.h - BootMaint/FormGuid.h - HwErrRecSupport.c - HwErrRecSupport.h - - DeviceMngr/DeviceManager.h - DeviceMngr/DeviceManagerVfr.h - DeviceMngr/DeviceManagerVfr.Vfr - DeviceMngr/DriverHealthVfr.Vfr - DeviceMngr/DeviceManagerStrings.uni - DeviceMngr/DeviceManager.c - BootMngr/BootManagerVfr.Vfr - BootMngr/BootManagerStrings.uni - BootMngr/BootManager.c - BootMaint/FE.vfr - BootMaint/FileExplorer.c - BootMaint/BootMaint.c - BootMaint/BBSsupport.c - BootMaint/UpdatePage.c - BootMaint/Variable.c - BootMaint/Data.c - BootMaint/ConsoleOption.c - BootMaint/BootOption.c - BootMaint/BmLib.c - BootMaint/Bm.vfr - BootMaint/Bmstring.uni - Hotkey.c - MemoryTest.c - Capsules.c - Strings.uni - String.c - Language.c - FrontPageVfr.Vfr - FrontPageStrings.uni - FrontPage.c - BdsEntry.c - - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - DevicePathLib - BaseLib - HobLib - UefiRuntimeServicesTableLib - GenericBdsLib - ReportStatusCodeLib - PerformanceLib - MemoryAllocationLib - UefiLib - UefiBootServicesTableLib - BaseMemoryLib - DebugLib - PrintLib - HiiLib - UefiDriverEntryPoint - PlatformBdsLib - CapsuleLib - PcdLib - UefiHiiServicesLib - -[Guids] - ## SOMETIMES_PRODUCES ## Variable:L"BootXXXX" # Boot option variable - ## SOMETIMES_PRODUCES ## Variable:L"DriverXXXX" # Driver load option. - ## SOMETIMES_PRODUCES ## Variable:L"PlatformLang" # Platform supported languange in Rfc4646 format - ## SOMETIMES_PRODUCES ## Variable:L"Lang" # Platform supported languange in Iso639 format - ## SOMETIMES_PRODUCES ## Variable:L"LangCodes" # Value of PcdUefiVariableDefaultLangCodes - ## PRODUCES ## Variable:L"PlatformLangCodes" # Value of PcdUefiVariableDefaultPlatformLangCodes - ## SOMETIMES_PRODUCES ## Variable:L"KeyXXXX" # Hotkey option variable - ## PRODUCES ## Variable:L"HwErrRecSupport" # The level of platform supported hardware Error Record Persistence - ## PRODUCES ## Variable:L"Timeout" # The time out value in second of showing progress bar - ## SOMETIMES_PRODUCES ## Variable:L"BootOptionSupport" # The feature supported in boot option menu, value could be: EFI_BOOT_OPTION_SUPPORT_KEY, EFI_BOOT_OPTION_SUPPORT_APP - ## SOMETIMES_PRODUCES ## Variable:L"BootOrder" # The boot option array - ## SOMETIMES_PRODUCES ## Variable:L"DriverOrder" # The driver order list - ## SOMETIMES_CONSUMES ## Variable:L"ConIn" # The device path of console in device - ## SOMETIMES_PRODUCES ## Variable:L"ConIn" # The device path of console in device - ## SOMETIMES_CONSUMES ## Variable:L"ConOut" # The device path of console out device - ## SOMETIMES_PRODUCES ## Variable:L"ConOut" # The device path of console out device - ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" # The device path of error out device - ## SOMETIMES_PRODUCES ## Variable:L"ErrOut" # The device path of error out device - ## SOMETIMES_CONSUMES ## Variable:L"ConInDev" # The device path of console in device - ## SOMETIMES_CONSUMES ## Variable:L"ConOutDev" # The device path of console out device - ## SOMETIMES_CONSUMES ## Variable:L"ErrOutDev" # The device path of error out device - ## SOMETIMES_PRODUCES ## Variable:L"BootNext" # The number of next boot option - gEfiGlobalVariableGuid - gEfiFileSystemVolumeLabelInfoIdGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the information type is volume - gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the information type is file - gEfiHiiPlatformSetupFormsetGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the formset class guid to be displayed - gEfiIfrTianoGuid ## SOMETIMES_PRODUCES ## UNDEFINED # Extended IFR Guid Opcode - gEfiHiiDriverHealthFormsetGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Indicate the Driver Health formset class guid to be displayed - ## SOMETIMES_PRODUCES ## Variable:L"LegacyDevOrder" - ## SOMETIMES_CONSUMES ## Variable:L"LegacyDevOrder" - gEfiLegacyDevOrderVariableGuid - gFrontPageFormSetGuid ## SOMETIMES_CONSUMES ## HII # FrontPage HII Package - gBootMaintFormSetGuid ## SOMETIMES_CONSUMES ## HII # BootMaint HII Package - gFileExploreFormSetGuid ## SOMETIMES_CONSUMES ## HII # FileExplore HII Package - gBootManagerFormSetGuid ## SOMETIMES_CONSUMES ## HII # BootManager HII Package - gDeviceManagerFormSetGuid ## SOMETIMES_CONSUMES ## HII # DeviceManager HII Package - gDriverHealthFormSetGuid ## SOMETIMES_CONSUMES ## HII # DriverHealth HII Package - ## SOMETIMES_PRODUCES ## Event - ## SOMETIMES_CONSUMES ## Event - gConnectConInEventGuid - gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID # FMP Capsule - gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID - gEfiUartDevicePathGuid ## SOMETIMES_CONSUMES ## GUID (Identify the device path for UARD device) - -[Protocols] - gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES - gEfiLoadFileProtocolGuid ## SOMETIMES_CONSUMES - gEfiBdsArchProtocolGuid ## PRODUCES - gEfiSmbiosProtocolGuid ## CONSUMES - gEfiGenericMemTestProtocolGuid ## SOMETIMES_CONSUMES - gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES - gEfiUgaDrawProtocolGuid |gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## SOMETIMES_CONSUMES - gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES - ## CONSUMES - ## NOTIFY - gEfiSimpleTextInputExProtocolGuid - gEfiHiiConfigAccessProtocolGuid ## SOMETIMES_PRODUCES - gEfiFormBrowser2ProtocolGuid ## CONSUMES - gEfiSerialIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiDevicePathProtocolGuid ## CONSUMES - gEfiDriverHealthProtocolGuid ## SOMETIMES_CONSUMES - gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES - gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES - gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES - -[FeaturePcd] - gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootlogoOnlyEnable ## CONSUMES - -[Pcd] - gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes ## SOMETIMES_CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang ## SOMETIMES_CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes ## CONSUMES - gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang ## SOMETIMES_CONSUMES - ## CONSUMES - ## PRODUCES - gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel - gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow ## PRODUCES - gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn ## PRODUCES - ## SOMETIMES_CONSUMES - ## SOMETIMES_PRODUCES - gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut - ## CONSUMES - ## PRODUCES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState - gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## PRODUCES - gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## PRODUCES - gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand ## SOMETIMES_CONSUMES - ## CONSUMES - ## SOMETIMES_PRODUCES - gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn - ## CONSUMES - ## SOMETIMES_PRODUCES - gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow - gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## CONSUMES - -[Depex] - TRUE - -# -# [BootMode] -# FLASH_UPDATE ## SOMETIMES_CONSUMES # Update Capsule Image -# - -[UserExtensions.TianoCore."ExtraFiles"] - BdsDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.uni deleted file mode 100644 index a120733895..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxeExtra.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxeExtra.uni deleted file mode 100644 index 9aee074abe..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c deleted file mode 100644 index ae7ad2153c..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c +++ /dev/null @@ -1,754 +0,0 @@ -/** @file - This module produce main entry for BDS phase - BdsEntry. - When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed - which contains interface of BdsEntry. - After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked - to enter BDS phase. - -Copyright (c) 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 -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 "Bds.h" -#include "Language.h" -#include "FrontPage.h" -#include "Hotkey.h" -#include "HwErrRecSupport.h" - -/// -/// BDS arch protocol instance initial value. -/// -/// Note: Current BDS not directly get the BootMode, DefaultBoot, -/// TimeoutDefault, MemoryTestLevel value from the BDS arch protocol. -/// Please refer to the library useage of BdsLibGetBootMode, BdsLibGetTimeout -/// and PlatformBdsDiagnostics in BdsPlatform.c -/// -EFI_HANDLE gBdsHandle = NULL; - -EFI_BDS_ARCH_PROTOCOL gBds = { - BdsEntry -}; - -UINT16 *mBootNext = NULL; - -/// -/// The read-only variables defined in UEFI Spec. -/// -CHAR16 *mReadOnlyVariables[] = { - L"PlatformLangCodes", - L"LangCodes", - L"BootOptionSupport", - L"HwErrRecSupport", - L"OsIndicationsSupported" - }; - -/** - - Install Boot Device Selection Protocol - - @param ImageHandle The image handle. - @param SystemTable The system table. - - @retval EFI_SUCEESS BDS has finished initializing. - Return the dispatcher and recall BDS.Entry - @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface - -**/ -EFI_STATUS -EFIAPI -BdsInitialize ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install protocol interface - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &gBdsHandle, - &gEfiBdsArchProtocolGuid, &gBds, - NULL - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} - - -/** - 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 -BdsEmptyCallbackFunction ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ -} - -/** - - This function attempts to boot for the boot order specified - by platform policy. - -**/ -VOID -BdsBootDeviceSelect ( - VOID - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - BDS_COMMON_OPTION *BootOption; - UINTN ExitDataSize; - CHAR16 *ExitData; - UINT16 Timeout; - LIST_ENTRY BootLists; - CHAR16 Buffer[20]; - BOOLEAN BootNextExist; - LIST_ENTRY *LinkBootNext; - EFI_EVENT ConnectConInEvent; - - // - // Got the latest boot option - // - BootNextExist = FALSE; - LinkBootNext = NULL; - ConnectConInEvent = NULL; - InitializeListHead (&BootLists); - - // - // First check the boot next option - // - ZeroMem (Buffer, sizeof (Buffer)); - - // - // Create Event to signal ConIn connection request - // - if (PcdGetBool (PcdConInConnectOnDemand)) { - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - BdsEmptyCallbackFunction, - NULL, - &gConnectConInEventGuid, - &ConnectConInEvent - ); - if (EFI_ERROR(Status)) { - ConnectConInEvent = NULL; - } - } - - if (mBootNext != NULL) { - // - // Indicate we have the boot next variable, so this time - // boot will always have this boot option - // - BootNextExist = TRUE; - - // - // Clear the this variable so it's only exist in this time boot - // - Status = gRT->SetVariable ( - L"BootNext", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - 0, - NULL - ); - // - // Deleting variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - // - // Add the boot next boot option - // - UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext); - BootOption = BdsLibVariableToOption (&BootLists, Buffer); - - // - // If fail to get boot option from variable, just return and do nothing. - // - if (BootOption == NULL) { - return; - } - - BootOption->BootCurrent = *mBootNext; - } - // - // Parse the boot order to get boot option - // - BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); - - // - // When we didn't have chance to build boot option variables in the first - // full configuration boot (e.g.: Reset in the first page or in Device Manager), - // we have no boot options in the following mini configuration boot. - // Give the last chance to enumerate the boot options. - // - if (IsListEmpty (&BootLists)) { - BdsLibEnumerateAllBootOption (&BootLists); - } - - Link = BootLists.ForwardLink; - - // - // Parameter check, make sure the loop will be valid - // - if (Link == NULL) { - return ; - } - // - // Here we make the boot in a loop, every boot success will - // return to the front page - // - for (;;) { - // - // Check the boot option list first - // - if (Link == &BootLists) { - // - // When LazyConIn enabled, signal connect ConIn event before enter UI - // - if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) { - gBS->SignalEvent (ConnectConInEvent); - } - - // - // There are two ways to enter here: - // 1. There is no active boot option, give user chance to - // add new boot option - // 2. All the active boot option processed, and there is no - // one is success to boot, then we back here to allow user - // add new active boot option - // - Timeout = 0xffff; - PlatformBdsEnterFrontPage (Timeout, FALSE); - InitializeListHead (&BootLists); - BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); - Link = BootLists.ForwardLink; - continue; - } - // - // Get the boot option from the link list - // - BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); - - // - // According to EFI Specification, if a load option is not marked - // as LOAD_OPTION_ACTIVE, the boot manager will not automatically - // load the option. - // - if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { - // - // skip the header of the link list, because it has no boot option - // - Link = Link->ForwardLink; - continue; - } - // - // Make sure the boot option device path connected, - // but ignore the BBS device path - // - if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { - // - // Notes: the internal shell can not been connected with device path - // so we do not check the status here - // - BdsLibConnectDevicePath (BootOption->DevicePath); - } - - // - // Restore to original mode before launching boot option. - // - BdsSetConsoleMode (FALSE); - - // - // All the driver options should have been processed since - // now boot will be performed. - // - Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); - if (Status != EFI_SUCCESS) { - // - // Call platform action to indicate the boot fail - // - BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); - PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize); - - // - // Check the next boot option - // - Link = Link->ForwardLink; - - } else { - // - // Call platform action to indicate the boot success - // - BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); - PlatformBdsBootSuccess (BootOption); - - // - // Boot success, then stop process the boot order, and - // present the boot manager menu, front page - // - - // - // When LazyConIn enabled, signal connect ConIn Event before enter UI - // - if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) { - gBS->SignalEvent (ConnectConInEvent); - } - - Timeout = 0xffff; - PlatformBdsEnterFrontPage (Timeout, FALSE); - - // - // Rescan the boot option list, avoid potential risk of the boot - // option change in front page - // - if (BootNextExist) { - LinkBootNext = BootLists.ForwardLink; - } - - InitializeListHead (&BootLists); - if (LinkBootNext != NULL) { - // - // Reserve the boot next option - // - InsertTailList (&BootLists, LinkBootNext); - } - - BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); - Link = BootLists.ForwardLink; - } - } - -} - -/** - - Validate input console variable data. - - If found the device path is not a valid device path, remove the variable. - - @param VariableName Input console variable name. - -**/ -VOID -BdsFormalizeConsoleVariable ( - IN CHAR16 *VariableName - ) -{ - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - UINTN VariableSize; - EFI_STATUS Status; - - DevicePath = BdsLibGetVariableAndSize ( - VariableName, - &gEfiGlobalVariableGuid, - &VariableSize - ); - if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) { - Status = gRT->SetVariable ( - VariableName, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - 0, - NULL - ); - // - // Deleting variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } -} - -/** - - Formalize Bds global variables. - - 1. For ConIn/ConOut/ConErr, if found the device path is not a valid device path, remove the variable. - 2. For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps - 3. Delete OsIndications variable if it is not NV/BS/RT UINT64 - Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable. - -**/ -VOID -BdsFormalizeEfiGlobalVariable ( - VOID - ) -{ - EFI_STATUS Status; - UINT64 OsIndicationSupport; - UINT64 OsIndication; - UINTN DataSize; - UINT32 Attributes; - - // - // Validate Console variable. - // - BdsFormalizeConsoleVariable (L"ConIn"); - BdsFormalizeConsoleVariable (L"ConOut"); - BdsFormalizeConsoleVariable (L"ErrOut"); - - // - // OS indicater support variable - // - OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI \ - | EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED; - - BdsDxeSetVariableAndReportStatusCodeOnError ( - L"OsIndicationsSupported", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - sizeof(UINT64), - &OsIndicationSupport - ); - - // - // If OsIndications is invalid, remove it. - // Invalid case - // 1. Data size != UINT64 - // 2. OsIndication value inconsistence - // 3. OsIndication attribute inconsistence - // - OsIndication = 0; - Attributes = 0; - DataSize = sizeof(UINT64); - Status = gRT->GetVariable ( - L"OsIndications", - &gEfiGlobalVariableGuid, - &Attributes, - &DataSize, - &OsIndication - ); - - if (!EFI_ERROR(Status)) { - if (DataSize != sizeof(UINT64) || - (OsIndication & ~OsIndicationSupport) != 0 || - Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE)){ - - DEBUG ((EFI_D_ERROR, "Unformalized OsIndications variable exists. Delete it\n")); - Status = gRT->SetVariable ( - L"OsIndications", - &gEfiGlobalVariableGuid, - 0, - 0, - NULL - ); - // - // Deleting variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } - } - -} - -/** - - Allocate a block of memory that will contain performance data to OS. - -**/ -VOID -BdsAllocateMemoryForPerformanceData ( - VOID - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase; - EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; - - AcpiLowMemoryBase = 0x0FFFFFFFFULL; - - // - // Allocate a block of memory that will contain performance data to OS. - // - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiReservedMemoryType, - EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH), - &AcpiLowMemoryBase - ); - if (!EFI_ERROR (Status)) { - // - // Save the pointer to variable for use in S3 resume. - // - BdsDxeSetVariableAndReportStatusCodeOnError ( - L"PerfDataMemAddr", - &gPerformanceProtocolGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - sizeof (EFI_PHYSICAL_ADDRESS), - &AcpiLowMemoryBase - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase)); - } - // - // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists - // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code. - // - Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); - if (!EFI_ERROR (Status)) { - Status = VariableLock->RequestToLock (VariableLock, L"PerfDataMemAddr", &gPerformanceProtocolGuid); - ASSERT_EFI_ERROR (Status); - } - } -} - -/** - - Service routine for BdsInstance->Entry(). Devices are connected, the - consoles are initialized, and the boot options are tried. - - @param This Protocol Instance structure. - -**/ -VOID -EFIAPI -BdsEntry ( - IN EFI_BDS_ARCH_PROTOCOL *This - ) -{ - LIST_ENTRY DriverOptionList; - LIST_ENTRY BootOptionList; - UINTN BootNextSize; - CHAR16 *FirmwareVendor; - EFI_STATUS Status; - UINT16 BootTimeOut; - UINTN Index; - EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; - - // - // Insert the performance probe - // - PERF_END (NULL, "DXE", NULL, 0); - PERF_START (NULL, "BDS", NULL, 0); - - PERF_CODE ( - BdsAllocateMemoryForPerformanceData (); - ); - - // - // Initialize the global system boot option and driver option - // - InitializeListHead (&DriverOptionList); - InitializeListHead (&BootOptionList); - - // - // Initialize hotkey service - // - InitializeHotkeyService (); - - // - // Fill in FirmwareVendor and FirmwareRevision from PCDs - // - FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor); - gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor); - ASSERT (gST->FirmwareVendor != NULL); - gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision); - - // - // Fixup Tasble CRC after we updated Firmware Vendor and Revision - // - gST->Hdr.CRC32 = 0; - gBS->CalculateCrc32 ((VOID *)gST, sizeof(EFI_SYSTEM_TABLE), &gST->Hdr.CRC32); - - // - // Validate Variable. - // - BdsFormalizeEfiGlobalVariable(); - - // - // Mark the read-only variables if the Variable Lock protocol exists - // - Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); - DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status)); - if (!EFI_ERROR (Status)) { - for (Index = 0; Index < sizeof (mReadOnlyVariables) / sizeof (mReadOnlyVariables[0]); Index++) { - Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid); - ASSERT_EFI_ERROR (Status); - } - } - - // - // Report Status Code to indicate connecting drivers will happen - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS) - ); - - InitializeHwErrRecSupport(); - - // - // Initialize L"Timeout" EFI global variable. - // - BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); - if (BootTimeOut != 0xFFFF) { - // - // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification - // define same behavior between no value or 0xFFFF value for L"Timeout". - // - BdsDxeSetVariableAndReportStatusCodeOnError ( - L"Timeout", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - sizeof (UINT16), - &BootTimeOut - ); - } - - // - // bugbug: platform specific code - // Initialize the platform specific string and language - // - InitializeStringSupport (); - InitializeLanguage (TRUE); - InitializeFrontPage (TRUE); - - // - // Do the platform init, can be customized by OEM/IBV - // - PERF_START (NULL, "PlatformBds", "BDS", 0); - PlatformBdsInit (); - - // - // Set up the device list based on EFI 1.1 variables - // process Driver#### and Load the driver's in the - // driver option list - // - BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder"); - if (!IsListEmpty (&DriverOptionList)) { - BdsLibLoadDrivers (&DriverOptionList); - } - // - // Check if we have the boot next option - // - mBootNext = BdsLibGetVariableAndSize ( - L"BootNext", - &gEfiGlobalVariableGuid, - &BootNextSize - ); - - // - // Setup some platform policy here - // - PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList, BdsProcessCapsules, BdsMemoryTest); - PERF_END (NULL, "PlatformBds", "BDS", 0); - - // - // BDS select the boot device to load OS - // - BdsBootDeviceSelect (); - - // - // Only assert here since this is the right behavior, we should never - // return back to DxeCore. - // - ASSERT (FALSE); - - return ; -} - - -/** - Set the variable and report the error through status code upon failure. - - @param VariableName A Null-terminated string that is the name of the vendor's variable. - Each VariableName is unique for each VendorGuid. VariableName must - contain 1 or more characters. If VariableName is an empty string, - then EFI_INVALID_PARAMETER is returned. - @param VendorGuid A unique identifier for the vendor. - @param Attributes Attributes bitmask to set for the variable. - @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero - causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is - set, then a SetVariable() call with a DataSize of zero will not cause any change to - the variable value (the timestamp associated with the variable may be updated however - even if no new data value is provided,see the description of the - EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not - be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). - @param Data The contents for the variable. - - @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as - defined by the Attributes. - @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the - DataSize exceeds the maximum allowed. - @retval EFI_INVALID_PARAMETER VariableName is an empty string. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. - @retval EFI_WRITE_PROTECTED The variable in question is read-only. - @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. - @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS - or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo - does NOT pass the validation check carried out by the firmware. - - @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. -**/ -EFI_STATUS -BdsDxeSetVariableAndReportStatusCodeOnError ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN UINT32 Attributes, - IN UINTN DataSize, - IN VOID *Data - ) -{ - EFI_STATUS Status; - EDKII_SET_VARIABLE_STATUS *SetVariableStatus; - UINTN NameSize; - - Status = gRT->SetVariable ( - VariableName, - VendorGuid, - Attributes, - DataSize, - Data - ); - if (EFI_ERROR (Status)) { - NameSize = StrSize (VariableName); - SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize); - if (SetVariableStatus != NULL) { - CopyGuid (&SetVariableStatus->Guid, VendorGuid); - SetVariableStatus->NameSize = NameSize; - SetVariableStatus->DataSize = DataSize; - SetVariableStatus->SetStatus = Status; - SetVariableStatus->Attributes = Attributes; - CopyMem (SetVariableStatus + 1, VariableName, NameSize); - CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data, DataSize); - - REPORT_STATUS_CODE_EX ( - EFI_ERROR_CODE, - PcdGet32 (PcdErrorCodeSetVariable), - 0, - NULL, - &gEdkiiStatusCodeDataTypeVariableGuid, - SetVariableStatus, - sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize - ); - - FreePool (SetVariableStatus); - } - } - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c deleted file mode 100644 index 6a0b525f15..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c +++ /dev/null @@ -1,254 +0,0 @@ -/** @file - This function deal with the legacy boot option, it create, delete - and manage the legacy boot option, all legacy boot option is getting from - the legacy BBS table. - -Copyright (c) 2004 - 2015, Intel 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 "BBSsupport.h" - -#pragma pack(1) -typedef struct { - BBS_TABLE BbsEntry; - UINT16 BbsIndex; -} LEGACY_BOOT_OPTION_BBS_DATA; -#pragma pack() - -/** - Re-order the Boot Option according to the DevOrder. - - The routine re-orders the Boot Option in BootOption array according to - the order specified by DevOrder. - - @param DevOrder Pointer to buffer containing the BBS Index, - high 8-bit value 0xFF indicating a disabled boot option - @param DevOrderCount Count of the BBS Index - @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers - @param EnBootOptionCount Count of the enabled Boot Option Numbers - @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers - @param DisBootOptionCount Count of the disabled Boot Option Numbers -**/ -VOID -OrderLegacyBootOption4SameType ( - UINT16 *DevOrder, - UINTN DevOrderCount, - UINT16 **EnBootOption, - UINTN *EnBootOptionCount, - UINT16 **DisBootOption, - UINTN *DisBootOptionCount - ) -{ - EFI_STATUS Status; - UINT16 *NewBootOption; - UINT16 *BootOrder; - UINTN BootOrderSize; - UINTN Index; - UINTN StartPosition; - - BDS_COMMON_OPTION *BootOption; - - CHAR16 OptionName[sizeof ("Boot####")]; - UINT16 *BbsIndexArray; - UINT16 *DeviceTypeArray; - LIST_ENTRY List; - - BootOrder = BdsLibGetVariableAndSize ( - L"BootOrder", - &gEfiGlobalVariableGuid, - &BootOrderSize - ); - ASSERT (BootOrder != NULL); - - BbsIndexArray = AllocatePool (BootOrderSize); - DeviceTypeArray = AllocatePool (BootOrderSize); - *EnBootOption = AllocatePool (BootOrderSize); - *DisBootOption = AllocatePool (BootOrderSize); - *DisBootOptionCount = 0; - *EnBootOptionCount = 0; - Index = 0; - - ASSERT (BbsIndexArray != NULL); - ASSERT (DeviceTypeArray != NULL); - ASSERT (*EnBootOption != NULL); - ASSERT (*DisBootOption != NULL); - - for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { - - UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); - InitializeListHead (&List); - BootOption = BdsLibVariableToOption (&List, OptionName); - ASSERT (BootOption != NULL); - - if ((DevicePathType (BootOption->DevicePath) == BBS_DEVICE_PATH) && - (DevicePathSubType (BootOption->DevicePath) == BBS_BBS_DP)) { - // - // Legacy Boot Option - // - ASSERT (BootOption->LoadOptionsSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); - - DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType; - BbsIndexArray [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption->LoadOptions)->BbsIndex; - } else { - DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN; - BbsIndexArray [Index] = 0xFFFF; - } - FreePool (BootOption->DevicePath); - FreePool (BootOption->Description); - FreePool (BootOption->LoadOptions); - FreePool (BootOption); - } - - // - // Record the corresponding Boot Option Numbers according to the DevOrder - // Record the EnBootOption and DisBootOption according to the DevOrder - // - StartPosition = BootOrderSize / sizeof (UINT16); - NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16)); - ASSERT (NewBootOption != NULL); - while (DevOrderCount-- != 0) { - for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { - if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) { - StartPosition = MIN (StartPosition, Index); - NewBootOption[DevOrderCount] = BootOrder[Index]; - - if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) { - (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index]; - (*DisBootOptionCount)++; - } else { - (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index]; - (*EnBootOptionCount)++; - } - break; - } - } - } - - // - // Overwrite the old BootOption - // - CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16)); - Status = gRT->SetVariable ( - L"BootOrder", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - BootOrderSize, - BootOrder - ); - // - // Changing content without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - FreePool (NewBootOption); - FreePool (DeviceTypeArray); - FreePool (BbsIndexArray); - FreePool (BootOrder); -} - -/** - Group the legacy boot options in the BootOption. - - The routine assumes the boot options in the beginning that covers all the device - types are ordered properly and re-position the following boot options just after - the corresponding boot options with the same device type. - For example: - 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0] - Assuming [Harddisk1 CdRom2 Efi1] is ordered properly - Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0] - - 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2] - Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly - Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2] - -**/ -VOID -GroupMultipleLegacyBootOption4SameType ( - VOID - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN DeviceIndex; - UINTN DeviceTypeIndex[7]; - UINTN *NextIndex; - UINT16 OptionNumber; - UINT16 *BootOrder; - UINTN BootOrderSize; - CHAR16 OptionName[sizeof ("Boot####")]; - BDS_COMMON_OPTION *BootOption; - LIST_ENTRY List; - - SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xff); - - BootOrder = BdsLibGetVariableAndSize ( - L"BootOrder", - &gEfiGlobalVariableGuid, - &BootOrderSize - ); - - for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { - UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); - InitializeListHead (&List); - BootOption = BdsLibVariableToOption (&List, OptionName); - ASSERT (BootOption != NULL); - - if ((DevicePathType (BootOption->DevicePath) == BBS_DEVICE_PATH) && - (DevicePathSubType (BootOption->DevicePath) == BBS_BBS_DP)) { - // - // Legacy Boot Option - // - ASSERT ((((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType & 0xF) < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0])); - NextIndex = &DeviceTypeIndex[((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType & 0xF]; - - if (*NextIndex == (UINTN) -1) { - // - // *NextIndex is the Index in BootOrder to put the next Option Number for the same type - // - *NextIndex = Index + 1; - } else { - // - // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position - // - OptionNumber = BootOrder[Index]; - CopyMem (&BootOrder[*NextIndex + 1], &BootOrder[*NextIndex], (Index - *NextIndex) * sizeof (UINT16)); - BootOrder[*NextIndex] = OptionNumber; - - // - // Update the DeviceTypeIndex array to reflect the right shift operation - // - for (DeviceIndex = 0; DeviceIndex < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]); DeviceIndex++) { - if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) { - DeviceTypeIndex[DeviceIndex]++; - } - } - } - } - FreePool (BootOption->DevicePath); - FreePool (BootOption->Description); - FreePool (BootOption->LoadOptions); - FreePool (BootOption); - } - - Status = gRT->SetVariable ( - L"BootOrder", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - BootOrderSize, - BootOrder - ); - // - // Changing content without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - FreePool (BootOrder); -} - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h deleted file mode 100644 index e73dc85995..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h +++ /dev/null @@ -1,82 +0,0 @@ -/** @file - declares interface functions - -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. - -**/ - -#ifndef _EFI_BDS_BBS_SUPPORT_H_ -#define _EFI_BDS_BBS_SUPPORT_H_ - -#include "BootMaint.h" - -/** - Build Legacy Device Name String according. - - @param CurBBSEntry BBS Table. - @param Index Index. - @param BufSize The buffer size. - @param BootString The output string. - - @return VOID No output. - -**/ -VOID -BdsBuildLegacyDevNameString ( - IN BBS_TABLE *CurBBSEntry, - IN UINTN Index, - IN UINTN BufSize, - OUT CHAR16 *BootString - ); - -/** - Group the legacy boot options in the BootOption. - - The routine assumes the boot options in the beginning that covers all the device - types are ordered properly and re-position the following boot options just after - the corresponding boot options with the same device type. - For example: - 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0] - Assuming [Harddisk1 CdRom2 Efi1] is ordered properly - Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0] - - 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2] - Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly - Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2] -**/ -VOID -GroupMultipleLegacyBootOption4SameType ( - VOID - ); - -/** - Re-order the Boot Option according to the DevOrder. - - The routine re-orders the Boot Option in BootOption array according to - the order specified by DevOrder. - - @param DevOrder Pointer to buffer containing the BBS Index, - high 8-bit value 0xFF indicating a disabled boot option - @param DevOrderCount Count of the BBS Index - @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers - @param EnBootOptionCount Count of the enabled Boot Option Numbers - @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers - @param DisBootOptionCount Count of the disabled Boot Option Numbers -**/ -VOID -OrderLegacyBootOption4SameType ( - UINT16 *DevOrder, - UINTN DevOrderCount, - UINT16 **EnBootOption, - UINTN *EnBootOptionCount, - UINT16 **DisBootOption, - UINTN *DisBootOptionCount - ); -#endif diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr deleted file mode 100644 index 0d35c2c37e..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr +++ /dev/null @@ -1,365 +0,0 @@ -///** @file -// -// Boot Maintenance Utility Formset -// -// Copyright (c) 2004 - 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 "FormGuid.h" - -formset - guid = BOOT_MAINT_FORMSET_GUID, - title = STRING_TOKEN(STR_FORM_MAIN_TITLE), - help = STRING_TOKEN(STR_NULL_STRING), - classguid = BOOT_MAINT_FORMSET_GUID, - - varstore BMM_FAKE_NV_DATA, - varid = VARSTORE_ID_BOOT_MAINT, - name = BmmData, - guid = BOOT_MAINT_FORMSET_GUID; - - form formid = FORM_MAIN_ID, - title = STRING_TOKEN(STR_FORM_MAIN_TITLE); - - goto FORM_BOOT_SETUP_ID, - prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE), - help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP), - flags = INTERACTIVE, - key = FORM_BOOT_SETUP_ID; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - goto FORM_DRIVER_SETUP_ID, - prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE), - help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP), - flags = INTERACTIVE, - key = FORM_DRIVER_SETUP_ID; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - goto FORM_CON_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE), - help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP), - flags = INTERACTIVE, - key = FORM_CON_MAIN_ID; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - goto FORM_BOOT_FROM_FILE_ID, - prompt = STRING_TOKEN(STR_BOOT_FROM_FILE), - help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP), - flags = INTERACTIVE, - key = KEY_VALUE_BOOT_FROM_FILE; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - -// label FORM_MAIN_ID; - - goto FORM_BOOT_NEXT_ID, - prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE), - help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP), - flags = INTERACTIVE, - key = FORM_BOOT_NEXT_ID; - - goto FORM_TIME_OUT_ID, - prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE), - help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP), - flags = INTERACTIVE, - key = FORM_TIME_OUT_ID; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - text - help = STRING_TOKEN(STR_RESET), - text = STRING_TOKEN(STR_RESET), - flags = INTERACTIVE, - key = FORM_RESET; - - endform; - - form formid = FORM_BOOT_SETUP_ID, - title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE); - - goto FORM_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), - help = STRING_TOKEN(STR_FORM_GOTO_MAIN); - //flags = INTERACTIVE, - //key = FORM_MAIN_ID; - - goto FORM_BOOT_ADD_ID, - prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE), - help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP), - flags = INTERACTIVE, - key = FORM_BOOT_ADD_ID; - - goto FORM_BOOT_DEL_ID, - prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE), - help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP), - flags = INTERACTIVE, - key = FORM_BOOT_DEL_ID; - - goto FORM_BOOT_CHG_ID, - prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), - help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP), - flags = INTERACTIVE, - key = FORM_BOOT_CHG_ID; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - // - // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive" - // here dynamically - // - label FORM_BOOT_LEGACY_DEVICE_ID; - label LABEL_END; - - endform; - - form formid = FORM_DRIVER_SETUP_ID, - title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE); - - goto FORM_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), - help = STRING_TOKEN(STR_FORM_GOTO_MAIN); - //help = STRING_TOKEN(STR_FORM_GOTO_MAIN), - //flags = INTERACTIVE, - //key = FORM_MAIN_ID; - - goto FORM_DRV_ADD_ID, - prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE), - help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP), - flags = INTERACTIVE, - key = FORM_DRV_ADD_ID; - - goto FORM_DRV_DEL_ID, - prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE), - help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_DRV_DEL_ID; - - goto FORM_DRV_CHG_ID, - prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), - help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_DRV_CHG_ID; - endform; - - form formid = FORM_BOOT_DEL_ID, - title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE); - - label FORM_BOOT_DEL_ID; - label LABEL_END; - endform; - - form formid = FORM_BOOT_CHG_ID, - title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE); - - label FORM_BOOT_CHG_ID; - label LABEL_END; - - endform; - - form formid = FORM_BOOT_NEXT_ID, - title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE); - - label FORM_BOOT_NEXT_ID; - label LABEL_END; - endform; - - form formid = FORM_TIME_OUT_ID, - title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE); - - label FORM_TIME_OUT_ID; - label LABEL_END; - endform; - - form formid = FORM_DRV_ADD_ID, - title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE); - - goto FORM_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), - help = STRING_TOKEN(STR_FORM_GOTO_MAIN); - //flags = INTERACTIVE, - //key = FORM_MAIN_ID; - - goto FORM_DRV_ADD_FILE_ID, - prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), - help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), - flags = INTERACTIVE, - key = FORM_DRV_ADD_FILE_ID; - - endform; - - form formid = FORM_DRV_DEL_ID, - title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE); - - label FORM_DRV_DEL_ID; - label LABEL_END; - - endform; - - form formid = FORM_DRV_CHG_ID, - title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE); - - label FORM_DRV_CHG_ID; - label LABEL_END; - - endform; - - form formid = FORM_CON_MAIN_ID, - title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE); - - goto FORM_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), - help = STRING_TOKEN(STR_FORM_GOTO_MAIN); - //flags = INTERACTIVE, - //key = FORM_MAIN_ID; - - goto FORM_CON_IN_ID, - prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE), - help = STRING_TOKEN(STR_FORM_CON_IN_HELP), - flags = INTERACTIVE, - key = FORM_CON_IN_ID; - - goto FORM_CON_OUT_ID, - prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE), - help = STRING_TOKEN(STR_FORM_CON_OUT_HELP), - flags = INTERACTIVE, - key = FORM_CON_OUT_ID; - - goto FORM_CON_ERR_ID, - prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE), - help = STRING_TOKEN(STR_FORM_STD_ERR_HELP), - flags = INTERACTIVE, - key = FORM_CON_ERR_ID; - - goto FORM_CON_MODE_ID, - prompt = STRING_TOKEN(STR_FORM_MODE_TITLE), - help = STRING_TOKEN(STR_FORM_MODE_HELP), - flags = INTERACTIVE, - key = FORM_CON_MODE_ID; - - goto FORM_CON_COM_ID, - prompt = STRING_TOKEN(STR_FORM_COM_TITLE), - help = STRING_TOKEN(STR_FORM_COM_HELP), - flags = INTERACTIVE, - key = FORM_CON_COM_ID; - endform; - - form formid = FORM_CON_MODE_ID, - title = STRING_TOKEN(STR_FORM_MODE_TITLE); - - label FORM_CON_MODE_ID; - label LABEL_END; - endform; - - form formid = FORM_CON_COM_ID, - title = STRING_TOKEN(STR_FORM_COM_TITLE); - - label FORM_CON_COM_ID; - label LABEL_END; - endform; - - form formid = FORM_CON_COM_SETUP_ID, - title = STRING_TOKEN(STR_CON_COM_SETUP); - - label FORM_CON_COM_SETUP_ID; - label LABEL_END; - endform; - - form formid = FORM_FILE_SEEK_ID, - title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); - - label FORM_FILE_SEEK_ID; - label LABEL_END; - endform; - - form formid = FORM_FILE_NEW_SEEK_ID, - title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); - - label FORM_FILE_NEW_SEEK_ID; - label LABEL_END; - endform; - - form formid = FORM_DRV_ADD_HANDLE_ID, - title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE); - - label FORM_DRV_ADD_HANDLE_ID; - label LABEL_END; - endform; - - form formid = FORM_DRV_ADD_HANDLE_DESC_ID, - title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); - - label FORM_DRV_ADD_HANDLE_DESC_ID; - label LABEL_END; - - endform; - - form formid = FORM_CON_IN_ID, - title = STRING_TOKEN(STR_FORM_CON_IN_TITLE); - - label FORM_CON_IN_ID; - label LABEL_END; - - endform; - - form formid = FORM_CON_OUT_ID, - title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE); - - label FORM_CON_OUT_ID; - label LABEL_END; - - endform; - - form formid = FORM_CON_ERR_ID, - title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE); - - label FORM_CON_ERR_ID; - label LABEL_END; - - endform; - - form formid = FORM_SET_FD_ORDER_ID, - title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE); - - label FORM_SET_FD_ORDER_ID; - label LABEL_END; - endform; - - form formid = FORM_SET_HD_ORDER_ID, - title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE); - - label FORM_SET_HD_ORDER_ID; - label LABEL_END; - endform; - - form formid = FORM_SET_CD_ORDER_ID, - title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE); - - label FORM_SET_CD_ORDER_ID; - label LABEL_END; - endform; - - form formid = FORM_SET_NET_ORDER_ID, - title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE); - - label FORM_SET_NET_ORDER_ID; - label LABEL_END; - endform; - - form formid = FORM_SET_BEV_ORDER_ID, - title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE); - - label FORM_SET_BEV_ORDER_ID; - label LABEL_END; - endform; - -endformset; diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c deleted file mode 100644 index 4424831859..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c +++ /dev/null @@ -1,411 +0,0 @@ -/** @file - Utility routines used by boot maintenance modules. - -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 -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 "BootMaint.h" - -/** - - Function opens and returns a file handle to the root directory of a volume. - - @param DeviceHandle A handle for a device - - @return A valid file handle or NULL is returned - -**/ -EFI_FILE_HANDLE -EfiLibOpenRoot ( - IN EFI_HANDLE DeviceHandle - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; - EFI_FILE_HANDLE File; - - File = NULL; - - // - // File the file system interface to the device - // - Status = gBS->HandleProtocol ( - DeviceHandle, - &gEfiSimpleFileSystemProtocolGuid, - (VOID *) &Volume - ); - - // - // Open the root directory of the volume - // - if (!EFI_ERROR (Status)) { - Status = Volume->OpenVolume ( - Volume, - &File - ); - } - // - // Done - // - return EFI_ERROR (Status) ? NULL : File; -} - -/** - - Helper function called as part of the code needed - to allocate the proper sized buffer for various - EFI interfaces. - - - @param Status Current status - @param Buffer Current allocated buffer, or NULL - @param BufferSize Current buffer size needed - - @retval TRUE if the buffer was reallocated and the caller - should try the API again. - @retval FALSE The caller should not call this function again. - -**/ -BOOLEAN -EfiGrowBuffer ( - IN OUT EFI_STATUS *Status, - IN OUT VOID **Buffer, - IN UINTN BufferSize - ) -{ - BOOLEAN TryAgain; - - // - // If this is an initial request, buffer will be null with a new buffer size - // - if ((*Buffer == NULL) && (BufferSize != 0)) { - *Status = EFI_BUFFER_TOO_SMALL; - } - // - // If the status code is "buffer too small", resize the buffer - // - TryAgain = FALSE; - if (*Status == EFI_BUFFER_TOO_SMALL) { - - if (*Buffer != NULL) { - FreePool (*Buffer); - } - - *Buffer = AllocateZeroPool (BufferSize); - - if (*Buffer != NULL) { - TryAgain = TRUE; - } else { - *Status = EFI_OUT_OF_RESOURCES; - } - } - // - // If there's an error, free the buffer - // - if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) { - FreePool (*Buffer); - *Buffer = NULL; - } - - return TryAgain; -} - -/** - Function returns the value of the specified variable. - - - @param Name A Null-terminated Unicode string that is - the name of the vendor's variable. - @param VendorGuid A unique identifier for the vendor. - - @return The payload of the variable. - @retval NULL If the variable can't be read. - -**/ -VOID * -EfiLibGetVariable ( - IN CHAR16 *Name, - IN EFI_GUID *VendorGuid - ) -{ - UINTN VarSize; - - return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize); -} - -/** - Function deletes the variable specified by VarName and VarGuid. - - @param VarName A Null-terminated Unicode string that is - the name of the vendor's variable. - - @param VarGuid A unique identifier for the vendor. - - @retval EFI_SUCCESS The variable was found and removed - @retval EFI_UNSUPPORTED The variable store was inaccessible - @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available - @retval EFI_NOT_FOUND The variable was not found - -**/ -EFI_STATUS -EfiLibDeleteVariable ( - IN CHAR16 *VarName, - IN EFI_GUID *VarGuid - ) -{ - VOID *VarBuf; - EFI_STATUS Status; - - VarBuf = EfiLibGetVariable (VarName, VarGuid); - Status = EFI_NOT_FOUND; - - if (VarBuf != NULL) { - // - // Delete variable from Storage - // - Status = gRT->SetVariable ( - VarName, - VarGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - 0, - NULL - ); - // - // Deleting variable with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - FreePool (VarBuf); - } - - return Status; -} - -/** - - Function gets the file system information from an open file descriptor, - and stores it in a buffer allocated from pool. - - - @param FHand The file handle. - - @return A pointer to a buffer with file information. - @retval NULL is returned if failed to get Vaolume Label Info. - -**/ -EFI_FILE_SYSTEM_VOLUME_LABEL * -EfiLibFileSystemVolumeLabelInfo ( - IN EFI_FILE_HANDLE FHand - ) -{ - EFI_STATUS Status; - EFI_FILE_SYSTEM_VOLUME_LABEL *Buffer; - UINTN BufferSize; - // - // Initialize for GrowBuffer loop - // - Buffer = NULL; - BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200; - - // - // Call the real function - // - while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { - Status = FHand->GetInfo ( - FHand, - &gEfiFileSystemVolumeLabelInfoIdGuid, - &BufferSize, - Buffer - ); - } - - return Buffer; -} - -/** - Duplicate a string. - - @param Src The source. - - @return A new string which is duplicated copy of the source. - @retval NULL If there is not enough memory. - -**/ -CHAR16 * -EfiStrDuplicate ( - IN CHAR16 *Src - ) -{ - CHAR16 *Dest; - UINTN Size; - - Size = StrSize (Src); - Dest = AllocateZeroPool (Size); - ASSERT (Dest != NULL); - if (Dest != NULL) { - CopyMem (Dest, Src, Size); - } - - return Dest; -} - -/** - - Function gets the file information from an open file descriptor, and stores it - in a buffer allocated from pool. - - @param FHand File Handle. - - @return A pointer to a buffer with file information or NULL is returned - -**/ -EFI_FILE_INFO * -EfiLibFileInfo ( - IN EFI_FILE_HANDLE FHand - ) -{ - EFI_STATUS Status; - EFI_FILE_INFO *Buffer; - UINTN BufferSize; - - // - // Initialize for GrowBuffer loop - // - Buffer = NULL; - BufferSize = SIZE_OF_EFI_FILE_INFO + 200; - - // - // Call the real function - // - while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { - Status = FHand->GetInfo ( - FHand, - &gEfiFileInfoGuid, - &BufferSize, - Buffer - ); - } - - return Buffer; -} - -/** - Function is used to determine the number of device path instances - that exist in a device path. - - - @param DevicePath A pointer to a device path data structure. - - @return This function counts and returns the number of device path instances - in DevicePath. - -**/ -UINTN -EfiDevicePathInstanceCount ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - UINTN Count; - UINTN Size; - - Count = 0; - while (GetNextDevicePathInstance (&DevicePath, &Size) != NULL) { - Count += 1; - } - - return Count; -} - -/** - Adjusts the size of a previously allocated buffer. - - - @param OldPool - A pointer to the buffer whose size is being adjusted. - @param OldSize - The size of the current buffer. - @param NewSize - The size of the new buffer. - - @return The newly allocated buffer. - @retval NULL Allocation failed. - -**/ -VOID * -EfiReallocatePool ( - IN VOID *OldPool, - IN UINTN OldSize, - IN UINTN NewSize - ) -{ - VOID *NewPool; - - NewPool = NULL; - if (NewSize != 0) { - NewPool = AllocateZeroPool (NewSize); - } - - if (OldPool != NULL) { - if (NewPool != NULL) { - CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); - } - - FreePool (OldPool); - } - - return NewPool; -} - -/** - Get a string from the Data Hub record based on - a device path. - - @param DevPath The device Path. - - @return A string located from the Data Hub records based on - the device path. - @retval NULL If failed to get the String from Data Hub. - -**/ -UINT16 * -EfiLibStrFromDatahub ( - IN EFI_DEVICE_PATH_PROTOCOL *DevPath - ) -{ - return NULL; -} - -/** - - Find the first instance of this Protocol - in the system and return it's interface. - - - @param ProtocolGuid Provides the protocol to search for - @param Interface On return, a pointer to the first interface - that matches ProtocolGuid - - @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found - @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid - -**/ -EFI_STATUS -EfiLibLocateProtocol ( - IN EFI_GUID *ProtocolGuid, - OUT VOID **Interface - ) -{ - EFI_STATUS Status; - - Status = gBS->LocateProtocol ( - ProtocolGuid, - NULL, - (VOID **) Interface - ); - return Status; -} - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni deleted file mode 100644 index b0aabc3b11..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c deleted file mode 100644 index d4b4475f09..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c +++ /dev/null @@ -1,1690 +0,0 @@ -/** @file - The functions for Boot Maintainence Main menu. - -Copyright (c) 2004 - 2015, Intel 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 "BootMaint.h" -#include "FormGuid.h" -#include "Bds.h" -#include "FrontPage.h" - -EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = { - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - END_DEVICE_PATH_LENGTH, - 0 - } - } -}; - -HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - BOOT_MAINT_FORMSET_GUID - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - (UINT8) (END_DEVICE_PATH_LENGTH), - (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) - } - } -}; - -HII_VENDOR_DEVICE_PATH mFeHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - FILE_EXPLORE_FORMSET_GUID - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - (UINT8) (END_DEVICE_PATH_LENGTH), - (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) - } - } -}; - -CHAR16 mBootMaintStorageName[] = L"BmmData"; -CHAR16 mFileExplorerStorageName[] = L"FeData"; -BMM_CALLBACK_DATA *mBmmCallbackInfo = NULL; - -/** - Init all memu. - - @param CallbackData The BMM context data. - -**/ -VOID -InitAllMenu ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Free up all Menu Option list. - -**/ -VOID -FreeAllMenu ( - VOID - ); - -/** - Initialize all of BMM configuration data in BmmFakeNvData and BmmOldFakeNVData member - in BMM context data and create all of dynamic OP code for BMM. - - @param CallbackData The BMM context data. - -**/ -VOID -InitializeBmmConfig ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT16 Index; - - ASSERT (CallbackData != NULL); - - // - // Initialize data which located in BMM main page - // - CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber); - for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - - if (NewLoadContext->IsBootNext) { - CallbackData->BmmFakeNvData.BootNext = Index; - break; - } - } - - CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); - - // - // Initialize data which located in Boot Options Menu - // - GetBootOrder (CallbackData); - GetLegacyDeviceOrder (CallbackData); - - // - // Initialize data which located in Driver Options Menu - // - GetDriverOrder (CallbackData); - - // - // Initialize data which located in Console Options Menu - // - GetConsoleOutMode (CallbackData); - GetConsoleInCheck (CallbackData); - GetConsoleOutCheck (CallbackData); - GetConsoleErrCheck (CallbackData); - GetTerminalAttribute (CallbackData); - - // - // Backup Initialize BMM configuartion data to BmmOldFakeNVData - // - CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA)); -} - -/** - Create string tokens for a menu from its help strings and display strings - - @param CallbackData The BMM context data. - @param HiiHandle Hii Handle of the package to be updated. - @param MenuOption The Menu whose string tokens need to be created - - @retval EFI_SUCCESS String tokens created successfully - @retval others contain some errors -**/ -EFI_STATUS -CreateMenuStringToken ( - IN BMM_CALLBACK_DATA *CallbackData, - IN EFI_HII_HANDLE HiiHandle, - IN BM_MENU_OPTION *MenuOption - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - UINTN Index; - - for (Index = 0; Index < MenuOption->MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); - - NewMenuEntry->DisplayStringToken = HiiSetString ( - HiiHandle, - 0, - NewMenuEntry->DisplayString, - NULL - ); - - if (NULL == NewMenuEntry->HelpString) { - NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; - } else { - NewMenuEntry->HelpStringToken = HiiSetString ( - HiiHandle, - 0, - NewMenuEntry->HelpString, - NULL - ); - } - } - - return EFI_SUCCESS; -} - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -BootMaintExtractConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Request, - OUT EFI_STRING *Progress, - OUT EFI_STRING *Results - ) -{ - EFI_STATUS Status; - UINTN BufferSize; - BMM_CALLBACK_DATA *Private; - EFI_STRING ConfigRequestHdr; - EFI_STRING ConfigRequest; - BOOLEAN AllocatedRequest; - UINTN Size; - - if (Progress == NULL || Results == NULL) { - return EFI_INVALID_PARAMETER; - } - - *Progress = Request; - if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gBootMaintFormSetGuid, mBootMaintStorageName)) { - return EFI_NOT_FOUND; - } - - ConfigRequestHdr = NULL; - ConfigRequest = NULL; - AllocatedRequest = FALSE; - Size = 0; - - Private = BMM_CALLBACK_DATA_FROM_THIS (This); - // - // Convert buffer data to by helper function BlockToConfig() - // - BufferSize = sizeof (BMM_FAKE_NV_DATA); - 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 (&gBootMaintFormSetGuid, mBootMaintStorageName, Private->BmmDriverHandle); - Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); - ConfigRequest = AllocateZeroPool (Size); - ASSERT (ConfigRequest != NULL); - AllocatedRequest = TRUE; - UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); - FreePool (ConfigRequestHdr); - } - - Status = gHiiConfigRouting->BlockToConfig ( - gHiiConfigRouting, - ConfigRequest, - (UINT8 *) &Private->BmmFakeNvData, - BufferSize, - 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 applies changes in a driver's configuration. - Input is a Configuration, which has the routing data for this - driver followed by name / value configuration pairs. The driver - must apply those pairs to its configurable storage. If the - driver's configuration is stored in a linear block of data - and the driver's name / value pairs are in - format, it may use the ConfigToBlock helper function (above) to - simplify the job. Currently not implemented. - - @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param[in] Configuration A null-terminated Unicode string in - format. - @param[out] Progress A pointer to a string filled in with the - offset of the most recent '&' before the - first failing name / value pair (or the - beginn ing 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 have been distributed or are - awaiting distribution. - @retval EFI_OUT_OF_RESOURCES Not enough memory to store the - parts of the results that must be - stored awaiting possible future - protocols. - @retval EFI_INVALID_PARAMETERS Passing in a NULL for the - Results parameter would result - in this type of error. - @retval EFI_NOT_FOUND Target for the specified routing data - was not found. -**/ -EFI_STATUS -EFIAPI -BootMaintRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ) -{ - EFI_STATUS Status; - UINTN BufferSize; - EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; - BMM_FAKE_NV_DATA *NewBmmData; - BMM_FAKE_NV_DATA *OldBmmData; - BM_CONSOLE_CONTEXT *NewConsoleContext; - BM_TERMINAL_CONTEXT *NewTerminalContext; - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT16 Index; - BOOLEAN TerminalAttChange; - BMM_CALLBACK_DATA *Private; - - if (Progress == NULL) { - return EFI_INVALID_PARAMETER; - } - *Progress = Configuration; - - if (Configuration == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check routing data in . - // Note: there is no name for Name/Value storage, only GUID will be checked - // - if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName)) { - return EFI_NOT_FOUND; - } - - Status = gBS->LocateProtocol ( - &gEfiHiiConfigRoutingProtocolGuid, - NULL, - (VOID**) &ConfigRouting - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Private = BMM_CALLBACK_DATA_FROM_THIS (This); - // - // Get Buffer Storage data from EFI variable - // - BufferSize = sizeof (BMM_FAKE_NV_DATA); - OldBmmData = &Private->BmmOldFakeNVData; - NewBmmData = &Private->BmmFakeNvData; - // - // Convert to buffer data by helper function ConfigToBlock() - // - Status = ConfigRouting->ConfigToBlock ( - ConfigRouting, - Configuration, - (UINT8 *) NewBmmData, - &BufferSize, - Progress - ); - ASSERT_EFI_ERROR (Status); - // - // Compare new and old BMM configuration data and only do action for modified item to - // avoid setting unnecessary non-volatile variable - // - - // - // Check data which located in BMM main page and save the settings if need - // - if (CompareMem (NewBmmData->LegacyFD, OldBmmData->LegacyFD, sizeof (NewBmmData->LegacyFD)) != 0) { - Var_UpdateBBSOption (Private, FORM_SET_FD_ORDER_ID); - } - - if (CompareMem (NewBmmData->LegacyHD, OldBmmData->LegacyHD, sizeof (NewBmmData->LegacyHD)) != 0) { - Var_UpdateBBSOption (Private, FORM_SET_HD_ORDER_ID); - } - - if (CompareMem (NewBmmData->LegacyCD, OldBmmData->LegacyCD, sizeof (NewBmmData->LegacyCD)) != 0) { - Var_UpdateBBSOption (Private, FORM_SET_CD_ORDER_ID); - } - - if (CompareMem (NewBmmData->LegacyNET, OldBmmData->LegacyNET, sizeof (NewBmmData->LegacyNET)) != 0) { - Var_UpdateBBSOption (Private, FORM_SET_NET_ORDER_ID); - } - - if (CompareMem (NewBmmData->LegacyBEV, OldBmmData->LegacyBEV, sizeof (NewBmmData->LegacyBEV)) != 0) { - Var_UpdateBBSOption (Private, FORM_SET_BEV_ORDER_ID); - } - - // - // Change for "delete boot option" page need update NewBmmData->BootOptionOrder, so process - // NewBmmData->BootOptionOrder before NewBmmData->BootOptionDel - // - if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) { - Status = Var_UpdateBootOrder (Private); - } - - // - // Change for "delete driver option" page need update NewBmmData->DriverOptionOrder, so process - // NewBmmData->DriverOptionOrder before NewBmmData->DriverOptionDel - // - if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) { - Status = Var_UpdateDriverOrder (Private); - } - - // - // Check data which located in Boot Options Menu and save the settings if need - // - if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) { - for (Index = 0; - ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); - Index ++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index]; - NewBmmData->BootOptionDel[Index] = FALSE; - NewBmmData->BootOptionDelMark[Index] = FALSE; - } - - Var_DelBootOption (); - } - - // - // Check data which located in Driver Options Menu and save the settings if need - // - if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) { - for (Index = 0; - ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); - Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index]; - NewBmmData->DriverOptionDel[Index] = FALSE; - NewBmmData->DriverOptionDelMark[Index] = FALSE; - } - Var_DelDriverOption (); - } - - if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0) { - Status = gRT->SetVariable ( - L"Timeout", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - sizeof (UINT16), - &(NewBmmData->BootTimeOut) - ); - ASSERT_EFI_ERROR(Status); - - // - // Bugbug: code not exit in UiApp but in IntelFrameworkModulePkg, need do more check. - // - Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut; - } - - if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) { - Status = Var_UpdateBootNext (Private); - } - - if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0) { - Var_UpdateConMode (Private); - } - - TerminalAttChange = FALSE; - for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { - - // - // only need update modified items - // - if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 && - CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 && - CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 && - CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 && - CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 && - CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) { - continue; - } - - NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); - ASSERT (NewMenuEntry != NULL); - NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; - NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index]; - ASSERT (NewBmmData->COMBaudRate[Index] < (sizeof (BaudRateList) / sizeof (BaudRateList[0]))); - NewTerminalContext->BaudRate = BaudRateList[NewBmmData->COMBaudRate[Index]].Value; - NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index]; - ASSERT (NewBmmData->COMDataRate[Index] < (sizeof (DataBitsList) / sizeof (DataBitsList[0]))); - NewTerminalContext->DataBits = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value; - NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index]; - ASSERT (NewBmmData->COMStopBits[Index] < (sizeof (StopBitsList) / sizeof (StopBitsList[0]))); - NewTerminalContext->StopBits = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value; - NewTerminalContext->ParityIndex = NewBmmData->COMParity[Index]; - ASSERT (NewBmmData->COMParity[Index] < (sizeof (ParityList) / sizeof (ParityList[0]))); - NewTerminalContext->Parity = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value; - NewTerminalContext->TerminalType = NewBmmData->COMTerminalType[Index]; - NewTerminalContext->FlowControl = NewBmmData->COMFlowControl[Index]; - ChangeTerminalDevicePath ( - &(NewTerminalContext->DevicePath), - FALSE - ); - TerminalAttChange = TRUE; - } - if (TerminalAttChange) { - Var_UpdateConsoleInpOption (); - Var_UpdateConsoleOutOption (); - Var_UpdateErrorOutOption (); - } - - // - // Check data which located in Console Options Menu and save the settings if need - // - if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0) { - for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); - NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; - ASSERT (Index < MAX_MENU_NUMBER); - NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index]; - } - - Var_UpdateConsoleInpOption (); - } - - if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0) { - for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); - NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; - ASSERT (Index < MAX_MENU_NUMBER); - NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index]; - } - - Var_UpdateConsoleOutOption (); - } - - if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0) { - for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); - NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; - ASSERT (Index < MAX_MENU_NUMBER); - NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index]; - } - - Var_UpdateErrorOutOption (); - } - - // - // After user do the save action, need to update OldBmmData. - // - CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA)); - - return EFI_SUCCESS; -} - -/** - Create GoTo OP code into FORM_BOOT_LEGACY_DEVICE label for legacy boot option. - -**/ -EFI_STATUS -InitializeLegacyBootOption ( - VOID - ) -{ - RefreshUpdateData (); - mStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID; - - // - // If LegacyBios Protocol is installed, add 3 tags about legacy boot option - // in BootOption form: legacy FD/HD/CD/NET/BEV - // - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FORM_SET_FD_ORDER_ID, - STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), - STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), - EFI_IFR_FLAG_CALLBACK, - FORM_SET_FD_ORDER_ID - ); - - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FORM_SET_HD_ORDER_ID, - STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), - STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), - EFI_IFR_FLAG_CALLBACK, - FORM_SET_HD_ORDER_ID - ); - - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FORM_SET_CD_ORDER_ID, - STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), - STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), - EFI_IFR_FLAG_CALLBACK, - FORM_SET_CD_ORDER_ID - ); - - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FORM_SET_NET_ORDER_ID, - STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), - STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), - EFI_IFR_FLAG_CALLBACK, - FORM_SET_NET_ORDER_ID - ); - - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FORM_SET_BEV_ORDER_ID, - STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), - STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), - EFI_IFR_FLAG_CALLBACK, - FORM_SET_BEV_ORDER_ID - ); - - HiiUpdateForm ( - mBmmCallbackInfo->BmmHiiHandle, - &gBootMaintFormSetGuid, - FORM_BOOT_SETUP_ID, - mStartOpCodeHandle, // Label FORM_BOOT_LEGACY_DEVICE_ID - mEndOpCodeHandle // LABEL_END - ); - - return EFI_SUCCESS; -} - -/** - This function processes the results of changes in configuration. - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be saved. - @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. - @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. -**/ -EFI_STATUS -EFIAPI -BootMaintCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - BMM_CALLBACK_DATA *Private; - BM_MENU_ENTRY *NewMenuEntry; - BMM_FAKE_NV_DATA *CurrentFakeNVMap; - EFI_STATUS Status; - UINTN OldValue; - UINTN NewValue; - UINTN Number; - UINTN Pos; - UINTN Bit; - UINT16 NewValuePos; - UINT16 Index3; - UINT16 Index2; - UINT16 Index; - UINT8 *OldLegacyDev; - UINT8 *NewLegacyDev; - UINT8 *DisMap; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - - Private = BMM_CALLBACK_DATA_FROM_THIS (This); - if (Action == EFI_BROWSER_ACTION_FORM_OPEN && QuestionId == FORM_BOOT_SETUP_ID) { - // - // Initilize Form for legacy boot option. - // - Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios); - if (!EFI_ERROR (Status)) { - InitializeLegacyBootOption (); - } - - return EFI_SUCCESS; - } - - if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { - // - // All other action return unsupported. - // - return EFI_UNSUPPORTED; - } - - Status = EFI_SUCCESS; - OldValue = 0; - NewValue = 0; - Number = 0; - OldLegacyDev = NULL; - NewLegacyDev = NULL; - NewValuePos = 0; - DisMap = NULL; - - Private = BMM_CALLBACK_DATA_FROM_THIS (This); - // - // Retrive uncommitted data from Form Browser - // - CurrentFakeNVMap = &Private->BmmFakeNvData; - HiiGetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); - if (Action == EFI_BROWSER_ACTION_CHANGING) { - if (Value == NULL) { - return EFI_INVALID_PARAMETER; - } - - UpdatePageId (Private, QuestionId); - - if (QuestionId < FILE_OPTION_OFFSET) { - if (QuestionId < CONFIG_OPTION_OFFSET) { - switch (QuestionId) { - case KEY_VALUE_BOOT_FROM_FILE: - Private->FeCurrentState = FileExplorerStateBootFromFile; - break; - - case FORM_BOOT_ADD_ID: - Private->FeCurrentState = FileExplorerStateAddBootOption; - break; - - case FORM_DRV_ADD_FILE_ID: - Private->FeCurrentState = FileExplorerStateAddDriverOptionState; - break; - - case FORM_DRV_ADD_HANDLE_ID: - CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); - UpdateDrvAddHandlePage (Private); - break; - - case FORM_BOOT_DEL_ID: - CleanUpPage (FORM_BOOT_DEL_ID, Private); - UpdateBootDelPage (Private); - break; - - case FORM_BOOT_CHG_ID: - case FORM_DRV_CHG_ID: - UpdatePageBody (QuestionId, Private); - break; - - case FORM_DRV_DEL_ID: - CleanUpPage (FORM_DRV_DEL_ID, Private); - UpdateDrvDelPage (Private); - break; - - case FORM_BOOT_NEXT_ID: - CleanUpPage (FORM_BOOT_NEXT_ID, Private); - UpdateBootNextPage (Private); - break; - - case FORM_TIME_OUT_ID: - CleanUpPage (FORM_TIME_OUT_ID, Private); - UpdateTimeOutPage (Private); - break; - - case FORM_CON_IN_ID: - case FORM_CON_OUT_ID: - case FORM_CON_ERR_ID: - UpdatePageBody (QuestionId, Private); - break; - - case FORM_CON_MODE_ID: - CleanUpPage (FORM_CON_MODE_ID, Private); - UpdateConModePage (Private); - break; - - case FORM_CON_COM_ID: - CleanUpPage (FORM_CON_COM_ID, Private); - UpdateConCOMPage (Private); - break; - - case FORM_SET_FD_ORDER_ID: - case FORM_SET_HD_ORDER_ID: - case FORM_SET_CD_ORDER_ID: - case FORM_SET_NET_ORDER_ID: - case FORM_SET_BEV_ORDER_ID: - CleanUpPage (QuestionId, Private); - UpdateSetLegacyDeviceOrderPage (QuestionId, Private); - break; - - default: - break; - } - } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { - Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); - Private->CurrentTerminal = Index2; - - CleanUpPage (FORM_CON_COM_SETUP_ID, Private); - UpdateTerminalPage (Private); - - } else if (QuestionId >= HANDLE_OPTION_OFFSET) { - Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); - - NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2); - ASSERT (NewMenuEntry != NULL); - Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; - - CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); - - Private->MenuEntry = NewMenuEntry; - Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; - - UpdateDriverAddHandleDescPage (Private); - } - } - } else if (Action == EFI_BROWSER_ACTION_CHANGED) { - if ((Value == NULL) || (ActionRequest == NULL)) { - return EFI_INVALID_PARAMETER; - } - if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { - if (Value->b){ - // - // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu. - // - CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE; - } else { - // - // Means user remove the old check status. - // - CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE; - } - } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { - if (Value->b){ - CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE; - } else { - CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE; - } - } else if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) { - // - // Update Select FD/HD/CD/NET/BEV Order Form - // - - DisMap = Private->BmmOldFakeNVData.DisableMap; - - if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyFDMenu.MenuNumber; - OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD; - NewLegacyDev = CurrentFakeNVMap->LegacyFD; - } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyHDMenu.MenuNumber; - OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD; - NewLegacyDev = CurrentFakeNVMap->LegacyHD; - } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyCDMenu.MenuNumber; - OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD; - NewLegacyDev = CurrentFakeNVMap->LegacyCD; - } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyNETMenu.MenuNumber; - OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET; - NewLegacyDev = CurrentFakeNVMap->LegacyNET; - } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { - Number = (UINT16) LegacyBEVMenu.MenuNumber; - OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV; - NewLegacyDev = CurrentFakeNVMap->LegacyBEV; - } - // - // First, find the different position - // if there is change, it should be only one - // - for (Index = 0; Index < Number; Index++) { - if (OldLegacyDev[Index] != NewLegacyDev[Index]) { - OldValue = OldLegacyDev[Index]; - NewValue = NewLegacyDev[Index]; - break; - } - } - - if (Index != Number) { - // - // there is change, now process - // - if (0xFF == NewValue) { - // - // This item will be disable - // Just move the items behind this forward to overlap it - // - Pos = OldValue / 8; - Bit = 7 - (OldValue % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); - for (Index2 = Index; Index2 < Number - 1; Index2++) { - NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1]; - } - - NewLegacyDev[Index2] = 0xFF; - } else { - for (Index2 = 0; Index2 < Number; Index2++) { - if (Index2 == Index) { - continue; - } - - if (OldLegacyDev[Index2] == NewValue) { - // - // If NewValue is in OldLegacyDev array - // remember its old position - // - NewValuePos = Index2; - break; - } - } - - if (Index2 != Number) { - // - // We will change current item to an existing item - // (It's hard to describe here, please read code, it's like a cycle-moving) - // - for (Index2 = NewValuePos; Index2 != Index;) { - if (NewValuePos < Index) { - NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1]; - Index2++; - } else { - NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1]; - Index2--; - } - } - } else { - // - // If NewValue is not in OldlegacyDev array, we are changing to a disabled item - // so we should modify DisMap to reflect the change - // - Pos = NewValue / 8; - Bit = 7 - (NewValue % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); - if (0xFF != OldValue) { - // - // Because NewValue is a item that was disabled before - // so after changing the OldValue should be disabled - // actually we are doing a swap of enable-disable states of two items - // - Pos = OldValue / 8; - Bit = 7 - (OldValue % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); - } - } - } - // - // To prevent DISABLE appears in the middle of the list - // we should perform a re-ordering - // - Index3 = Index; - Index = 0; - while (Index < Number) { - if (0xFF != NewLegacyDev[Index]) { - Index++; - continue; - } - - Index2 = Index; - Index2++; - while (Index2 < Number) { - if (0xFF != NewLegacyDev[Index2]) { - break; - } - - Index2++; - } - - if (Index2 < Number) { - NewLegacyDev[Index] = NewLegacyDev[Index2]; - NewLegacyDev[Index2] = 0xFF; - } - - Index++; - } - - // - // Return correct question value. - // - Value->u8 = NewLegacyDev[Index3]; - } - } else { - switch (QuestionId) { - case KEY_VALUE_SAVE_AND_EXIT: - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; - break; - - case KEY_VALUE_NO_SAVE_AND_EXIT: - // - // Restore local maintain data. - // - DiscardChangeHandler (Private, CurrentFakeNVMap); - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; - break; - - case FORM_RESET: - gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); - return EFI_UNSUPPORTED; - - default: - break; - } - } - } - - // - // Pass changed uncommitted data back to Form Browser - // - HiiSetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); - return EFI_SUCCESS; -} - -/** - Discard all changes done to the BMM pages such as Boot Order change, - Driver order change. - - @param Private The BMM context data. - @param CurrentFakeNVMap The current Fack NV Map. - -**/ -VOID -DiscardChangeHandler ( - IN BMM_CALLBACK_DATA *Private, - IN BMM_FAKE_NV_DATA *CurrentFakeNVMap - ) -{ - UINT16 Index; - - switch (Private->BmmPreviousPageId) { - case FORM_BOOT_CHG_ID: - CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder)); - break; - - case FORM_DRV_CHG_ID: - CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder)); - break; - - case FORM_BOOT_DEL_ID: - ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0]))); - for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { - CurrentFakeNVMap->BootOptionDel[Index] = FALSE; - CurrentFakeNVMap->BootOptionDelMark[Index] = FALSE; - } - break; - - case FORM_DRV_DEL_ID: - ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0]))); - for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { - CurrentFakeNVMap->DriverOptionDel[Index] = FALSE; - CurrentFakeNVMap->DriverOptionDelMark[Index] = FALSE; - } - break; - - case FORM_BOOT_NEXT_ID: - CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext; - break; - - case FORM_TIME_OUT_ID: - CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut; - break; - - case FORM_DRV_ADD_HANDLE_DESC_ID: - case FORM_DRV_ADD_FILE_ID: - case FORM_DRV_ADD_HANDLE_ID: - CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000; - CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000; - break; - - default: - break; - } -} - -/** - Initialize the Boot Maintenance Utitliy. - - - @retval EFI_SUCCESS utility ended successfully - @retval others contain some errors - -**/ -EFI_STATUS -InitializeBM ( - VOID - ) -{ - BMM_CALLBACK_DATA *BmmCallbackInfo; - EFI_STATUS Status; - EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; - UINT32 Length; - UINT8 *Data; - - Status = EFI_SUCCESS; - BmmCallbackInfo = mBmmCallbackInfo; - - BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; - BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; - BmmCallbackInfo->FeCurrentState = FileExplorerStateInActive; - BmmCallbackInfo->FeDisplayContext = FileExplorerDisplayUnknown; - - // - // Reinstall String packages to include more new strings. - // - - // - // String package size - // - Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32); - - // - // Add the length of the Package List Header and the terminating Package Header - // - Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER); - - // - // Allocate the storage for the entire Package List - // - PackageListHeader = AllocateZeroPool (Length); - - // - // If the Package List can not be allocated, then return a NULL HII Handle - // - if (PackageListHeader == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Fill in the GUID and Length of the Package List Header - // - PackageListHeader->PackageLength = Length; - - // - // Copy String Data into Package list. - // - Data = (UINT8 *)(PackageListHeader + 1); - Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32); - CopyMem (Data, (UINT8 *) BdsDxeStrings + sizeof (UINT32), Length); - - // - // Add End type HII package. - // - Data += Length; - ((EFI_HII_PACKAGE_HEADER *) Data)->Type = EFI_HII_PACKAGE_END; - ((EFI_HII_PACKAGE_HEADER *) Data)->Length = sizeof (EFI_HII_PACKAGE_HEADER); - - // - // Update String package for BM - // - CopyGuid (&PackageListHeader->PackageListGuid, &gBootMaintFormSetGuid); - Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle, PackageListHeader); - - // - // Update String package for FE. - // - CopyGuid (&PackageListHeader->PackageListGuid, &gFileExploreFormSetGuid); - Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle, PackageListHeader); - - FreePool (PackageListHeader); - - // - // Init OpCode Handle and Allocate space for creation of Buffer - // - mStartOpCodeHandle = HiiAllocateOpCodeHandle (); - if (mStartOpCodeHandle == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - mEndOpCodeHandle = HiiAllocateOpCodeHandle (); - if (mEndOpCodeHandle == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - // - // Create Hii Extend Label OpCode as the start opcode - // - mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - - // - // Create Hii Extend Label OpCode as the end opcode - // - mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - mEndLabel->Number = LABEL_END; - - InitializeStringDepository (); - - InitAllMenu (BmmCallbackInfo); - - CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu); - CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu); - CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu); - CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu); - CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu); - CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu); - CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu); - - InitializeBmmConfig (BmmCallbackInfo); - - // - // Dispatch BMM main formset and File Explorer formset. - // - FormSetDispatcher (BmmCallbackInfo); - - // - // Clean up. - // - CleanUpStringDepository (); - - FreeAllMenu (); - -Exit: - if (mStartOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (mStartOpCodeHandle); - } - - if (mEndOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (mEndOpCodeHandle); - } - - return Status; -} - - -/** - Initialized all Menu Option List. - - @param CallbackData The BMM context data. - -**/ -VOID -InitAllMenu ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - InitializeListHead (&BootOptionMenu.Head); - InitializeListHead (&DriverOptionMenu.Head); - BOpt_GetBootOptions (CallbackData); - BOpt_GetDriverOptions (CallbackData); - BOpt_GetLegacyOptions (); - InitializeListHead (&FsOptionMenu.Head); - BOpt_FindDrivers (); - InitializeListHead (&DirectoryMenu.Head); - InitializeListHead (&ConsoleInpMenu.Head); - InitializeListHead (&ConsoleOutMenu.Head); - InitializeListHead (&ConsoleErrMenu.Head); - InitializeListHead (&TerminalMenu.Head); - LocateSerialIo (); - GetAllConsoles (); -} - -/** - Free up all Menu Option list. - -**/ -VOID -FreeAllMenu ( - VOID - ) -{ - BOpt_FreeMenu (&DirectoryMenu); - BOpt_FreeMenu (&FsOptionMenu); - BOpt_FreeMenu (&BootOptionMenu); - BOpt_FreeMenu (&DriverOptionMenu); - BOpt_FreeMenu (&DriverMenu); - BOpt_FreeLegacyOptions (); - FreeAllConsoles (); -} - -/** - Initialize all the string depositories. - -**/ -VOID -InitializeStringDepository ( - VOID - ) -{ - STRING_DEPOSITORY *StringDepository; - StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER); - FileOptionStrDepository = StringDepository++; - ConsoleOptionStrDepository = StringDepository++; - BootOptionStrDepository = StringDepository++; - BootOptionHelpStrDepository = StringDepository++; - DriverOptionStrDepository = StringDepository++; - DriverOptionHelpStrDepository = StringDepository++; - TerminalStrDepository = StringDepository; -} - -/** - Fetch a usable string node from the string depository and return the string token. - - @param CallbackData The BMM context data. - @param StringDepository The string repository. - - @retval EFI_STRING_ID String token. - -**/ -EFI_STRING_ID -GetStringTokenFromDepository ( - IN BMM_CALLBACK_DATA *CallbackData, - IN STRING_DEPOSITORY *StringDepository - ) -{ - STRING_LIST_NODE *CurrentListNode; - STRING_LIST_NODE *NextListNode; - - CurrentListNode = StringDepository->CurrentNode; - - if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) { - // - // Fetch one reclaimed node from the list. - // - NextListNode = StringDepository->CurrentNode->Next; - } else { - // - // If there is no usable node in the list, update the list. - // - NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE)); - ASSERT (NextListNode != NULL); - NextListNode->StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, L" ", NULL); - ASSERT (NextListNode->StringToken != 0); - - StringDepository->TotalNodeNumber++; - - if (NULL == CurrentListNode) { - StringDepository->ListHead = NextListNode; - } else { - CurrentListNode->Next = NextListNode; - } - } - - StringDepository->CurrentNode = NextListNode; - - return StringDepository->CurrentNode->StringToken; -} - -/** - Reclaim string depositories by moving the current node pointer to list head.. - -**/ -VOID -ReclaimStringDepository ( - VOID - ) -{ - UINTN DepositoryIndex; - STRING_DEPOSITORY *StringDepository; - - StringDepository = FileOptionStrDepository; - for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { - StringDepository->CurrentNode = StringDepository->ListHead; - StringDepository++; - } -} - -/** - Release resource for all the string depositories. - -**/ -VOID -CleanUpStringDepository ( - VOID - ) -{ - UINTN NodeIndex; - UINTN DepositoryIndex; - STRING_LIST_NODE *CurrentListNode; - STRING_LIST_NODE *NextListNode; - STRING_DEPOSITORY *StringDepository; - - // - // Release string list nodes. - // - StringDepository = FileOptionStrDepository; - for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { - CurrentListNode = StringDepository->ListHead; - for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) { - NextListNode = CurrentListNode->Next; - FreePool (CurrentListNode); - CurrentListNode = NextListNode; - } - - StringDepository++; - } - // - // Release string depository. - // - FreePool (FileOptionStrDepository); -} - -/** - Start boot maintenance manager - - @retval EFI_SUCCESS If BMM is invoked successfully. - @return Other value if BMM return unsuccessfully. - -**/ -EFI_STATUS -BdsStartBootMaint ( - VOID - ) -{ - EFI_STATUS Status; - LIST_ENTRY BdsBootOptionList; - - InitializeListHead (&BdsBootOptionList); - - // - // Connect all prior to entering the platform setup menu. - // - if (!gConnectAllHappened) { - BdsLibConnectAllDriversToAllControllers (); - gConnectAllHappened = TRUE; - } - // - // Have chance to enumerate boot device - // - BdsLibEnumerateAllBootOption (&BdsBootOptionList); - - // - // Group the legacy boot options for the same device type - // - GroupMultipleLegacyBootOption4SameType (); - - // - // Init the BMM - // - Status = InitializeBM (); - - return Status; -} - -/** - Dispatch BMM formset and FileExplorer formset. - - - @param CallbackData The BMM context data. - - @retval EFI_SUCCESS If function complete successfully. - @return Other value if the Setup Browser process BMM's pages and - return unsuccessfully. - -**/ -EFI_STATUS -FormSetDispatcher ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - EFI_STATUS Status; - EFI_BROWSER_ACTION_REQUEST ActionRequest; - - while (TRUE) { - UpdatePageId (CallbackData, FORM_MAIN_ID); - - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - Status = gFormBrowser2->SendForm ( - gFormBrowser2, - &CallbackData->BmmHiiHandle, - 1, - &gBootMaintFormSetGuid, - 0, - NULL, - &ActionRequest - ); - if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { - EnableResetRequired (); - } - - ReclaimStringDepository (); - - // - // When this Formset returns, check if we are going to explore files. - // - if (FileExplorerStateInActive != CallbackData->FeCurrentState) { - UpdateFileExplorer (CallbackData, 0); - - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - Status = gFormBrowser2->SendForm ( - gFormBrowser2, - &CallbackData->FeHiiHandle, - 1, - &gFileExploreFormSetGuid, - 0, - NULL, - &ActionRequest - ); - if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { - EnableResetRequired (); - } - - CallbackData->FeCurrentState = FileExplorerStateInActive; - CallbackData->FeDisplayContext = FileExplorerDisplayUnknown; - ReclaimStringDepository (); - } else { - break; - } - } - - return Status; -} - -/** - Intall BootMaint and FileExplorer HiiPackages. - -**/ -EFI_STATUS -InitBMPackage ( - VOID - ) -{ - BMM_CALLBACK_DATA *BmmCallbackInfo; - EFI_STATUS Status; - UINT8 *Ptr; - - // - // Create CallbackData structures for Driver Callback - // - BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA)); - if (BmmCallbackInfo == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Create LoadOption in BmmCallbackInfo for Driver Callback - // - Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY)); - if (Ptr == NULL) { - FreePool (BmmCallbackInfo); - BmmCallbackInfo = NULL; - return EFI_OUT_OF_RESOURCES; - } - // - // Initialize Bmm callback data. - // - BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr; - Ptr += sizeof (BM_LOAD_CONTEXT); - - BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr; - Ptr += sizeof (BM_FILE_CONTEXT); - - BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr; - Ptr += sizeof (BM_HANDLE_CONTEXT); - - BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr; - - BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE; - BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig; - BmmCallbackInfo->BmmConfigAccess.RouteConfig = BootMaintRouteConfig; - BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback; - BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig; - BmmCallbackInfo->FeConfigAccess.RouteConfig = FileExplorerRouteConfig; - BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback; - - // - // Install Device Path Protocol and Config Access protocol to driver handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &BmmCallbackInfo->BmmDriverHandle, - &gEfiDevicePathProtocolGuid, - &mBmmHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &BmmCallbackInfo->BmmConfigAccess, - NULL - ); - ASSERT_EFI_ERROR (Status); - - // - // Install Device Path Protocol and Config Access protocol to driver handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &BmmCallbackInfo->FeDriverHandle, - &gEfiDevicePathProtocolGuid, - &mFeHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &BmmCallbackInfo->FeConfigAccess, - NULL - ); - ASSERT_EFI_ERROR (Status); - - // - // Post our Boot Maint VFR binary to the HII database. - // - BmmCallbackInfo->BmmHiiHandle = HiiAddPackages ( - &gBootMaintFormSetGuid, - BmmCallbackInfo->BmmDriverHandle, - BmBin, - BdsDxeStrings, - NULL - ); - ASSERT (BmmCallbackInfo->BmmHiiHandle != NULL); - - // - // Post our File Explorer VFR binary to the HII database. - // - BmmCallbackInfo->FeHiiHandle = HiiAddPackages ( - &gFileExploreFormSetGuid, - BmmCallbackInfo->FeDriverHandle, - FEBin, - BdsDxeStrings, - NULL - ); - ASSERT (BmmCallbackInfo->FeHiiHandle != NULL); - - mBmmCallbackInfo = BmmCallbackInfo; - - return EFI_SUCCESS; -} - -/** - Remvoe the intalled BootMaint and FileExplorer HiiPackages. - -**/ -VOID -FreeBMPackage ( - VOID - ) -{ - BMM_CALLBACK_DATA *BmmCallbackInfo; - - BmmCallbackInfo = mBmmCallbackInfo; - - // - // Remove our IFR data from HII database - // - HiiRemovePackages (BmmCallbackInfo->BmmHiiHandle); - HiiRemovePackages (BmmCallbackInfo->FeHiiHandle); - - if (BmmCallbackInfo->FeDriverHandle != NULL) { - gBS->UninstallMultipleProtocolInterfaces ( - BmmCallbackInfo->FeDriverHandle, - &gEfiDevicePathProtocolGuid, - &mFeHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &BmmCallbackInfo->FeConfigAccess, - NULL - ); - } - - if (BmmCallbackInfo->BmmDriverHandle != NULL) { - gBS->UninstallMultipleProtocolInterfaces ( - BmmCallbackInfo->BmmDriverHandle, - &gEfiDevicePathProtocolGuid, - &mBmmHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &BmmCallbackInfo->BmmConfigAccess, - NULL - ); - } - - FreePool (BmmCallbackInfo->LoadContext); - FreePool (BmmCallbackInfo); - - mBmmCallbackInfo = NULL; - - return; -} - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h deleted file mode 100644 index 098692fa53..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h +++ /dev/null @@ -1,1679 +0,0 @@ -/** @file - Header file for boot maintenance module. - -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 -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 _BOOT_MAINT_H_ -#define _BOOT_MAINT_H_ - -#include "Bds.h" -#include "BBSsupport.h" -#include "FormGuid.h" -#include "FrontPage.h" - -// -// Constants which are variable names used to access variables -// -#define VAR_CON_OUT_MODE L"ConOutMode" - -// -// String Contant -// -#define STR_FLOPPY L"Floppy Drive #%02x" -#define STR_HARDDISK L"HardDisk Drive #%02x" -#define STR_CDROM L"ATAPI CDROM Drive #%02x" -#define STR_NET L"NET Drive #%02x" -#define STR_BEV L"BEV Drive #%02x" -#define STR_FLOPPY_HELP L"Select Floppy Drive #%02x" -#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x" -#define STR_CDROM_HELP L"Select ATAPI CDROM Drive #%02x" -#define STR_NET_HELP L"NET Drive #%02x" -#define STR_BEV_HELP L"BEV Drive #%02x" - -extern CHAR16 mFileExplorerStorageName[]; -extern CHAR16 mBootMaintStorageName[]; -// -// These are the VFR compiler generated data representing our VFR data. -// -extern UINT8 BmBin[]; -extern UINT8 FEBin[]; - -// -// Below are the number of options in Baudrate, Databits, -// Parity and Stopbits selection for serial ports. -// -#define BM_COM_ATTR_BUADRATE 19 -#define BM_COM_ATTR_DATABITS 4 -#define BM_COM_ATTR_PARITY 5 -#define BM_COM_ATTR_STOPBITS 3 - -// -// Callback function helper -// -#define BMM_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('C', 'b', 'c', 'k') -#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE) - -#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE) - -// -// Enumeration type definition -// -typedef enum _TYPE_OF_TERMINAL { - TerminalTypePcAnsi = 0, - TerminalTypeVt100, - TerminalTypeVt100Plus, - TerminalTypeVtUtf8 -} TYPE_OF_TERMINAL; - -typedef enum _FILE_EXPLORER_STATE { - FileExplorerStateInActive = 0, - FileExplorerStateBootFromFile, - FileExplorerStateAddBootOption, - FileExplorerStateAddDriverOptionState, - FileExplorerStateUnknown -} FILE_EXPLORER_STATE; - -typedef enum _FILE_EXPLORER_DISPLAY_CONTEXT { - FileExplorerDisplayFileSystem, - FileExplorerDisplayDirectory, - FileExplorerDisplayUnknown -} FILE_EXPLORER_DISPLAY_CONTEXT; - -// -// All of the signatures that will be used in list structure -// -#define BM_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u') -#define BM_LOAD_OPTION_SIGNATURE SIGNATURE_32 ('l', 'o', 'a', 'd') -#define BM_CONSOLE_OPTION_SIGNATURE SIGNATURE_32 ('c', 'n', 's', 'l') -#define BM_FILE_OPTION_SIGNATURE SIGNATURE_32 ('f', 'i', 'l', 'e') -#define BM_HANDLE_OPTION_SIGNATURE SIGNATURE_32 ('h', 'n', 'd', 'l') -#define BM_TERMINAL_OPTION_SIGNATURE SIGNATURE_32 ('t', 'r', 'm', 'l') -#define BM_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r') - -#define BM_LOAD_CONTEXT_SELECT 0x0 -#define BM_CONSOLE_CONTEXT_SELECT 0x1 -#define BM_FILE_CONTEXT_SELECT 0x2 -#define BM_HANDLE_CONTEXT_SELECT 0x3 -#define BM_TERMINAL_CONTEXT_SELECT 0x5 - -#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6 -#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7 -#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8 -#define BM_LEGACY_DEV_CONTEXT_SELECT 0x9 - -// -// Buffer size for update data -// -#define UPDATE_DATA_SIZE 0x100000 - -// -// Namespace of callback keys used in display and file system navigation -// -#define MAX_BBS_OFFSET 0xE000 -#define NET_OPTION_OFFSET 0xD800 -#define BEV_OPTION_OFFSET 0xD000 -#define FD_OPTION_OFFSET 0xC000 -#define HD_OPTION_OFFSET 0xB000 -#define CD_OPTION_OFFSET 0xA000 -#define FILE_OPTION_GOTO_OFFSET 0xC000 -#define FILE_OPTION_OFFSET 0x8000 -#define FILE_OPTION_MASK 0x3FFF -#define HANDLE_OPTION_OFFSET 0x7000 -#define CONSOLE_OPTION_OFFSET 0x6000 -#define TERMINAL_OPTION_OFFSET 0x5000 -#define CONFIG_OPTION_OFFSET 0x1200 -#define KEY_VALUE_OFFSET 0x1100 -#define FORM_ID_OFFSET 0x1000 - -// -// VarOffset that will be used to create question -// all these values are computed from the structure -// defined below -// -#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field))) - -// -// Question Id of Zero is invalid, so add an offset to it -// -#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET) - -#define BOOT_TIME_OUT_VAR_OFFSET VAR_OFFSET (BootTimeOut) -#define BOOT_NEXT_VAR_OFFSET VAR_OFFSET (BootNext) -#define COM1_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM1BaudRate) -#define COM1_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM1DataRate) -#define COM1_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM1StopBits) -#define COM1_PARITY_VAR_OFFSET VAR_OFFSET (COM1Parity) -#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType) -#define COM2_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM2BaudRate) -#define COM2_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM2DataRate) -#define COM2_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM2StopBits) -#define COM2_PARITY_VAR_OFFSET VAR_OFFSET (COM2Parity) -#define COM2_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType) -#define DRV_ADD_HANDLE_DESC_VAR_OFFSET VAR_OFFSET (DriverAddHandleDesc) -#define DRV_ADD_ACTIVE_VAR_OFFSET VAR_OFFSET (DriverAddActive) -#define DRV_ADD_RECON_VAR_OFFSET VAR_OFFSET (DriverAddForceReconnect) -#define CON_IN_COM1_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM1) -#define CON_IN_COM2_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM2) -#define CON_OUT_COM1_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM1) -#define CON_OUT_COM2_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM2) -#define CON_ERR_COM1_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM1) -#define CON_ERR_COM2_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM2) -#define CON_MODE_VAR_OFFSET VAR_OFFSET (ConsoleOutMode) -#define CON_IN_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleInCheck) -#define CON_OUT_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleOutCheck) -#define CON_ERR_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleErrCheck) -#define BOOT_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (BootOptionOrder) -#define DRIVER_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (DriverOptionOrder) -#define BOOT_OPTION_DEL_VAR_OFFSET VAR_OFFSET (BootOptionDel) -#define DRIVER_OPTION_DEL_VAR_OFFSET VAR_OFFSET (DriverOptionDel) -#define DRIVER_ADD_OPTION_VAR_OFFSET VAR_OFFSET (DriverAddHandleOptionalData) -#define COM_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COMBaudRate) -#define COM_DATA_RATE_VAR_OFFSET VAR_OFFSET (COMDataRate) -#define COM_STOP_BITS_VAR_OFFSET VAR_OFFSET (COMStopBits) -#define COM_PARITY_VAR_OFFSET VAR_OFFSET (COMParity) -#define COM_TERMINAL_VAR_OFFSET VAR_OFFSET (COMTerminalType) -#define COM_FLOWCONTROL_VAR_OFFSET VAR_OFFSET (COMFlowControl) -#define LEGACY_FD_VAR_OFFSET VAR_OFFSET (LegacyFD) -#define LEGACY_HD_VAR_OFFSET VAR_OFFSET (LegacyHD) -#define LEGACY_CD_VAR_OFFSET VAR_OFFSET (LegacyCD) -#define LEGACY_NET_VAR_OFFSET VAR_OFFSET (LegacyNET) -#define LEGACY_BEV_VAR_OFFSET VAR_OFFSET (LegacyBEV) - -#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut) -#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext) -#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate) -#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate) -#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits) -#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity) -#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) -#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate) -#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate) -#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits) -#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity) -#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) -#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc) -#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive) -#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect) -#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1) -#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2) -#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1) -#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2) -#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1) -#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2) -#define CON_MODE_QUESTION_ID QUESTION_ID (ConsoleOutMode) -#define CON_IN_DEVICE_QUESTION_ID QUESTION_ID (ConsoleInCheck) -#define CON_OUT_DEVICE_QUESTION_ID QUESTION_ID (ConsoleOutCheck) -#define CON_ERR_DEVICE_QUESTION_ID QUESTION_ID (ConsoleErrCheck) -#define BOOT_OPTION_ORDER_QUESTION_ID QUESTION_ID (BootOptionOrder) -#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionOrder) -#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel) -#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel) -#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData) -#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate) -#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate) -#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits) -#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity) -#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType) -#define COM_FLOWCONTROL_QUESTION_ID QUESTION_ID (COMFlowControl) -#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD) -#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD) -#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD) -#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET) -#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV) - -#define STRING_DEPOSITORY_NUMBER 8 - -/// -/// Serial Ports attributes, first one is the value for -/// return from callback function, stringtoken is used to -/// display the value properly -/// -typedef struct { - UINTN Value; - UINT16 StringToken; -} COM_ATTR; - -typedef struct { - UINT64 BaudRate; - UINT8 DataBits; - UINT8 Parity; - UINT8 StopBits; - - UINT8 BaudRateIndex; - UINT8 DataBitsIndex; - UINT8 ParityIndex; - UINT8 StopBitsIndex; - - UINT8 FlowControl; - - UINT8 IsConIn; - UINT8 IsConOut; - UINT8 IsStdErr; - UINT8 TerminalType; - - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} BM_TERMINAL_CONTEXT; - -typedef struct { - BOOLEAN IsBootNext; - BOOLEAN LoadOptionModified; - BOOLEAN Deleted; - - BOOLEAN IsLegacy; - BOOLEAN IsActive; - BOOLEAN ForceReconnect; - UINTN OptionalDataSize; - - UINTN LoadOptionSize; - UINT8 *LoadOption; - - UINT32 Attributes; - UINT16 FilePathListLength; - UINT16 *Description; - EFI_DEVICE_PATH_PROTOCOL *FilePathList; - UINT8 *OptionalData; - - UINT16 BbsIndex; -} BM_LOAD_CONTEXT; - -typedef struct { - BBS_TABLE *BbsEntry; - UINT16 BbsIndex; - UINT16 BbsCount; - CHAR16 *Description; -} BM_LEGACY_DEVICE_CONTEXT; - -typedef struct { - - BOOLEAN IsActive; - - BOOLEAN IsTerminal; - - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} BM_CONSOLE_CONTEXT; - -typedef struct { - UINTN Column; - UINTN Row; -} CONSOLE_OUT_MODE; - -typedef struct { - EFI_HANDLE Handle; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_FILE_HANDLE FHandle; - UINT16 *FileName; - EFI_FILE_SYSTEM_VOLUME_LABEL *Info; - - BOOLEAN IsRoot; - BOOLEAN IsDir; - BOOLEAN IsRemovableMedia; - BOOLEAN IsLoadFile; - BOOLEAN IsBootLegacy; -} BM_FILE_CONTEXT; - -typedef struct { - EFI_HANDLE Handle; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} BM_HANDLE_CONTEXT; - -typedef struct { - UINTN Signature; - LIST_ENTRY Head; - UINTN MenuNumber; -} BM_MENU_OPTION; - -typedef struct { - UINTN Signature; - LIST_ENTRY Link; - UINTN OptionNumber; - UINT16 *DisplayString; - UINT16 *HelpString; - EFI_STRING_ID DisplayStringToken; - EFI_STRING_ID HelpStringToken; - UINTN ContextSelection; - VOID *VariableContext; -} BM_MENU_ENTRY; - -typedef struct { - // - // Shared callback data. - // - UINTN Signature; - - BM_MENU_ENTRY *MenuEntry; - BM_HANDLE_CONTEXT *HandleContext; - BM_FILE_CONTEXT *FileContext; - BM_LOAD_CONTEXT *LoadContext; - BM_TERMINAL_CONTEXT *TerminalContext; - UINTN CurrentTerminal; - BBS_TYPE BbsType; - - // - // BMM main formset callback data. - // - EFI_HII_HANDLE BmmHiiHandle; - EFI_HANDLE BmmDriverHandle; - EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess; - EFI_FORM_ID BmmCurrentPageId; - EFI_FORM_ID BmmPreviousPageId; - BOOLEAN BmmAskSaveOrNot; - BMM_FAKE_NV_DATA BmmFakeNvData; - BMM_FAKE_NV_DATA BmmOldFakeNVData; - - // - // File explorer formset callback data. - // - EFI_HII_HANDLE FeHiiHandle; - EFI_HANDLE FeDriverHandle; - EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess; - FILE_EXPLORER_STATE FeCurrentState; - FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext; - FILE_EXPLORER_NV_DATA FeFakeNvData; -} BMM_CALLBACK_DATA; - -typedef struct _STRING_LIST_NODE STRING_LIST_NODE; - -struct _STRING_LIST_NODE { - EFI_STRING_ID StringToken; - STRING_LIST_NODE *Next; -}; - -typedef struct _STRING_DEPOSITORY { - UINTN TotalNodeNumber; - STRING_LIST_NODE *CurrentNode; - STRING_LIST_NODE *ListHead; -} STRING_DEPOSITORY; - -// -// #pragma pack() -// -// For initializing File System menu -// - -/** - This function build the FsOptionMenu list which records all - available file system in the system. They includes all instances - of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM - and all type of legacy boot device. - - @param CallbackData BMM context data - - @retval EFI_SUCCESS Success find the file system - @retval EFI_OUT_OF_RESOURCES Can not create menu entry - -**/ -EFI_STATUS -BOpt_FindFileSystem ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Find files under current directory - All files and sub-directories in current directory - will be stored in DirectoryMenu for future use. - - @param CallbackData The BMM context data. - @param MenuEntry The Menu Entry. - - @retval EFI_SUCCESS Get files from current dir successfully. - @return Other value if can't get files from current dir. - -**/ -EFI_STATUS -BOpt_FindFiles ( - IN BMM_CALLBACK_DATA *CallbackData, - IN BM_MENU_ENTRY *MenuEntry - ); - -/** - - Find drivers that will be added as Driver#### variables from handles - in current system environment - All valid handles in the system except those consume SimpleFs, LoadFile - are stored in DriverMenu for future use. - - @retval EFI_SUCCESS The function complets successfully. - @return Other value if failed to build the DriverMenu. - -**/ -EFI_STATUS -BOpt_FindDrivers ( - VOID - ); - -/** - - Build the BootOptionMenu according to BootOrder Variable. - This Routine will access the Boot#### to get EFI_LOAD_OPTION. - - @param CallbackData The BMM context data. - - @return The number of the Var Boot####. - -**/ -EFI_STATUS -BOpt_GetBootOptions ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - - Build up all DriverOptionMenu - - @param CallbackData The BMM context data. - - @return EFI_SUCESS The functin completes successfully. - @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation. - - -**/ -EFI_STATUS -BOpt_GetDriverOptions ( - IN BMM_CALLBACK_DATA *CallbackData - ); - - -/** - Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). - - @retval EFI_SUCCESS The function complete successfully. - @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function. - -**/ -EFI_STATUS -BOpt_GetLegacyOptions ( - VOID - ); - -/** - Free out resouce allocated from Legacy Boot Options. - -**/ -VOID -BOpt_FreeLegacyOptions ( - VOID - ); - -/** - Free resources allocated in Allocate Rountine. - - @param FreeMenu Menu to be freed - -**/ -VOID -BOpt_FreeMenu ( - BM_MENU_OPTION *FreeMenu - ); - - -/** - - Append file name to existing file name. - - @param Str1 The existing file name - @param Str2 The file name to be appended - - @return Allocate a new string to hold the appended result. - Caller is responsible to free the returned string. - -**/ -CHAR16* -BOpt_AppendFileName ( - IN CHAR16 *Str1, - IN CHAR16 *Str2 - ); - -/** - - Check whether current FileName point to a valid - Efi Image File. - - @param FileName File need to be checked. - - @retval TRUE Is Efi Image - @retval FALSE Not a valid Efi Image - -**/ -BOOLEAN -BOpt_IsEfiImageName ( - IN UINT16 *FileName - ); - -/** - - Check whether current FileName point to a valid Efi Application - - @param Dir Pointer to current Directory - @param FileName Pointer to current File name. - - @retval TRUE Is a valid Efi Application - @retval FALSE not a valid Efi Application - -**/ -BOOLEAN -BOpt_IsEfiApp ( - IN EFI_FILE_HANDLE Dir, - IN UINT16 *FileName - ); - -/** - - Get the Option Number that has not been allocated for use. - - @param Type The type of Option. - - @return The available Option Number. - -**/ -UINT16 -BOpt_GetOptionNumber ( - CHAR16 *Type - ); - -/** - - Get the Option Number for Boot#### that does not used. - - @return The available Option Number. - -**/ -UINT16 -BOpt_GetBootOptionNumber ( - VOID - ); - -/** - -Get the Option Number for Driver#### that does not used. - -@return The unused Option Number. - -**/ -UINT16 -BOpt_GetDriverOptionNumber ( - VOID - ); - -/** - Create a menu entry give a Menu type. - - @param MenuType The Menu type to be created. - - - @retval NULL If failed to create the menu. - @return The menu. - -**/ -BM_MENU_ENTRY * -BOpt_CreateMenuEntry ( - UINTN MenuType - ); - -/** - Free up all resource allocated for a BM_MENU_ENTRY. - - @param MenuEntry A pointer to BM_MENU_ENTRY. - -**/ -VOID -BOpt_DestroyMenuEntry ( - BM_MENU_ENTRY *MenuEntry - ); - -/** - Get the Menu Entry from the list in Menu Entry List. - - If MenuNumber is great or equal to the number of Menu - Entry in the list, then ASSERT. - - @param MenuOption The Menu Entry List to read the menu entry. - @param MenuNumber The index of Menu Entry. - - @return The Menu Entry. - -**/ -BM_MENU_ENTRY * -BOpt_GetMenuEntry ( - BM_MENU_OPTION *MenuOption, - UINTN MenuNumber - ); - -// -// Locate all serial io devices for console -// -/** - Build a list containing all serial devices. - - @retval EFI_SUCCESS The function complete successfully. - @retval EFI_UNSUPPORTED No serial ports present. - -**/ -EFI_STATUS -LocateSerialIo ( - VOID - ); - -// -// Initializing Console menu -// -/** - Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu - - @retval EFI_SUCCESS The function always complete successfully. - -**/ -EFI_STATUS -GetAllConsoles( - VOID - ); - -// -// Get current mode information -// -/** - Get mode number according to column and row - - @param CallbackData The BMM context data. -**/ -VOID -GetConsoleOutMode ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -// -// Cleaning up console menu -// -/** - Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu - - @retval EFI_SUCCESS The function always complete successfully. -**/ -EFI_STATUS -FreeAllConsoles ( - VOID - ); - -/** - Update the device path that describing a terminal device - based on the new BaudRate, Data Bits, parity and Stop Bits - set. - - @param DevicePath The devicepath protocol instance wanted to be updated. - -**/ -VOID -ChangeVariableDevicePath ( - IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath - ); - -/** - Update the multi-instance device path of Terminal Device based on - the global TerminalMenu. If ChangeTernimal is TRUE, the terminal - device path in the Terminal Device in TerminalMenu is also updated. - - @param DevicePath The multi-instance device path. - @param ChangeTerminal TRUE, then device path in the Terminal Device - in TerminalMenu is also updated; FALSE, no update. - - @return EFI_SUCCESS The function completes successfully. - -**/ -EFI_STATUS -ChangeTerminalDevicePath ( - IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, - IN BOOLEAN ChangeTerminal - ); - -// -// Variable operation by menu selection -// -/** - This function create a currently loaded Boot Option from - the BMM. It then appends this Boot Option to the end of - the "BootOrder" list. It also append this Boot Opotion to the end - of BootOptionMenu. - - @param CallbackData The BMM context data. - @param NvRamMap The file explorer formset internal state. - - @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. - @retval EFI_SUCCESS If function completes successfully. - -**/ -EFI_STATUS -Var_UpdateBootOption ( - IN BMM_CALLBACK_DATA *CallbackData, - IN FILE_EXPLORER_NV_DATA *NvRamMap - ); - -/** - Delete Boot Option that represent a Deleted state in BootOptionMenu. - After deleting this boot option, call Var_ChangeBootOrder to - make sure BootOrder is in valid state. - - @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to - BM_LOAD_CONTEXT marked for deletion is deleted - @return Others If failed to update the "BootOrder" variable after deletion. - -**/ -EFI_STATUS -Var_DelBootOption ( - VOID - ); - -/** - After any operation on Boot####, there will be a discrepancy in BootOrder. - Since some are missing but in BootOrder, while some are present but are - not reflected by BootOrder. Then a function rebuild BootOrder from - scratch by content from BootOptionMenu is needed. - - @retval EFI_SUCCESS The boot order is updated successfully. - @return other than EFI_SUCCESS if failed to change the "BootOrder" EFI Variable. - -**/ -EFI_STATUS -Var_ChangeBootOrder ( - VOID - ); - -/** - This function create a currently loaded Drive Option from - the BMM. It then appends this Driver Option to the end of - the "DriverOrder" list. It append this Driver Opotion to the end - of DriverOptionMenu. - - @param CallbackData The BMM context data. - @param HiiHandle The HII handle associated with the BMM formset. - @param DescriptionData The description of this driver option. - @param OptionalData The optional load option. - @param ForceReconnect If to force reconnect. - - @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. - @retval EFI_SUCCESS If function completes successfully. - -**/ -EFI_STATUS -Var_UpdateDriverOption ( - IN BMM_CALLBACK_DATA *CallbackData, - IN EFI_HII_HANDLE HiiHandle, - IN UINT16 *DescriptionData, - IN UINT16 *OptionalData, - IN UINT8 ForceReconnect - ); - -/** - Delete Load Option that represent a Deleted state in BootOptionMenu. - After deleting this Driver option, call Var_ChangeDriverOrder to - make sure DriverOrder is in valid state. - - @retval EFI_SUCCESS Load Option is successfully updated. - @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI - Variable. - -**/ -EFI_STATUS -Var_DelDriverOption ( - VOID - ); - -/** - After any operation on Driver####, there will be a discrepancy in - DriverOrder. Since some are missing but in DriverOrder, while some - are present but are not reflected by DriverOrder. Then a function - rebuild DriverOrder from scratch by content from DriverOptionMenu is - needed. - - @retval EFI_SUCCESS The driver order is updated successfully. - @return other than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable. - -**/ -EFI_STATUS -Var_ChangeDriverOrder ( - VOID - ); - -/** - This function delete and build multi-instance device path ConIn - console device. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. -**/ -EFI_STATUS -Var_UpdateConsoleInpOption ( - VOID - ); - -/** - This function delete and build multi-instance device path ConOut console device. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. -**/ -EFI_STATUS -Var_UpdateConsoleOutOption ( - VOID - ); - -/** - This function delete and build multi-instance device path ErrOut console device. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. -**/ -EFI_STATUS -Var_UpdateErrorOutOption ( - VOID - ); - -/** - Update the device path of "ConOut", "ConIn" and "ErrOut" based on the new BaudRate, Data Bits, - parity and stop Bits set. - -**/ -VOID -Var_UpdateAllConsoleOption ( - VOID - ); - -/** - This function update the "BootNext" EFI Variable. If there is no "BootNex" specified in BMM, - this EFI Variable is deleted. - It also update the BMM context data specified the "BootNext" value. - - @param CallbackData The BMM context data. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. - -**/ -EFI_STATUS -Var_UpdateBootNext ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - This function update the "BootOrder" EFI Variable based on BMM Formset's NV map. It then refresh - BootOptionMenu with the new "BootOrder" list. - - @param CallbackData The BMM context data. - - @retval EFI_SUCCESS The function complete successfully. - @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. - @return not The EFI variable can not be saved. See gRT->SetVariable for detail return information. - -**/ -EFI_STATUS -Var_UpdateBootOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - This function update the "DriverOrder" EFI Variable based on - BMM Formset's NV map. It then refresh DriverOptionMenu - with the new "DriverOrder" list. - - @param CallbackData The BMM context data. - - @retval EFI_SUCCESS The function complete successfully. - @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. - -**/ -EFI_STATUS -Var_UpdateDriverOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable - is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid - is also updated. - - @param CallbackData The context data for BMM. - @param FormId The form id. - - @return EFI_SUCCESS The function completed successfully. - @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can not be found. - -**/ -EFI_STATUS -Var_UpdateBBSOption ( - IN BMM_CALLBACK_DATA *CallbackData, - IN EFI_FORM_ID FormId - ); - -/** - Update the Text Mode of Console. - - @param CallbackData The context data for BMM. - - @retval EFI_SUCCSS If the Text Mode of Console is updated. - @return Other value if the Text Mode of Console is not updated. - -**/ -EFI_STATUS -Var_UpdateConMode ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -// -// Following are page create and refresh functions -// -/** - Refresh the global UpdateData structure. - -**/ -VOID -RefreshUpdateData ( - VOID - ); - -/** - Clean up the dynamic opcode at label and form specified by - both LabelId. - - @param LabelId It is both the Form ID and Label ID for - opcode deletion. - @param CallbackData The BMM context data. - -**/ -VOID -CleanUpPage ( - IN UINT16 LabelId, - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Create a lit of boot option from global BootOptionMenu. It - allow user to delete the boot option. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateBootDelPage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Create a lit of driver option from global DriverMenu. - - @param CallbackData The BMM context data. -**/ -VOID -UpdateDrvAddHandlePage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Create a lit of driver option from global DriverOptionMenu. It - allow user to delete the driver option. - - @param CallbackData The BMM context data. -**/ -VOID -UpdateDrvDelPage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Prepare the page to allow user to add description for a Driver Option. - - @param CallbackData The BMM context data. -**/ -VOID -UpdateDriverAddHandleDescPage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Dispatch the correct update page function to call based on the UpdatePageId. - - @param UpdatePageId The form ID. - @param CallbackData The BMM context data. -**/ -VOID -UpdatePageBody ( - IN UINT16 UpdatePageId, - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Create the dynamic page to allow user to set the "BootNext" vaule. - - @param CallbackData The BMM context data. -**/ -VOID -UpdateBootNextPage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Create the dynamic page to allow user to set the "TimeOut" vaule. - - @param CallbackData The BMM context data. -**/ -VOID -UpdateTimeOutPage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits, - Parity, Stop Bits, Terminal Type. - - @param CallbackData The BMM context data. -**/ -VOID -UpdateTerminalPage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Refresh the text mode page - - @param CallbackData The BMM context data. -**/ -VOID -UpdateConModePage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Create a list of Goto Opcode for all terminal devices logged - by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID. - - @param CallbackData The BMM context data. -**/ -VOID -UpdateConCOMPage ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Create a dynamic page so that Legacy Device boot order - can be set for specified device type. - - @param UpdatePageId The form ID. It also spefies the legacy device type. - @param CallbackData The BMM context data. -**/ -VOID -UpdateSetLegacyDeviceOrderPage ( - IN UINT16 UpdatePageId, - IN BMM_CALLBACK_DATA *CallbackData - ); - - -/** - Function opens and returns a file handle to the root directory of a volume. - - @param DeviceHandle A handle for a device - @return A valid file handle or NULL is returned -**/ -EFI_FILE_HANDLE -EfiLibOpenRoot ( - IN EFI_HANDLE DeviceHandle - ); - -/** - Function gets the file system information from an open file descriptor, - and stores it in a buffer allocated from pool. - - @param FHand The file handle. - - @return A pointer to a buffer with file information. - NULL is returned if failed to get Vaolume Label Info. -**/ -EFI_FILE_SYSTEM_VOLUME_LABEL * -EfiLibFileSystemVolumeLabelInfo ( - IN EFI_FILE_HANDLE FHand - ); - -/** - - Function gets the file information from an open file descriptor, and stores it - in a buffer allocated from pool. - - @param FHand File Handle. - - @return A pointer to a buffer with file information or NULL is returned - -**/ -EFI_FILE_INFO * -EfiLibFileInfo ( - IN EFI_FILE_HANDLE FHand - ); - -/** - Adjusts the size of a previously allocated buffer. - - @param OldPool A pointer to the buffer whose size is being adjusted. - @param OldSize The size of the current buffer. - @param NewSize The size of the new buffer. - - @return The newly allocated buffer. if NULL, allocation failed. - -**/ -VOID* -EfiReallocatePool ( - IN VOID *OldPool, - IN UINTN OldSize, - IN UINTN NewSize - ); - -/** - Function deletes the variable specified by VarName and VarGuid. - - - @param VarName A Null-terminated Unicode string that is - the name of the vendor's variable. - - @param VarGuid A unique identifier for the vendor. - - @retval EFI_SUCCESS The variable was found and removed - @retval EFI_UNSUPPORTED The variable store was inaccessible - @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available - @retval EFI_NOT_FOUND The variable was not found - -**/ -EFI_STATUS -EfiLibDeleteVariable ( - IN CHAR16 *VarName, - IN EFI_GUID *VarGuid - ); - -/** - Duplicate a string. - - @param Src The source. - - @return A new string which is duplicated copy of the source. - @retval NULL If there is not enough memory. - -**/ -CHAR16 * -EfiStrDuplicate ( - IN CHAR16 *Src - ); - -/** - Function is used to determine the number of device path instances - that exist in a device path. - - - @param DevicePath A pointer to a device path data structure. - - @return This function counts and returns the number of device path instances - in DevicePath. - -**/ -UINTN -EfiDevicePathInstanceCount ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ); - -/** - Create string tokens for a menu from its help strings and display strings - - - @param CallbackData The BMM context data. - @param HiiHandle Hii Handle of the package to be updated. - @param MenuOption The Menu whose string tokens need to be created - - @retval EFI_SUCCESS string tokens created successfully - @retval others contain some errors - -**/ -EFI_STATUS -CreateMenuStringToken ( - IN BMM_CALLBACK_DATA *CallbackData, - IN EFI_HII_HANDLE HiiHandle, - IN BM_MENU_OPTION *MenuOption - ); - -/** - Get a string from the Data Hub record based on - a device path. - - @param DevPath The device Path. - - @return A string located from the Data Hub records based on - the device path. - @retval NULL If failed to get the String from Data Hub. - -**/ -UINT16 * -EfiLibStrFromDatahub ( - IN EFI_DEVICE_PATH_PROTOCOL *DevPath - ); - -/** - Initialize the Boot Maintenance Utitliy. - - @retval EFI_SUCCESS utility ended successfully. - @retval others contain some errors. - -**/ -EFI_STATUS -InitializeBM ( - VOID - ); - -/** - Start boot maintenance manager - - @retval EFI_SUCCESS If BMM is invoked successfully. - @return Other value if BMM return unsuccessfully. - -**/ -EFI_STATUS -BdsStartBootMaint ( - VOID - ); - -/** - Intialize all the string depositories. - -**/ -VOID -InitializeStringDepository ( - VOID - ); - -/** - Fetch a usable string node from the string depository and return the string token. - - - @param CallbackData The BMM context data. - @param StringDepository Pointer of the string depository. - - @retval EFI_STRING_ID String token. - -**/ -EFI_STRING_ID -GetStringTokenFromDepository ( - IN BMM_CALLBACK_DATA *CallbackData, - IN STRING_DEPOSITORY *StringDepository - ); - -/** - Reclaim string depositories by moving the current node pointer to list head.. -**/ -VOID -ReclaimStringDepository ( - VOID - ); - -/** - Release resource for all the string depositories. - -**/ -VOID -CleanUpStringDepository ( - VOID - ); - -/** - Function handling request to apply changes for BMM pages. - - @param Private Pointer to callback data buffer. - @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM - @param FormId ID of the form which has sent the request to apply change. - - @retval EFI_SUCCESS Change successfully applied. - @retval Other Error occurs while trying to apply changes. - -**/ -EFI_STATUS -ApplyChangeHandler ( - IN BMM_CALLBACK_DATA *Private, - IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, - IN EFI_FORM_ID FormId - ); - -/** - Discard all changes done to the BMM pages such as Boot Order change, - Driver order change. - - @param Private The BMM context data. - @param CurrentFakeNVMap The current Fack NV Map. - -**/ -VOID -DiscardChangeHandler ( - IN BMM_CALLBACK_DATA *Private, - IN BMM_FAKE_NV_DATA *CurrentFakeNVMap - ); - -/** - Dispatch the display to the next page based on NewPageId. - - @param Private The BMM context data. - @param NewPageId The original page ID. - -**/ -VOID -UpdatePageId ( - BMM_CALLBACK_DATA *Private, - UINT16 NewPageId - ); - -/** - Boot a file selected by user at File Expoloer of BMM. - - @param FileContext The file context data, which contains the device path - of the file to be boot from. - - @retval EFI_SUCCESS The function completed successfull. - @return Other value if the boot from the file fails. - -**/ -EFI_STATUS -BootThisFile ( - IN BM_FILE_CONTEXT *FileContext - ); - -/** - Update the file explower page with the refershed file system. - - - @param CallbackData BMM context data - @param KeyValue Key value to identify the type of data to expect. - - @retval TRUE Inform the caller to create a callback packet to exit file explorer. - @retval FALSE Indicate that there is no need to exit file explorer. - -**/ -BOOLEAN -UpdateFileExplorer ( - IN BMM_CALLBACK_DATA *CallbackData, - IN UINT16 KeyValue - ); - -/** - This function processes the results of changes in configuration. - When user select a interactive opcode, this callback will be triggered. - Based on the Question(QuestionId) that triggers the callback, the corresponding - actions is performed. It handles: - - 1) the addition of boot option. - 2) the addition of driver option. - 3) exit from file browser - 4) update of file content if a dir is selected. - 5) boot the file if a file is selected in "boot from file" - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be saved. - @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. - -**/ -EFI_STATUS -EFIAPI -FileExplorerCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ); - -/** - This function applies changes in a driver's configuration. - Input is a Configuration, which has the routing data for this - driver followed by name / value configuration pairs. The driver - must apply those pairs to its configurable storage. If the - driver's configuration is stored in a linear block of data - and the driver's name / value pairs are in - format, it may use the ConfigToBlock helper function (above) to - simplify the job. Currently not implemented. - - @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param[in] Configuration A null-terminated Unicode string in - format. - @param[out] Progress A pointer to a string filled in with the - offset of the most recent '&' before the - first failing name / value pair (or the - beginn ing 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 have been distributed or are - awaiting distribution. - @retval EFI_OUT_OF_RESOURCES Not enough memory to store the - parts of the results that must be - stored awaiting possible future - protocols. - @retval EFI_INVALID_PARAMETERS Passing in a NULL for the - Results parameter would result - in this type of error. - @retval EFI_NOT_FOUND Target for the specified routing data - was not found. -**/ -EFI_STATUS -EFIAPI -FileExplorerRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ); - -/** - Dispatch BMM formset and FileExplorer formset. - - - @param CallbackData The BMM context data. - - @retval EFI_SUCCESS If function complete successfully. - @return Other value if the Setup Browser process BMM's pages and - return unsuccessfully. - -**/ -EFI_STATUS -FormSetDispatcher ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Function returns the value of the specified variable. - - @param Name A Null-terminated Unicode string that is - the name of the vendor's variable. - @param VendorGuid A unique identifier for the vendor. - - @return The payload of the variable. - @retval NULL If the variable can't be read. - -**/ -VOID * -EfiLibGetVariable ( - IN CHAR16 *Name, - IN EFI_GUID *VendorGuid - ); - -/** - Get option number according to Boot#### and BootOrder variable. - The value is saved as #### + 1. - - @param CallbackData The BMM context data. -**/ -VOID -GetBootOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Get driver option order from globalc DriverOptionMenu. - - @param CallbackData The BMM context data. - -**/ -VOID -GetDriverOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - Intall BootMaint and FileExplorer HiiPackages. - -**/ -EFI_STATUS -InitBMPackage ( - VOID - ); - -/** - Remvoe the intalled BootMaint and FileExplorer HiiPackages. - -**/ -VOID -FreeBMPackage ( - VOID - ); - -/** - According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV - devices list . - - @param CallbackData The BMM context data. -**/ -VOID -GetLegacyDeviceOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - - Initialize console input device check box to ConsoleInCheck[MAX_MENU_NUMBER] - in BMM_FAKE_NV_DATA structure. - - @param CallbackData The BMM context data. - -**/ -VOID -GetConsoleInCheck ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - - Initialize console output device check box to ConsoleOutCheck[MAX_MENU_NUMBER] - in BMM_FAKE_NV_DATA structure. - - @param CallbackData The BMM context data. - -**/ -VOID -GetConsoleOutCheck ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - - Initialize standard error output device check box to ConsoleErrCheck[MAX_MENU_NUMBER] - in BMM_FAKE_NV_DATA structure. - - @param CallbackData The BMM context data. - -**/ -VOID -GetConsoleErrCheck ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - - Initialize terminal attributes (baudrate, data rate, stop bits, parity and terminal type) - to BMM_FAKE_NV_DATA structure. - - @param CallbackData The BMM context data. - -**/ -VOID -GetTerminalAttribute ( - IN BMM_CALLBACK_DATA *CallbackData - ); - -/** - - Find the first instance of this Protocol - in the system and return it's interface. - - - @param ProtocolGuid Provides the protocol to search for - @param Interface On return, a pointer to the first interface - that matches ProtocolGuid - - @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found - @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid - -**/ -EFI_STATUS -EfiLibLocateProtocol ( - IN EFI_GUID *ProtocolGuid, - OUT VOID **Interface - ); - -// -// Global variable in this program (defined in data.c) -// -extern BM_MENU_OPTION BootOptionMenu; -extern BM_MENU_OPTION DriverOptionMenu; -extern BM_MENU_OPTION FsOptionMenu; -extern BM_MENU_OPTION ConsoleInpMenu; -extern BM_MENU_OPTION ConsoleOutMenu; -extern BM_MENU_OPTION ConsoleErrMenu; -extern BM_MENU_OPTION DirectoryMenu; -extern BM_MENU_OPTION DriverMenu; -extern BM_MENU_OPTION TerminalMenu; -extern BM_MENU_OPTION LegacyFDMenu; -extern BM_MENU_OPTION LegacyHDMenu; -extern BM_MENU_OPTION LegacyCDMenu; -extern BM_MENU_OPTION LegacyNETMenu; -extern BM_MENU_OPTION LegacyBEVMenu; -extern UINT16 TerminalType[]; -extern COM_ATTR BaudRateList[19]; -extern COM_ATTR DataBitsList[4]; -extern COM_ATTR ParityList[5]; -extern COM_ATTR StopBitsList[3]; -extern EFI_GUID TerminalTypeGuid[4]; -extern STRING_DEPOSITORY *FileOptionStrDepository; -extern STRING_DEPOSITORY *ConsoleOptionStrDepository; -extern STRING_DEPOSITORY *BootOptionStrDepository; -extern STRING_DEPOSITORY *BootOptionHelpStrDepository; -extern STRING_DEPOSITORY *DriverOptionStrDepository; -extern STRING_DEPOSITORY *DriverOptionHelpStrDepository; -extern STRING_DEPOSITORY *TerminalStrDepository; -extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[]; -extern UINT16 mFlowControlType[2]; -extern UINT32 mFlowControlValue[2]; -// -// Shared IFR form update data -// -extern VOID *mStartOpCodeHandle; -extern VOID *mEndOpCodeHandle; -extern EFI_IFR_GUID_LABEL *mStartLabel; -extern EFI_IFR_GUID_LABEL *mEndLabel; - -#endif diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c deleted file mode 100644 index 56bcfab23f..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c +++ /dev/null @@ -1,1823 +0,0 @@ -/** @file - Provide boot option support for Application "BootMaint" - - Include file system navigation, system handle selection - - Boot option manipulation - -Copyright (c) 2004 - 2015, Intel 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 "BootMaint.h" -#include "BBSsupport.h" - -/** - Create a menu entry by given menu type. - - @param MenuType The Menu type to be created. - - @retval NULL If failed to create the menu. - @return the new menu entry. - -**/ -BM_MENU_ENTRY * -BOpt_CreateMenuEntry ( - UINTN MenuType - ) -{ - BM_MENU_ENTRY *MenuEntry; - UINTN ContextSize; - - // - // Get context size according to menu type - // - switch (MenuType) { - case BM_LOAD_CONTEXT_SELECT: - ContextSize = sizeof (BM_LOAD_CONTEXT); - break; - - case BM_FILE_CONTEXT_SELECT: - ContextSize = sizeof (BM_FILE_CONTEXT); - break; - - case BM_CONSOLE_CONTEXT_SELECT: - ContextSize = sizeof (BM_CONSOLE_CONTEXT); - break; - - case BM_TERMINAL_CONTEXT_SELECT: - ContextSize = sizeof (BM_TERMINAL_CONTEXT); - break; - - case BM_HANDLE_CONTEXT_SELECT: - ContextSize = sizeof (BM_HANDLE_CONTEXT); - break; - - case BM_LEGACY_DEV_CONTEXT_SELECT: - ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT); - break; - - default: - ContextSize = 0; - break; - } - - if (ContextSize == 0) { - return NULL; - } - - // - // Create new menu entry - // - MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY)); - if (MenuEntry == NULL) { - return NULL; - } - - MenuEntry->VariableContext = AllocateZeroPool (ContextSize); - if (MenuEntry->VariableContext == NULL) { - FreePool (MenuEntry); - return NULL; - } - - MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE; - MenuEntry->ContextSelection = MenuType; - return MenuEntry; -} - -/** - Free up all resource allocated for a BM_MENU_ENTRY. - - @param MenuEntry A pointer to BM_MENU_ENTRY. - -**/ -VOID -BOpt_DestroyMenuEntry ( - BM_MENU_ENTRY *MenuEntry - ) -{ - BM_LOAD_CONTEXT *LoadContext; - BM_FILE_CONTEXT *FileContext; - BM_CONSOLE_CONTEXT *ConsoleContext; - BM_TERMINAL_CONTEXT *TerminalContext; - BM_HANDLE_CONTEXT *HandleContext; - BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext; - - // - // Select by the type in Menu entry for current context type - // - switch (MenuEntry->ContextSelection) { - case BM_LOAD_CONTEXT_SELECT: - LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext; - FreePool (LoadContext->FilePathList); - FreePool (LoadContext->LoadOption); - if (LoadContext->OptionalData != NULL) { - FreePool (LoadContext->OptionalData); - } - FreePool (LoadContext); - break; - - case BM_FILE_CONTEXT_SELECT: - FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; - - if (!FileContext->IsRoot) { - FreePool (FileContext->DevicePath); - } else { - if (FileContext->FHandle != NULL) { - FileContext->FHandle->Close (FileContext->FHandle); - } - } - - if (FileContext->FileName != NULL) { - FreePool (FileContext->FileName); - } - if (FileContext->Info != NULL) { - FreePool (FileContext->Info); - } - FreePool (FileContext); - break; - - case BM_CONSOLE_CONTEXT_SELECT: - ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext; - FreePool (ConsoleContext->DevicePath); - FreePool (ConsoleContext); - break; - - case BM_TERMINAL_CONTEXT_SELECT: - TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext; - FreePool (TerminalContext->DevicePath); - FreePool (TerminalContext); - break; - - case BM_HANDLE_CONTEXT_SELECT: - HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext; - FreePool (HandleContext); - break; - - case BM_LEGACY_DEV_CONTEXT_SELECT: - LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext; - FreePool (LegacyDevContext); - - default: - break; - } - - FreePool (MenuEntry->DisplayString); - if (MenuEntry->HelpString != NULL) { - FreePool (MenuEntry->HelpString); - } - - FreePool (MenuEntry); -} - -/** - Get the Menu Entry from the list in Menu Entry List. - - If MenuNumber is great or equal to the number of Menu - Entry in the list, then ASSERT. - - @param MenuOption The Menu Entry List to read the menu entry. - @param MenuNumber The index of Menu Entry. - - @return The Menu Entry. - -**/ -BM_MENU_ENTRY * -BOpt_GetMenuEntry ( - BM_MENU_OPTION *MenuOption, - UINTN MenuNumber - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - UINTN Index; - LIST_ENTRY *List; - - ASSERT (MenuNumber < MenuOption->MenuNumber); - - List = MenuOption->Head.ForwardLink; - for (Index = 0; Index < MenuNumber; Index++) { - List = List->ForwardLink; - } - - NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE); - - return NewMenuEntry; -} - -/** - This function build the FsOptionMenu list which records all - available file system in the system. They includes all instances - of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM - and all type of legacy boot device. - - @param CallbackData BMM context data - - @retval EFI_SUCCESS Success find the file system - @retval EFI_OUT_OF_RESOURCES Can not create menu entry - -**/ -EFI_STATUS -BOpt_FindFileSystem ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINTN NoBlkIoHandles; - UINTN NoSimpleFsHandles; - UINTN NoLoadFileHandles; - EFI_HANDLE *BlkIoHandle; - EFI_HANDLE *SimpleFsHandle; - EFI_HANDLE *LoadFileHandle; - UINT16 *VolumeLabel; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - UINTN Index; - EFI_STATUS Status; - BM_MENU_ENTRY *MenuEntry; - BM_FILE_CONTEXT *FileContext; - UINT16 *TempStr; - UINTN OptionNumber; - VOID *Buffer; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - UINT16 DeviceType; - BBS_BBS_DEVICE_PATH BbsDevicePathNode; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - BOOLEAN RemovableMedia; - - - NoSimpleFsHandles = 0; - NoLoadFileHandles = 0; - OptionNumber = 0; - InitializeListHead (&FsOptionMenu.Head); - - // - // Locate Handles that support BlockIo protocol - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiBlockIoProtocolGuid, - NULL, - &NoBlkIoHandles, - &BlkIoHandle - ); - if (!EFI_ERROR (Status)) { - - for (Index = 0; Index < NoBlkIoHandles; Index++) { - Status = gBS->HandleProtocol ( - BlkIoHandle[Index], - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo - ); - - if (EFI_ERROR (Status)) { - continue; - } - - // - // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media - // - if (BlkIo->Media->RemovableMedia) { - Buffer = AllocateZeroPool (BlkIo->Media->BlockSize); - if (NULL == Buffer) { - FreePool (BlkIoHandle); - return EFI_OUT_OF_RESOURCES; - } - - BlkIo->ReadBlocks ( - BlkIo, - BlkIo->Media->MediaId, - 0, - BlkIo->Media->BlockSize, - Buffer - ); - FreePool (Buffer); - } - } - FreePool (BlkIoHandle); - } - - // - // Locate Handles that support Simple File System protocol - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiSimpleFileSystemProtocolGuid, - NULL, - &NoSimpleFsHandles, - &SimpleFsHandle - ); - if (!EFI_ERROR (Status)) { - // - // Find all the instances of the File System prototocol - // - for (Index = 0; Index < NoSimpleFsHandles; Index++) { - Status = gBS->HandleProtocol ( - SimpleFsHandle[Index], - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo - ); - if (EFI_ERROR (Status)) { - // - // If no block IO exists assume it's NOT a removable media - // - RemovableMedia = FALSE; - } else { - // - // If block IO exists check to see if it's remobable media - // - RemovableMedia = BlkIo->Media->RemovableMedia; - } - - // - // Allocate pool for this load option - // - MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); - if (NULL == MenuEntry) { - FreePool (SimpleFsHandle); - return EFI_OUT_OF_RESOURCES; - } - - FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; - - FileContext->Handle = SimpleFsHandle[Index]; - MenuEntry->OptionNumber = Index; - FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle); - if (FileContext->FHandle == NULL) { - BOpt_DestroyMenuEntry (MenuEntry); - continue; - } - - MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle)); - FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle); - FileContext->FileName = EfiStrDuplicate (L"\\"); - FileContext->DevicePath = FileDevicePath ( - FileContext->Handle, - FileContext->FileName - ); - FileContext->IsDir = TRUE; - FileContext->IsRoot = TRUE; - FileContext->IsRemovableMedia = RemovableMedia; - FileContext->IsLoadFile = FALSE; - - // - // Get current file system's Volume Label - // - if (FileContext->Info == NULL) { - VolumeLabel = L"NO FILE SYSTEM INFO"; - } else { - VolumeLabel = FileContext->Info->VolumeLabel; - if (*VolumeLabel == 0x0000) { - VolumeLabel = L"NO VOLUME LABEL"; - } - } - - TempStr = MenuEntry->HelpString; - MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); - ASSERT (MenuEntry->DisplayString != NULL); - UnicodeSPrint ( - MenuEntry->DisplayString, - MAX_CHAR, - L"%s, [%s]", - VolumeLabel, - TempStr - ); - OptionNumber++; - InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); - } - } - - if (NoSimpleFsHandles != 0) { - FreePool (SimpleFsHandle); - } - // - // Searching for handles that support Load File protocol - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiLoadFileProtocolGuid, - NULL, - &NoLoadFileHandles, - &LoadFileHandle - ); - - if (!EFI_ERROR (Status)) { - for (Index = 0; Index < NoLoadFileHandles; Index++) { - MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); - if (NULL == MenuEntry) { - FreePool (LoadFileHandle); - return EFI_OUT_OF_RESOURCES; - } - - FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; - FileContext->IsRemovableMedia = FALSE; - FileContext->IsLoadFile = TRUE; - FileContext->Handle = LoadFileHandle[Index]; - FileContext->IsRoot = TRUE; - - FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle); - FileContext->FileName = DevicePathToStr (FileContext->DevicePath); - - MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); - - TempStr = MenuEntry->HelpString; - MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); - ASSERT (MenuEntry->DisplayString != NULL); - UnicodeSPrint ( - MenuEntry->DisplayString, - MAX_CHAR, - L"Load File [%s]", - TempStr - ); - - MenuEntry->OptionNumber = OptionNumber; - OptionNumber++; - InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); - } - } - - if (NoLoadFileHandles != 0) { - FreePool (LoadFileHandle); - } - - // - // Add Legacy Boot Option Support Here - // - Status = gBS->LocateProtocol ( - &gEfiLegacyBiosProtocolGuid, - NULL, - (VOID **) &LegacyBios - ); - if (!EFI_ERROR (Status)) { - - for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) { - MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); - if (NULL == MenuEntry) { - return EFI_OUT_OF_RESOURCES; - } - - FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; - - FileContext->IsRemovableMedia = FALSE; - FileContext->IsLoadFile = TRUE; - FileContext->IsBootLegacy = TRUE; - DeviceType = (UINT16) Index; - BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH; - BbsDevicePathNode.Header.SubType = BBS_BBS_DP; - SetDevicePathNodeLength ( - &BbsDevicePathNode.Header, - sizeof (BBS_BBS_DEVICE_PATH) - ); - BbsDevicePathNode.DeviceType = DeviceType; - BbsDevicePathNode.StatusFlag = 0; - BbsDevicePathNode.String[0] = 0; - DevicePath = AppendDevicePathNode ( - EndDevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode - ); - - FileContext->DevicePath = DevicePath; - MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); - - TempStr = MenuEntry->HelpString; - MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); - ASSERT (MenuEntry->DisplayString != NULL); - UnicodeSPrint ( - MenuEntry->DisplayString, - MAX_CHAR, - L"Boot Legacy [%s]", - TempStr - ); - MenuEntry->OptionNumber = OptionNumber; - OptionNumber++; - InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); - } - } - // - // Remember how many file system options are here - // - FsOptionMenu.MenuNumber = OptionNumber; - return EFI_SUCCESS; -} - -/** - Free resources allocated in Allocate Rountine. - - @param FreeMenu Menu to be freed -**/ -VOID -BOpt_FreeMenu ( - BM_MENU_OPTION *FreeMenu - ) -{ - BM_MENU_ENTRY *MenuEntry; - while (!IsListEmpty (&FreeMenu->Head)) { - MenuEntry = CR ( - FreeMenu->Head.ForwardLink, - BM_MENU_ENTRY, - Link, - BM_MENU_ENTRY_SIGNATURE - ); - RemoveEntryList (&MenuEntry->Link); - BOpt_DestroyMenuEntry (MenuEntry); - } - FreeMenu->MenuNumber = 0; -} - -/** - Find files under current directory - All files and sub-directories in current directory - will be stored in DirectoryMenu for future use. - - @param CallbackData The BMM context data. - @param MenuEntry The Menu Entry. - - @retval EFI_SUCCESS Get files from current dir successfully. - @return Other value if can't get files from current dir. - -**/ -EFI_STATUS -BOpt_FindFiles ( - IN BMM_CALLBACK_DATA *CallbackData, - IN BM_MENU_ENTRY *MenuEntry - ) -{ - EFI_FILE_HANDLE NewDir; - EFI_FILE_HANDLE Dir; - EFI_FILE_INFO *DirInfo; - UINTN BufferSize; - UINTN DirBufferSize; - BM_MENU_ENTRY *NewMenuEntry; - BM_FILE_CONTEXT *FileContext; - BM_FILE_CONTEXT *NewFileContext; - UINTN Pass; - EFI_STATUS Status; - UINTN OptionNumber; - - FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; - Dir = FileContext->FHandle; - OptionNumber = 0; - // - // Open current directory to get files from it - // - Status = Dir->Open ( - Dir, - &NewDir, - FileContext->FileName, - EFI_FILE_READ_ONLY, - 0 - ); - if (!FileContext->IsRoot) { - Dir->Close (Dir); - } - - if (EFI_ERROR (Status)) { - return Status; - } - - DirInfo = EfiLibFileInfo (NewDir); - if (DirInfo == NULL) { - return EFI_NOT_FOUND; - } - - if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { - return EFI_INVALID_PARAMETER; - } - - FileContext->DevicePath = FileDevicePath ( - FileContext->Handle, - FileContext->FileName - ); - - DirBufferSize = sizeof (EFI_FILE_INFO) + 1024; - DirInfo = AllocateZeroPool (DirBufferSize); - if (DirInfo == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // Get all files in current directory - // Pass 1 to get Directories - // Pass 2 to get files that are EFI images - // - for (Pass = 1; Pass <= 2; Pass++) { - NewDir->SetPosition (NewDir, 0); - for (;;) { - BufferSize = DirBufferSize; - Status = NewDir->Read (NewDir, &BufferSize, DirInfo); - if (EFI_ERROR (Status) || BufferSize == 0) { - break; - } - - if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) || - ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1) - ) { - // - // Pass 1 is for Directories - // Pass 2 is for file names - // - continue; - } - - if (!(BOpt_IsEfiImageName (DirInfo->FileName) || (DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0)) { - // - // Slip file unless it is a directory entry or a .EFI file - // - continue; - } - - NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); - if (NULL == NewMenuEntry) { - return EFI_OUT_OF_RESOURCES; - } - - NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; - NewFileContext->Handle = FileContext->Handle; - NewFileContext->FileName = BOpt_AppendFileName ( - FileContext->FileName, - DirInfo->FileName - ); - NewFileContext->FHandle = NewDir; - NewFileContext->DevicePath = FileDevicePath ( - NewFileContext->Handle, - NewFileContext->FileName - ); - NewMenuEntry->HelpString = NULL; - - MenuEntry->DisplayStringToken = GetStringTokenFromDepository ( - CallbackData, - FileOptionStrDepository - ); - - NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY); - - if (NewFileContext->IsDir) { - BufferSize = StrLen (DirInfo->FileName) * 2 + 6; - NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize); - - UnicodeSPrint ( - NewMenuEntry->DisplayString, - BufferSize, - L"<%s>", - DirInfo->FileName - ); - - } else { - NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName); - } - - NewFileContext->IsRoot = FALSE; - NewFileContext->IsLoadFile = FALSE; - NewFileContext->IsRemovableMedia = FALSE; - - NewMenuEntry->OptionNumber = OptionNumber; - OptionNumber++; - InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link); - } - } - - DirectoryMenu.MenuNumber = OptionNumber; - FreePool (DirInfo); - return EFI_SUCCESS; -} - -/** - Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). - - @retval EFI_SUCCESS The function complete successfully. - @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function. - -**/ -EFI_STATUS -BOpt_GetLegacyOptions ( - VOID - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; - EFI_STATUS Status; - EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - UINT16 HddCount; - HDD_INFO *HddInfo; - UINT16 BbsCount; - BBS_TABLE *BbsTable; - UINT16 Index; - CHAR16 DescString[100]; - UINTN FDNum; - UINTN HDNum; - UINTN CDNum; - UINTN NETNum; - UINTN BEVNum; - - NewMenuEntry = NULL; - HddInfo = NULL; - BbsTable = NULL; - BbsCount = 0; - - // - // Initialize Bbs Table Context from BBS info data - // - InitializeListHead (&LegacyFDMenu.Head); - InitializeListHead (&LegacyHDMenu.Head); - InitializeListHead (&LegacyCDMenu.Head); - InitializeListHead (&LegacyNETMenu.Head); - InitializeListHead (&LegacyBEVMenu.Head); - - Status = gBS->LocateProtocol ( - &gEfiLegacyBiosProtocolGuid, - NULL, - (VOID **) &LegacyBios - ); - if (!EFI_ERROR (Status)) { - Status = LegacyBios->GetBbsInfo ( - LegacyBios, - &HddCount, - &HddInfo, - &BbsCount, - &BbsTable - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - - FDNum = 0; - HDNum = 0; - CDNum = 0; - NETNum = 0; - BEVNum = 0; - - for (Index = 0; Index < BbsCount; Index++) { - if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) || - (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority) - ) { - continue; - } - - NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT); - if (NULL == NewMenuEntry) { - break; - } - - NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; - NewLegacyDevContext->BbsEntry = &BbsTable[Index]; - NewLegacyDevContext->BbsIndex = Index; - NewLegacyDevContext->BbsCount = BbsCount; - BdsBuildLegacyDevNameString ( - &BbsTable[Index], - Index, - sizeof (DescString), - DescString - ); - NewLegacyDevContext->Description = AllocateCopyPool (StrSize (DescString), DescString); - if (NULL == NewLegacyDevContext->Description) { - break; - } - - NewMenuEntry->DisplayString = NewLegacyDevContext->Description; - NewMenuEntry->HelpString = NULL; - - switch (BbsTable[Index].DeviceType) { - case BBS_FLOPPY: - InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); - FDNum++; - break; - - case BBS_HARDDISK: - InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); - HDNum++; - break; - - case BBS_CDROM: - InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); - CDNum++; - break; - - case BBS_EMBED_NETWORK: - InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); - NETNum++; - break; - - case BBS_BEV_DEVICE: - InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); - BEVNum++; - break; - } - } - - if (Index != BbsCount) { - BOpt_FreeLegacyOptions (); - return EFI_OUT_OF_RESOURCES; - } - - LegacyFDMenu.MenuNumber = FDNum; - LegacyHDMenu.MenuNumber = HDNum; - LegacyCDMenu.MenuNumber = CDNum; - LegacyNETMenu.MenuNumber = NETNum; - LegacyBEVMenu.MenuNumber = BEVNum; - return EFI_SUCCESS; -} - -/** - Free out resouce allocated from Legacy Boot Options. - -**/ -VOID -BOpt_FreeLegacyOptions ( - VOID - ) -{ - BOpt_FreeMenu (&LegacyFDMenu); - BOpt_FreeMenu (&LegacyHDMenu); - BOpt_FreeMenu (&LegacyCDMenu); - BOpt_FreeMenu (&LegacyNETMenu); - BOpt_FreeMenu (&LegacyBEVMenu); -} - -/** - - Build the BootOptionMenu according to BootOrder Variable. - This Routine will access the Boot#### to get EFI_LOAD_OPTION. - - @param CallbackData The BMM context data. - - @return EFI_NOT_FOUND Fail to find "BootOrder" variable. - @return EFI_SUCESS Success build boot option menu. - -**/ -EFI_STATUS -BOpt_GetBootOptions ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINTN Index; - UINT16 BootString[10]; - UINT8 *LoadOptionFromVar; - UINT8 *LoadOption; - UINTN BootOptionSize; - BOOLEAN BootNextFlag; - UINT16 *BootOrderList; - UINTN BootOrderListSize; - UINT16 *BootNext; - UINTN BootNextSize; - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT8 *LoadOptionPtr; - UINTN StringSize; - UINTN OptionalDataSize; - UINT8 *LoadOptionEnd; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - UINTN MenuCount; - UINT8 *Ptr; - - MenuCount = 0; - BootOrderListSize = 0; - BootNextSize = 0; - BootOrderList = NULL; - BootNext = NULL; - LoadOptionFromVar = NULL; - BOpt_FreeMenu (&BootOptionMenu); - InitializeListHead (&BootOptionMenu.Head); - - // - // Get the BootOrder from the Var - // - BootOrderList = BdsLibGetVariableAndSize ( - L"BootOrder", - &gEfiGlobalVariableGuid, - &BootOrderListSize - ); - if (BootOrderList == NULL) { - return EFI_NOT_FOUND; - } - - // - // Get the BootNext from the Var - // - BootNext = BdsLibGetVariableAndSize ( - L"BootNext", - &gEfiGlobalVariableGuid, - &BootNextSize - ); - - if (BootNext != NULL) { - if (BootNextSize != sizeof (UINT16)) { - FreePool (BootNext); - BootNext = NULL; - } - } - - for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { - UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]); - // - // Get all loadoptions from the VAR - // - LoadOptionFromVar = BdsLibGetVariableAndSize ( - BootString, - &gEfiGlobalVariableGuid, - &BootOptionSize - ); - if (LoadOptionFromVar == NULL) { - continue; - } - - LoadOption = AllocateZeroPool (BootOptionSize); - if (LoadOption == NULL) { - continue; - } - - CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize); - FreePool (LoadOptionFromVar); - - if (BootNext != NULL) { - BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]); - } else { - BootNextFlag = FALSE; - } - - if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) { - FreePool (LoadOption); - continue; - } - // - // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly. - // the buffer allocated already should be freed before returning. - // - NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); - if (NULL == NewMenuEntry) { - return EFI_OUT_OF_RESOURCES; - } - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - - LoadOptionPtr = LoadOption; - LoadOptionEnd = LoadOption + BootOptionSize; - - NewMenuEntry->OptionNumber = BootOrderList[Index]; - NewLoadContext->LoadOptionModified = FALSE; - NewLoadContext->Deleted = FALSE; - NewLoadContext->IsBootNext = BootNextFlag; - - // - // Is a Legacy Device? - // - Ptr = (UINT8 *) LoadOption; - - // - // Attribute = *(UINT32 *)Ptr; - // - Ptr += sizeof (UINT32); - - // - // FilePathSize = *(UINT16 *)Ptr; - // - Ptr += sizeof (UINT16); - - // - // Description = (CHAR16 *)Ptr; - // - Ptr += StrSize ((CHAR16 *) Ptr); - - // - // Now Ptr point to Device Path - // - DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; - if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { - NewLoadContext->IsLegacy = TRUE; - } else { - NewLoadContext->IsLegacy = FALSE; - } - // - // LoadOption is a pointer type of UINT8 - // for easy use with following LOAD_OPTION - // embedded in this struct - // - NewLoadContext->LoadOption = LoadOption; - NewLoadContext->LoadOptionSize = BootOptionSize; - - NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; - NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); - - NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); - - LoadOptionPtr += sizeof (UINT32); - - NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; - LoadOptionPtr += sizeof (UINT16); - - StringSize = StrSize((UINT16*)LoadOptionPtr); - - NewLoadContext->Description = AllocateCopyPool (StrSize((UINT16*)LoadOptionPtr), LoadOptionPtr); - ASSERT (NewLoadContext->Description != NULL); - - NewMenuEntry->DisplayString = NewLoadContext->Description; - - LoadOptionPtr += StringSize; - - NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); - ASSERT (NewLoadContext->FilePathList != NULL); - CopyMem ( - NewLoadContext->FilePathList, - (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, - NewLoadContext->FilePathListLength - ); - - NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); - NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( - CallbackData, - BootOptionStrDepository - ); - NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( - CallbackData, - BootOptionHelpStrDepository - ); - LoadOptionPtr += NewLoadContext->FilePathListLength; - - if (LoadOptionPtr < LoadOptionEnd) { - OptionalDataSize = BootOptionSize - - sizeof (UINT32) - - sizeof (UINT16) - - StringSize - - NewLoadContext->FilePathListLength; - - NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); - ASSERT (NewLoadContext->OptionalData != NULL); - CopyMem ( - NewLoadContext->OptionalData, - LoadOptionPtr, - OptionalDataSize - ); - - NewLoadContext->OptionalDataSize = OptionalDataSize; - } - - InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); - MenuCount++; - } - - if (BootNext != NULL) { - FreePool (BootNext); - } - if (BootOrderList != NULL) { - FreePool (BootOrderList); - } - BootOptionMenu.MenuNumber = MenuCount; - return EFI_SUCCESS; -} - -/** - - Append file name to existing file name. - - @param Str1 The existing file name - @param Str2 The file name to be appended - - @return Allocate a new string to hold the appended result. - Caller is responsible to free the returned string. - -**/ -CHAR16 * -BOpt_AppendFileName ( - IN CHAR16 *Str1, - IN CHAR16 *Str2 - ) -{ - UINTN Size1; - UINTN Size2; - UINTN MaxLen; - CHAR16 *Str; - CHAR16 *TmpStr; - CHAR16 *Ptr; - CHAR16 *LastSlash; - - Size1 = StrSize (Str1); - Size2 = StrSize (Str2); - MaxLen = (Size1 + Size2 + sizeof (CHAR16)) / sizeof (CHAR16); - Str = AllocateZeroPool (MaxLen * sizeof (CHAR16)); - ASSERT (Str != NULL); - - TmpStr = AllocateZeroPool (MaxLen * sizeof (CHAR16)); - ASSERT (TmpStr != NULL); - - StrCatS (Str, MaxLen, Str1); - if (!((*Str == '\\') && (*(Str + 1) == 0))) { - StrCatS (Str, MaxLen, L"\\"); - } - - StrCatS (Str, MaxLen, Str2); - - Ptr = Str; - LastSlash = Str; - while (*Ptr != 0) { - if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') { - // - // Convert "\Name\..\" to "\" - // DO NOT convert the .. if it is at the end of the string. This will - // break the .. behavior in changing directories. - // - - // - // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings - // that overlap. - // - StrCpyS (TmpStr, MaxLen, Ptr + 3); - StrCpyS (LastSlash, MaxLen - (UINTN) (LastSlash - Str), TmpStr); - Ptr = LastSlash; - } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') { - // - // Convert a "\.\" to a "\" - // - - // - // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings - // that overlap. - // - StrCpyS (TmpStr, MaxLen, Ptr + 2); - StrCpyS (Ptr, MaxLen - (UINTN) (Ptr - Str), TmpStr); - Ptr = LastSlash; - } else if (*Ptr == '\\') { - LastSlash = Ptr; - } - - Ptr++; - } - - FreePool (TmpStr); - - return Str; -} - -/** - - Check whether current FileName point to a valid - Efi Image File. - - @param FileName File need to be checked. - - @retval TRUE Is Efi Image - @retval FALSE Not a valid Efi Image - -**/ -BOOLEAN -BOpt_IsEfiImageName ( - IN UINT16 *FileName - ) -{ - // - // Search for ".efi" extension - // - while (*FileName != L'\0') { - if (FileName[0] == '.') { - if (FileName[1] == 'e' || FileName[1] == 'E') { - if (FileName[2] == 'f' || FileName[2] == 'F') { - if (FileName[3] == 'i' || FileName[3] == 'I') { - return TRUE; - } else if (FileName[3] == 0x0000) { - return FALSE; - } - } else if (FileName[2] == 0x0000) { - return FALSE; - } - } else if (FileName[1] == 0x0000) { - return FALSE; - } - } - - FileName += 1; - } - - return FALSE; -} - -/** - - Check whether current FileName point to a valid Efi Application - - @param Dir Pointer to current Directory - @param FileName Pointer to current File name. - - @retval TRUE Is a valid Efi Application - @retval FALSE not a valid Efi Application - -**/ -BOOLEAN -BOpt_IsEfiApp ( - IN EFI_FILE_HANDLE Dir, - IN UINT16 *FileName - ) -{ - UINTN BufferSize; - EFI_IMAGE_DOS_HEADER DosHdr; - UINT16 Subsystem; - EFI_FILE_HANDLE File; - EFI_STATUS Status; - EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr; - - Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0); - - if (EFI_ERROR (Status)) { - return FALSE; - } - - BufferSize = sizeof (EFI_IMAGE_DOS_HEADER); - File->Read (File, &BufferSize, &DosHdr); - if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) { - File->Close (File); - return FALSE; - } - - File->SetPosition (File, DosHdr.e_lfanew); - BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); - File->Read (File, &BufferSize, &PeHdr); - if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { - File->Close (File); - return FALSE; - } - // - // Determine PE type and read subsytem - // - if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - Subsystem = PeHdr.Pe32.OptionalHeader.Subsystem; - } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { - Subsystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem; - } else { - return FALSE; - } - - if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { - File->Close (File); - return TRUE; - } else { - File->Close (File); - return FALSE; - } -} - -/** - - Find drivers that will be added as Driver#### variables from handles - in current system environment - All valid handles in the system except those consume SimpleFs, LoadFile - are stored in DriverMenu for future use. - - @retval EFI_SUCCESS The function complets successfully. - @return Other value if failed to build the DriverMenu. - -**/ -EFI_STATUS -BOpt_FindDrivers ( - VOID - ) -{ - UINTN NoDevicePathHandles; - EFI_HANDLE *DevicePathHandle; - UINTN Index; - EFI_STATUS Status; - BM_MENU_ENTRY *NewMenuEntry; - BM_HANDLE_CONTEXT *NewHandleContext; - EFI_HANDLE CurHandle; - UINTN OptionNumber; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs; - EFI_LOAD_FILE_PROTOCOL *LoadFile; - - SimpleFs = NULL; - LoadFile = NULL; - - InitializeListHead (&DriverMenu.Head); - - // - // At first, get all handles that support Device Path - // protocol which is the basic requirement for - // Driver#### - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiDevicePathProtocolGuid, - NULL, - &NoDevicePathHandles, - &DevicePathHandle - ); - if (EFI_ERROR (Status)) { - return Status; - } - - OptionNumber = 0; - for (Index = 0; Index < NoDevicePathHandles; Index++) { - CurHandle = DevicePathHandle[Index]; - - Status = gBS->HandleProtocol ( - CurHandle, - &gEfiSimpleFileSystemProtocolGuid, - (VOID **) &SimpleFs - ); - if (Status == EFI_SUCCESS) { - continue; - } - - Status = gBS->HandleProtocol ( - CurHandle, - &gEfiLoadFileProtocolGuid, - (VOID **) &LoadFile - ); - if (Status == EFI_SUCCESS) { - continue; - } - - NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT); - if (NULL == NewMenuEntry) { - FreePool (DevicePathHandle); - return EFI_OUT_OF_RESOURCES; - } - - NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; - NewHandleContext->Handle = CurHandle; - NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle); - NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath); - NewMenuEntry->HelpString = NULL; - NewMenuEntry->OptionNumber = OptionNumber; - OptionNumber++; - InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link); - - } - - if (DevicePathHandle != NULL) { - FreePool (DevicePathHandle); - } - - DriverMenu.MenuNumber = OptionNumber; - return EFI_SUCCESS; -} - -/** - - Get the Option Number that has not been allocated for use. - - @param Type The type of Option. - - @return The available Option Number. - -**/ -UINT16 -BOpt_GetOptionNumber ( - CHAR16 *Type - ) -{ - UINT16 *OrderList; - UINTN OrderListSize; - UINTN Index; - CHAR16 StrTemp[20]; - UINT16 *OptionBuffer; - UINT16 OptionNumber; - UINTN OptionSize; - - OrderListSize = 0; - OrderList = NULL; - OptionNumber = 0; - Index = 0; - - UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type); - - OrderList = BdsLibGetVariableAndSize ( - StrTemp, - &gEfiGlobalVariableGuid, - &OrderListSize - ); - - for (OptionNumber = 0; ; OptionNumber++) { - if (OrderList != NULL) { - for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) { - if (OptionNumber == OrderList[Index]) { - break; - } - } - } - - if (Index < OrderListSize / sizeof (UINT16)) { - // - // The OptionNumber occurs in the OrderList, continue to use next one - // - continue; - } - UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber); - DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp)); - OptionBuffer = BdsLibGetVariableAndSize ( - StrTemp, - &gEfiGlobalVariableGuid, - &OptionSize - ); - if (NULL == OptionBuffer) { - // - // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it - // - break; - } - } - - return OptionNumber; -} - -/** - - Get the Option Number for Boot#### that does not used. - - @return The available Option Number. - -**/ -UINT16 -BOpt_GetBootOptionNumber ( - VOID - ) -{ - return BOpt_GetOptionNumber (L"Boot"); -} - -/** - - Get the Option Number for Driver#### that does not used. - - @return The unused Option Number. - -**/ -UINT16 -BOpt_GetDriverOptionNumber ( - VOID - ) -{ - return BOpt_GetOptionNumber (L"Driver"); -} - -/** - - Build up all DriverOptionMenu - - @param CallbackData The BMM context data. - - @retval EFI_SUCESS The functin completes successfully. - @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation. - @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable. - -**/ -EFI_STATUS -BOpt_GetDriverOptions ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINTN Index; - UINT16 DriverString[12]; - UINT8 *LoadOptionFromVar; - UINT8 *LoadOption; - UINTN DriverOptionSize; - - UINT16 *DriverOrderList; - UINTN DriverOrderListSize; - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT8 *LoadOptionPtr; - UINTN StringSize; - UINTN OptionalDataSize; - UINT8 *LoadOptionEnd; - - DriverOrderListSize = 0; - DriverOrderList = NULL; - DriverOptionSize = 0; - LoadOptionFromVar = NULL; - BOpt_FreeMenu (&DriverOptionMenu); - InitializeListHead (&DriverOptionMenu.Head); - // - // Get the DriverOrder from the Var - // - DriverOrderList = BdsLibGetVariableAndSize ( - L"DriverOrder", - &gEfiGlobalVariableGuid, - &DriverOrderListSize - ); - if (DriverOrderList == NULL) { - return EFI_NOT_FOUND; - } - - for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { - UnicodeSPrint ( - DriverString, - sizeof (DriverString), - L"Driver%04x", - DriverOrderList[Index] - ); - // - // Get all loadoptions from the VAR - // - LoadOptionFromVar = BdsLibGetVariableAndSize ( - DriverString, - &gEfiGlobalVariableGuid, - &DriverOptionSize - ); - if (LoadOptionFromVar == NULL) { - continue; - } - - LoadOption = AllocateZeroPool (DriverOptionSize); - if (LoadOption == NULL) { - continue; - } - - CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize); - FreePool (LoadOptionFromVar); - - NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); - if (NULL == NewMenuEntry) { - return EFI_OUT_OF_RESOURCES; - } - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - LoadOptionPtr = LoadOption; - LoadOptionEnd = LoadOption + DriverOptionSize; - NewMenuEntry->OptionNumber = DriverOrderList[Index]; - NewLoadContext->LoadOptionModified = FALSE; - NewLoadContext->Deleted = FALSE; - NewLoadContext->IsLegacy = FALSE; - - // - // LoadOption is a pointer type of UINT8 - // for easy use with following LOAD_OPTION - // embedded in this struct - // - NewLoadContext->LoadOption = LoadOption; - NewLoadContext->LoadOptionSize = DriverOptionSize; - - NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; - NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); - - NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); - - LoadOptionPtr += sizeof (UINT32); - - NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; - LoadOptionPtr += sizeof (UINT16); - - StringSize = StrSize ((UINT16 *) LoadOptionPtr); - NewLoadContext->Description = AllocateZeroPool (StringSize); - ASSERT (NewLoadContext->Description != NULL); - CopyMem ( - NewLoadContext->Description, - (UINT16 *) LoadOptionPtr, - StringSize - ); - NewMenuEntry->DisplayString = NewLoadContext->Description; - - LoadOptionPtr += StringSize; - - NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); - ASSERT (NewLoadContext->FilePathList != NULL); - CopyMem ( - NewLoadContext->FilePathList, - (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, - NewLoadContext->FilePathListLength - ); - - NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); - NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( - CallbackData, - DriverOptionStrDepository - ); - NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( - CallbackData, - DriverOptionHelpStrDepository - ); - LoadOptionPtr += NewLoadContext->FilePathListLength; - - if (LoadOptionPtr < LoadOptionEnd) { - OptionalDataSize = DriverOptionSize - - sizeof (UINT32) - - sizeof (UINT16) - - StringSize - - NewLoadContext->FilePathListLength; - - NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); - ASSERT (NewLoadContext->OptionalData != NULL); - CopyMem ( - NewLoadContext->OptionalData, - LoadOptionPtr, - OptionalDataSize - ); - - NewLoadContext->OptionalDataSize = OptionalDataSize; - } - - InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); - - } - - if (DriverOrderList != NULL) { - FreePool (DriverOrderList); - } - DriverOptionMenu.MenuNumber = Index; - return EFI_SUCCESS; - -} - -/** - Get option number according to Boot#### and BootOrder variable. - The value is saved as #### + 1. - - @param CallbackData The BMM context data. -**/ -VOID -GetBootOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BMM_FAKE_NV_DATA *BmmConfig; - UINT16 Index; - UINT16 OptionOrderIndex; - UINTN DeviceType; - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - - ASSERT (CallbackData != NULL); - - DeviceType = (UINTN) -1; - BmmConfig = &CallbackData->BmmFakeNvData; - ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder)); - - for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) && - (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0])))); - Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - - if (NewLoadContext->IsLegacy) { - if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) { - DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType; - } else { - // - // Only show one legacy boot option for the same device type - // assuming the boot options are grouped by the device type - // - continue; - } - } - BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1); - } -} - -/** - According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV - devices list . - - @param CallbackData The BMM context data. -**/ -VOID -GetLegacyDeviceOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINTN Index; - UINTN OptionIndex; - UINT16 PageIdList[5]; - UINTN PageNum; - UINTN VarSize; - UINT8 *VarData; - UINT8 *WorkingVarData; - LEGACY_DEV_ORDER_ENTRY *DevOrder; - UINT16 VarDevOrder; - UINT8 *DisMap; - BM_MENU_OPTION *OptionMenu; - BBS_TYPE BbsType; - UINT8 *LegacyOrder; - UINT8 *OldData; - UINTN Pos; - UINTN Bit; - - ASSERT (CallbackData != NULL); - - PageIdList[0] = FORM_SET_FD_ORDER_ID; - PageIdList[1] = FORM_SET_HD_ORDER_ID; - PageIdList[2] = FORM_SET_CD_ORDER_ID; - PageIdList[3] = FORM_SET_NET_ORDER_ID; - PageIdList[4] = FORM_SET_BEV_ORDER_ID; - OptionMenu = NULL; - BbsType = 0; - LegacyOrder = NULL; - OldData = NULL; - DisMap = ZeroMem (CallbackData->BmmFakeNvData.DisableMap, sizeof (CallbackData->BmmFakeNvData.DisableMap)); - PageNum = sizeof (PageIdList) / sizeof (PageIdList[0]); - VarData = BdsLibGetVariableAndSize ( - VAR_LEGACY_DEV_ORDER, - &gEfiLegacyDevOrderVariableGuid, - &VarSize - ); - - for (Index = 0; Index < PageNum; Index++) { - switch (PageIdList[Index]) { - - case FORM_SET_FD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; - BbsType = BBS_FLOPPY; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD; - OldData = CallbackData->BmmOldFakeNVData.LegacyFD; - break; - - case FORM_SET_HD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; - BbsType = BBS_HARDDISK; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD; - OldData = CallbackData->BmmOldFakeNVData.LegacyHD; - break; - - case FORM_SET_CD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; - BbsType = BBS_CDROM; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD; - OldData = CallbackData->BmmOldFakeNVData.LegacyCD; - break; - - case FORM_SET_NET_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; - BbsType = BBS_EMBED_NETWORK; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET; - OldData = CallbackData->BmmOldFakeNVData.LegacyNET; - break; - - default: - ASSERT (PageIdList[Index] == FORM_SET_BEV_ORDER_ID); - OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; - BbsType = BBS_BEV_DEVICE; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV; - OldData = CallbackData->BmmOldFakeNVData.LegacyBEV; - break; - } - - if (NULL != VarData) { - WorkingVarData = VarData; - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData; - while (WorkingVarData < VarData + VarSize) { - if (DevOrder->BbsType == BbsType) { - break; - } - - WorkingVarData = (UINT8 *)((UINTN)WorkingVarData + sizeof (BBS_TYPE)); - WorkingVarData += *(UINT16 *) WorkingVarData; - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData; - } - for (OptionIndex = 0; OptionIndex < OptionMenu->MenuNumber; OptionIndex++) { - VarDevOrder = *(UINT16 *) ((UINTN) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + OptionIndex * sizeof (UINT16)); - if (0xFF00 == (VarDevOrder & 0xFF00)) { - LegacyOrder[OptionIndex] = 0xFF; - Pos = (VarDevOrder & 0xFF) / 8; - Bit = 7 - ((VarDevOrder & 0xFF) % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); - } else { - LegacyOrder[OptionIndex] = (UINT8) (VarDevOrder & 0xFF); - } - } - CopyMem (OldData, LegacyOrder, 100); - } - } -} - -/** - Get driver option order from globalc DriverOptionMenu. - - @param CallbackData The BMM context data. - -**/ -VOID -GetDriverOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BMM_FAKE_NV_DATA *BmmConfig; - UINT16 Index; - UINT16 OptionOrderIndex; - UINTN DeviceType; - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - - ASSERT (CallbackData != NULL); - - DeviceType = (UINTN) -1; - BmmConfig = &CallbackData->BmmFakeNvData; - ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder)); - - for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) && - (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0])))); - Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - - if (NewLoadContext->IsLegacy) { - if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) { - DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType; - } else { - // - // Only show one legacy boot option for the same device type - // assuming the boot options are grouped by the device type - // - continue; - } - } - BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1); - } -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c deleted file mode 100644 index 1854b98c36..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c +++ /dev/null @@ -1,1198 +0,0 @@ -/** @file - handles console redirection from boot manager - -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 -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 "BootMaint.h" - -UART_FLOW_CONTROL_DEVICE_PATH mFlowControlDevicePath = -{ - { - MESSAGING_DEVICE_PATH, - MSG_VENDOR_DP, - { - (UINT8)(sizeof(UART_FLOW_CONTROL_DEVICE_PATH)), - (UINT8)((sizeof(UART_FLOW_CONTROL_DEVICE_PATH)) >> 8) - } - }, - DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL, - UART_FLOW_CONTROL_HARDWARE -}; - -/** - Check the device path node whether it's the Flow Control node or not. - - @param[in] FlowControl The device path node to be checked. - - @retval TRUE It's the Flow Control node. - @retval FALSE It's not. - -**/ -BOOLEAN -IsUartFlowControlNode ( - IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl - ) -{ - return (BOOLEAN) ( - (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) && - (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) && - (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid)) - ); -} - -/** - Check whether the device path node is ISA Serial Node. - - @param Acpi Device path node to be checked - - @retval TRUE It's ISA Serial Node. - @retval FALSE It's NOT ISA Serial Node. - -**/ -BOOLEAN -IsIsaSerialNode ( - IN ACPI_HID_DEVICE_PATH *Acpi - ) -{ - return (BOOLEAN) ( - (DevicePathType (Acpi) == ACPI_DEVICE_PATH) && - (DevicePathSubType (Acpi) == ACPI_DP) && - (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501)) - ); -} - -/** - Update Com Ports attributes from DevicePath - - @param DevicePath DevicePath that contains Com ports - - @retval EFI_SUCCESS The update is successful. - -**/ -EFI_STATUS -UpdateComAttributeFromVariable ( - EFI_DEVICE_PATH_PROTOCOL *DevicePath - ); - -/** - Update the multi-instance device path of Terminal Device based on - the global TerminalMenu. If ChangeTernimal is TRUE, the terminal - device path in the Terminal Device in TerminalMenu is also updated. - - @param DevicePath The multi-instance device path. - @param ChangeTerminal TRUE, then device path in the Terminal Device - in TerminalMenu is also updated; FALSE, no update. - - @return EFI_SUCCESS The function completes successfully. - -**/ -EFI_STATUS -ChangeTerminalDevicePath ( - IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, - IN BOOLEAN ChangeTerminal - ) -{ - EFI_DEVICE_PATH_PROTOCOL *Node; - EFI_DEVICE_PATH_PROTOCOL *Node1; - ACPI_HID_DEVICE_PATH *Acpi; - UART_DEVICE_PATH *Uart; - UART_DEVICE_PATH *Uart1; - UINTN Com; - BM_TERMINAL_CONTEXT *NewTerminalContext; - BM_MENU_ENTRY *NewMenuEntry; - UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode; - - Node = *DevicePath; - Node = NextDevicePathNode (Node); - Com = 0; - while (!IsDevicePathEnd (Node)) { - Acpi = (ACPI_HID_DEVICE_PATH *) Node; - if (IsIsaSerialNode (Acpi)) { - CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); - } - - NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com); - - NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; - if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { - Uart = (UART_DEVICE_PATH *) Node; - CopyMem ( - &Uart->BaudRate, - &NewTerminalContext->BaudRate, - sizeof (UINT64) - ); - - CopyMem ( - &Uart->DataBits, - &NewTerminalContext->DataBits, - sizeof (UINT8) - ); - - CopyMem ( - &Uart->Parity, - &NewTerminalContext->Parity, - sizeof (UINT8) - ); - - CopyMem ( - &Uart->StopBits, - &NewTerminalContext->StopBits, - sizeof (UINT8) - ); - - FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node); - if (IsUartFlowControlNode (FlowControlNode)) { - FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl; - } else { - // - // Append the Flow control device node when user enable flow control. - // - if (NewTerminalContext->FlowControl != 0) { - mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl; - *DevicePath = AppendDevicePathNode ( - *DevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath) - ); - } - } - - // - // Change the device path in the ComPort - // - if (ChangeTerminal) { - Node1 = NewTerminalContext->DevicePath; - Node1 = NextDevicePathNode (Node1); - while (!IsDevicePathEnd (Node1)) { - if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) { - Uart1 = (UART_DEVICE_PATH *) Node1; - CopyMem ( - &Uart1->BaudRate, - &NewTerminalContext->BaudRate, - sizeof (UINT64) - ); - - CopyMem ( - &Uart1->DataBits, - &NewTerminalContext->DataBits, - sizeof (UINT8) - ); - - CopyMem ( - &Uart1->Parity, - &NewTerminalContext->Parity, - sizeof (UINT8) - ); - - CopyMem ( - &Uart1->StopBits, - &NewTerminalContext->StopBits, - sizeof (UINT8) - ); - break; - } - // - // end if - // - Node1 = NextDevicePathNode (Node1); - } - // - // end while - // - break; - } - } - - Node = NextDevicePathNode (Node); - } - - return EFI_SUCCESS; - -} - -/** - Update the device path that describing a terminal device - based on the new BaudRate, Data Bits, parity and Stop Bits - set. - - @param DevicePath terminal device's path - -**/ -VOID -ChangeVariableDevicePath ( - IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - EFI_DEVICE_PATH_PROTOCOL *Node; - ACPI_HID_DEVICE_PATH *Acpi; - UART_DEVICE_PATH *Uart; - UINTN Com; - BM_TERMINAL_CONTEXT *NewTerminalContext; - BM_MENU_ENTRY *NewMenuEntry; - - Node = DevicePath; - Node = NextDevicePathNode (Node); - Com = 0; - while (!IsDevicePathEnd (Node)) { - Acpi = (ACPI_HID_DEVICE_PATH *) Node; - if (IsIsaSerialNode (Acpi)) { - CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); - } - - if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { - NewMenuEntry = BOpt_GetMenuEntry ( - &TerminalMenu, - Com - ); - ASSERT (NewMenuEntry != NULL); - NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; - Uart = (UART_DEVICE_PATH *) Node; - CopyMem ( - &Uart->BaudRate, - &NewTerminalContext->BaudRate, - sizeof (UINT64) - ); - - CopyMem ( - &Uart->DataBits, - &NewTerminalContext->DataBits, - sizeof (UINT8) - ); - - CopyMem ( - &Uart->Parity, - &NewTerminalContext->Parity, - sizeof (UINT8) - ); - - CopyMem ( - &Uart->StopBits, - &NewTerminalContext->StopBits, - sizeof (UINT8) - ); - } - - Node = NextDevicePathNode (Node); - } -} - -/** - Retrieve ACPI UID of UART from device path - - @param Handle The handle for the UART device. - @param AcpiUid The ACPI UID on output. - - @retval TRUE Find valid UID from device path - @retval FALSE Can't find - -**/ -BOOLEAN -RetrieveUartUid ( - IN EFI_HANDLE Handle, - IN OUT UINT32 *AcpiUid - ) -{ - EFI_STATUS Status; - ACPI_HID_DEVICE_PATH *Acpi; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - - Status = gBS->HandleProtocol ( - Handle, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath - ); - if (EFI_ERROR (Status)) { - return FALSE; - } - - Acpi = NULL; - for (; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { - if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_UART_DP)) { - break; - } - // - // Acpi points to the node before the Uart node - // - Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath; - } - - if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { - if (AcpiUid != NULL) { - CopyMem (AcpiUid, &Acpi->UID, sizeof (UINT32)); - } - return TRUE; - } else { - return FALSE; - } -} - -/** - Sort Uart handles array with Acpi->UID from low to high. - - @param Handles EFI_SERIAL_IO_PROTOCOL handle buffer - @param NoHandles EFI_SERIAL_IO_PROTOCOL handle count -**/ -VOID -SortedUartHandle ( - IN EFI_HANDLE *Handles, - IN UINTN NoHandles - ) -{ - UINTN Index1; - UINTN Index2; - UINTN Position; - UINT32 AcpiUid1; - UINT32 AcpiUid2; - UINT32 TempAcpiUid; - EFI_HANDLE TempHandle; - - for (Index1 = 0; Index1 < NoHandles-1; Index1++) { - if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) { - continue; - } - TempHandle = Handles[Index1]; - Position = Index1; - TempAcpiUid = AcpiUid1; - - for (Index2 = Index1+1; Index2 < NoHandles; Index2++) { - if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) { - continue; - } - if (AcpiUid2 < TempAcpiUid) { - TempAcpiUid = AcpiUid2; - TempHandle = Handles[Index2]; - Position = Index2; - } - } - Handles[Position] = Handles[Index1]; - Handles[Index1] = TempHandle; - } -} - -/** - Test whether DevicePath is a valid Terminal - - - @param DevicePath DevicePath to be checked - @param Termi If DevicePath is valid Terminal, terminal type is returned. - @param Com If DevicePath is valid Terminal, Com Port type is returned. - - @retval TRUE If DevicePath point to a Terminal. - @retval FALSE If DevicePath does not point to a Terminal. - -**/ -BOOLEAN -IsTerminalDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT TYPE_OF_TERMINAL *Termi, - OUT UINTN *Com - ); - -/** - Build a list containing all serial devices. - - - @retval EFI_SUCCESS The function complete successfully. - @retval EFI_UNSUPPORTED No serial ports present. - -**/ -EFI_STATUS -LocateSerialIo ( - VOID - ) -{ - UINTN Index; - UINTN Index2; - UINTN NoHandles; - EFI_HANDLE *Handles; - EFI_STATUS Status; - ACPI_HID_DEVICE_PATH *Acpi; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_SERIAL_IO_PROTOCOL *SerialIo; - EFI_DEVICE_PATH_PROTOCOL *Node; - EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; - EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; - EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; - BM_MENU_ENTRY *NewMenuEntry; - BM_TERMINAL_CONTEXT *NewTerminalContext; - EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; - VENDOR_DEVICE_PATH Vendor; - UINT32 FlowControl; - // - // Get all handles that have SerialIo protocol installed - // - InitializeListHead (&TerminalMenu.Head); - TerminalMenu.MenuNumber = 0; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiSerialIoProtocolGuid, - NULL, - &NoHandles, - &Handles - ); - if (EFI_ERROR (Status)) { - // - // No serial ports present - // - return EFI_UNSUPPORTED; - } - - // - // Sort Uart handles array with Acpi->UID from low to high - // then Terminal menu can be built from low Acpi->UID to high Acpi->UID - // - SortedUartHandle (Handles, NoHandles); - - for (Index = 0; Index < NoHandles; Index++) { - // - // Check to see whether the handle has DevicePath Protocol installed - // - gBS->HandleProtocol ( - Handles[Index], - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath - ); - - Acpi = NULL; - for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { - if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { - break; - } - // - // Acpi points to the node before Uart node - // - Acpi = (ACPI_HID_DEVICE_PATH *) Node; - } - - if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { - NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT); - if (NewMenuEntry == NULL) { - FreePool (Handles); - return EFI_OUT_OF_RESOURCES; - } - - NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; - CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32)); - NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath); - // - // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system! - // coz' the misc data for each platform is not correct, actually it's the device path stored in - // datahub which is not completed, so a searching for end of device path will enter a - // dead-loop. - // - NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath); - if (NULL == NewMenuEntry->DisplayString) { - NewMenuEntry->DisplayString = DevicePathToStr (DevicePath); - } - - NewMenuEntry->HelpString = NULL; - - gBS->HandleProtocol ( - Handles[Index], - &gEfiSerialIoProtocolGuid, - (VOID **) &SerialIo - ); - - CopyMem ( - &NewTerminalContext->BaudRate, - &SerialIo->Mode->BaudRate, - sizeof (UINT64) - ); - - CopyMem ( - &NewTerminalContext->DataBits, - &SerialIo->Mode->DataBits, - sizeof (UINT8) - ); - - CopyMem ( - &NewTerminalContext->Parity, - &SerialIo->Mode->Parity, - sizeof (UINT8) - ); - - CopyMem ( - &NewTerminalContext->StopBits, - &SerialIo->Mode->StopBits, - sizeof (UINT8) - ); - - NewTerminalContext->FlowControl = 0; - SerialIo->GetControl(SerialIo, &FlowControl); - if ((FlowControl & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) != 0) { - NewTerminalContext->FlowControl = UART_FLOW_CONTROL_HARDWARE; - } - - InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link); - TerminalMenu.MenuNumber++; - } - } - if (Handles != NULL) { - FreePool (Handles); - } - - // - // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var - // - OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid); - InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid); - ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid); - if (OutDevicePath != NULL) { - UpdateComAttributeFromVariable (OutDevicePath); - } - - if (InpDevicePath != NULL) { - UpdateComAttributeFromVariable (InpDevicePath); - } - - if (ErrDevicePath != NULL) { - UpdateComAttributeFromVariable (ErrDevicePath); - } - - for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); - if (NULL == NewMenuEntry) { - return EFI_NOT_FOUND; - } - - NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; - - NewTerminalContext->TerminalType = 0; - NewTerminalContext->IsConIn = FALSE; - NewTerminalContext->IsConOut = FALSE; - NewTerminalContext->IsStdErr = FALSE; - - Vendor.Header.Type = MESSAGING_DEVICE_PATH; - Vendor.Header.SubType = MSG_VENDOR_DP; - - for (Index2 = 0; Index2 < 4; Index2++) { - CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID)); - SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); - NewDevicePath = AppendDevicePathNode ( - NewTerminalContext->DevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) &Vendor - ); - if (NewMenuEntry->HelpString != NULL) { - FreePool (NewMenuEntry->HelpString); - } - // - // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath); - // NewMenuEntry->DisplayString = NewMenuEntry->HelpString; - // - NewMenuEntry->HelpString = NULL; - - if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) { - NewTerminalContext->IsConOut = TRUE; - NewTerminalContext->TerminalType = (UINT8) Index2; - } - - if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) { - NewTerminalContext->IsConIn = TRUE; - NewTerminalContext->TerminalType = (UINT8) Index2; - } - - if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) { - NewTerminalContext->IsStdErr = TRUE; - NewTerminalContext->TerminalType = (UINT8) Index2; - } - } - } - - return EFI_SUCCESS; -} - -/** - Update Com Ports attributes from DevicePath - - @param DevicePath DevicePath that contains Com ports - - @retval EFI_SUCCESS The update is successful. - @retval EFI_NOT_FOUND Can not find specific menu entry -**/ -EFI_STATUS -UpdateComAttributeFromVariable ( - EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - EFI_DEVICE_PATH_PROTOCOL *Node; - EFI_DEVICE_PATH_PROTOCOL *SerialNode; - ACPI_HID_DEVICE_PATH *Acpi; - UART_DEVICE_PATH *Uart; - UART_DEVICE_PATH *Uart1; - UINTN TerminalNumber; - BM_MENU_ENTRY *NewMenuEntry; - BM_TERMINAL_CONTEXT *NewTerminalContext; - UINTN Index; - UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode; - BOOLEAN HasFlowControlNode; - - HasFlowControlNode = FALSE; - Node = DevicePath; - Node = NextDevicePathNode (Node); - TerminalNumber = 0; - for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { - while (!IsDevicePathEnd (Node)) { - Acpi = (ACPI_HID_DEVICE_PATH *) Node; - if (IsIsaSerialNode (Acpi)) { - CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32)); - } - - if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { - Uart = (UART_DEVICE_PATH *) Node; - NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber); - if (NULL == NewMenuEntry) { - return EFI_NOT_FOUND; - } - - NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; - CopyMem ( - &NewTerminalContext->BaudRate, - &Uart->BaudRate, - sizeof (UINT64) - ); - - CopyMem ( - &NewTerminalContext->DataBits, - &Uart->DataBits, - sizeof (UINT8) - ); - - CopyMem ( - &NewTerminalContext->Parity, - &Uart->Parity, - sizeof (UINT8) - ); - - CopyMem ( - &NewTerminalContext->StopBits, - &Uart->StopBits, - sizeof (UINT8) - ); - - FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node); - if (IsUartFlowControlNode (FlowControlNode)) { - HasFlowControlNode = TRUE; - NewTerminalContext->FlowControl = (UINT8) ReadUnaligned32 (&FlowControlNode->FlowControlMap); - } else if (NewTerminalContext->FlowControl != 0) { - // - // No Flow Control device path node, assumption no Flow control - // - NewTerminalContext->FlowControl = 0; - } - - SerialNode = NewTerminalContext->DevicePath; - SerialNode = NextDevicePathNode (SerialNode); - while (!IsDevicePathEnd (SerialNode)) { - if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) { - // - // Update following device paths according to - // previous acquired uart attributes - // - Uart1 = (UART_DEVICE_PATH *) SerialNode; - CopyMem ( - &Uart1->BaudRate, - &NewTerminalContext->BaudRate, - sizeof (UINT64) - ); - - CopyMem ( - &Uart1->DataBits, - &NewTerminalContext->DataBits, - sizeof (UINT8) - ); - CopyMem ( - &Uart1->Parity, - &NewTerminalContext->Parity, - sizeof (UINT8) - ); - CopyMem ( - &Uart1->StopBits, - &NewTerminalContext->StopBits, - sizeof (UINT8) - ); - - FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (SerialNode); - if (IsUartFlowControlNode (FlowControlNode)) { - FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl; - } else { - if (HasFlowControlNode) { - mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl; - NewTerminalContext->DevicePath = AppendDevicePathNode ( - NewTerminalContext->DevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath) - ); - } - } - break; - } - - SerialNode = NextDevicePathNode (SerialNode); - } - // - // end while - // - } - - Node = NextDevicePathNode (Node); - } - // - // end while - // - } - - return EFI_SUCCESS; -} - -/** - Build up Console Menu based on types passed in. The type can - be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT - and BM_CONSOLE_ERR_CONTEXT_SELECT. - - @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT - and BM_CONSOLE_ERR_CONTEXT_SELECT. - - @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined. - @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev", - "ConInDev" or "ConErrDev" doesn't exists. - @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations. - @retval EFI_SUCCESS Function completes successfully. - -**/ -EFI_STATUS -GetConsoleMenu ( - IN UINTN ConsoleMenuType - ) -{ - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_DEVICE_PATH_PROTOCOL *AllDevicePath; - EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath; - EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; - UINTN Size; - UINTN AllCount; - UINTN Index; - UINTN Index2; - BM_MENU_ENTRY *NewMenuEntry; - BM_CONSOLE_CONTEXT *NewConsoleContext; - TYPE_OF_TERMINAL Terminal; - UINTN Com; - BM_MENU_OPTION *ConsoleMenu; - - DevicePath = NULL; - AllDevicePath = NULL; - AllCount = 0; - switch (ConsoleMenuType) { - case BM_CONSOLE_IN_CONTEXT_SELECT: - ConsoleMenu = &ConsoleInpMenu; - DevicePath = EfiLibGetVariable ( - L"ConIn", - &gEfiGlobalVariableGuid - ); - - AllDevicePath = EfiLibGetVariable ( - L"ConInDev", - &gEfiGlobalVariableGuid - ); - break; - - case BM_CONSOLE_OUT_CONTEXT_SELECT: - ConsoleMenu = &ConsoleOutMenu; - DevicePath = EfiLibGetVariable ( - L"ConOut", - &gEfiGlobalVariableGuid - ); - - AllDevicePath = EfiLibGetVariable ( - L"ConOutDev", - &gEfiGlobalVariableGuid - ); - break; - - case BM_CONSOLE_ERR_CONTEXT_SELECT: - ConsoleMenu = &ConsoleErrMenu; - DevicePath = EfiLibGetVariable ( - L"ErrOut", - &gEfiGlobalVariableGuid - ); - - AllDevicePath = EfiLibGetVariable ( - L"ErrOutDev", - &gEfiGlobalVariableGuid - ); - break; - - default: - return EFI_UNSUPPORTED; - } - - if (NULL == AllDevicePath) { - return EFI_NOT_FOUND; - } - - InitializeListHead (&ConsoleMenu->Head); - - AllCount = EfiDevicePathInstanceCount (AllDevicePath); - ConsoleMenu->MenuNumber = 0; - // - // Following is menu building up for Console Devices selected. - // - MultiDevicePath = AllDevicePath; - Index2 = 0; - for (Index = 0; Index < AllCount; Index++) { - DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size); - - NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT); - if (NULL == NewMenuEntry) { - return EFI_OUT_OF_RESOURCES; - } - - NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; - NewMenuEntry->OptionNumber = Index2; - - NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst); - ASSERT (NewConsoleContext->DevicePath != NULL); - NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath); - if (NULL == NewMenuEntry->DisplayString) { - NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath); - } - - NewConsoleContext->IsTerminal = IsTerminalDevicePath ( - NewConsoleContext->DevicePath, - &Terminal, - &Com - ); - - NewConsoleContext->IsActive = BdsLibMatchDevicePaths ( - DevicePath, - NewConsoleContext->DevicePath - ); - - if (NewConsoleContext->IsTerminal) { - BOpt_DestroyMenuEntry (NewMenuEntry); - } else { - Index2++; - ConsoleMenu->MenuNumber++; - InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); - } - } - - return EFI_SUCCESS; -} - -/** - Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu - - @retval EFI_SUCCESS The function always complete successfully. - -**/ -EFI_STATUS -GetAllConsoles ( - VOID - ) -{ - GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT); - GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT); - GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT); - return EFI_SUCCESS; -} - -/** - Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu - - @retval EFI_SUCCESS The function always complete successfully. -**/ -EFI_STATUS -FreeAllConsoles ( - VOID - ) -{ - BOpt_FreeMenu (&ConsoleOutMenu); - BOpt_FreeMenu (&ConsoleInpMenu); - BOpt_FreeMenu (&ConsoleErrMenu); - BOpt_FreeMenu (&TerminalMenu); - return EFI_SUCCESS; -} - -/** - Test whether DevicePath is a valid Terminal - - - @param DevicePath DevicePath to be checked - @param Termi If DevicePath is valid Terminal, terminal type is returned. - @param Com If DevicePath is valid Terminal, Com Port type is returned. - - @retval TRUE If DevicePath point to a Terminal. - @retval FALSE If DevicePath does not point to a Terminal. - -**/ -BOOLEAN -IsTerminalDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT TYPE_OF_TERMINAL *Termi, - OUT UINTN *Com - ) -{ - BOOLEAN IsTerminal; - EFI_DEVICE_PATH_PROTOCOL *Node; - VENDOR_DEVICE_PATH *Vendor; - UART_DEVICE_PATH *Uart; - ACPI_HID_DEVICE_PATH *Acpi; - - IsTerminal = FALSE; - - Uart = NULL; - Vendor = NULL; - Acpi = NULL; - for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { - // - // Vendor points to the node before the End node - // - Vendor = (VENDOR_DEVICE_PATH *) Node; - - if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { - Uart = (UART_DEVICE_PATH *) Node; - } - - if (Uart == NULL) { - // - // Acpi points to the node before the UART node - // - Acpi = (ACPI_HID_DEVICE_PATH *) Node; - } - } - - if (Vendor == NULL || - DevicePathType (Vendor) != MESSAGING_DEVICE_PATH || - DevicePathSubType (Vendor) != MSG_VENDOR_DP || - Uart == NULL) { - return FALSE; - } - - // - // There are four kinds of Terminal types - // check to see whether this devicepath - // is one of that type - // - if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[0])) { - *Termi = TerminalTypePcAnsi; - IsTerminal = TRUE; - } else { - if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[1])) { - *Termi = TerminalTypeVt100; - IsTerminal = TRUE; - } else { - if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[2])) { - *Termi = TerminalTypeVt100Plus; - IsTerminal = TRUE; - } else { - if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[3])) { - *Termi = TerminalTypeVtUtf8; - IsTerminal = TRUE; - } else { - IsTerminal = FALSE; - } - } - } - } - - if (!IsTerminal) { - return FALSE; - } - - if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { - CopyMem (Com, &Acpi->UID, sizeof (UINT32)); - } else { - return FALSE; - } - - return TRUE; -} - -/** - Get mode number according to column and row - - @param CallbackData The BMM context data. -**/ -VOID -GetConsoleOutMode ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINTN Col; - UINTN Row; - UINTN CurrentCol; - UINTN CurrentRow; - UINTN Mode; - UINTN MaxMode; - EFI_STATUS Status; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; - - ConOut = gST->ConOut; - MaxMode = (UINTN) (ConOut->Mode->MaxMode); - - CurrentCol = PcdGet32 (PcdSetupConOutColumn); - CurrentRow = PcdGet32 (PcdSetupConOutRow); - for (Mode = 0; Mode < MaxMode; Mode++) { - Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); - if (!EFI_ERROR(Status)) { - if (CurrentCol == Col && CurrentRow == Row) { - CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode; - break; - } - } - } -} - -/** - - Initialize console input device check box to ConsoleInCheck[MAX_MENU_NUMBER] - in BMM_FAKE_NV_DATA structure. - - @param CallbackData The BMM context data. - -**/ -VOID -GetConsoleInCheck ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINT16 Index; - BM_MENU_ENTRY *NewMenuEntry; - UINT8 *ConInCheck; - BM_CONSOLE_CONTEXT *NewConsoleContext; - - ASSERT (CallbackData != NULL); - - ConInCheck = &CallbackData->BmmFakeNvData.ConsoleInCheck[0]; - for (Index = 0; ((Index < ConsoleInpMenu.MenuNumber) && \ - (Index < MAX_MENU_NUMBER)) ; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); - NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; - ConInCheck[Index] = NewConsoleContext->IsActive; - } -} - -/** - - Initialize console output device check box to ConsoleOutCheck[MAX_MENU_NUMBER] - in BMM_FAKE_NV_DATA structure. - - @param CallbackData The BMM context data. - -**/ -VOID -GetConsoleOutCheck ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINT16 Index; - BM_MENU_ENTRY *NewMenuEntry; - UINT8 *ConOutCheck; - BM_CONSOLE_CONTEXT *NewConsoleContext; - - ASSERT (CallbackData != NULL); - ConOutCheck = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0]; - for (Index = 0; ((Index < ConsoleOutMenu.MenuNumber) && \ - (Index < MAX_MENU_NUMBER)) ; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); - NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; - ConOutCheck[Index] = NewConsoleContext->IsActive; - } -} - -/** - - Initialize standard error output device check box to ConsoleErrCheck[MAX_MENU_NUMBER] - in BMM_FAKE_NV_DATA structure. - - @param CallbackData The BMM context data. - -**/ -VOID -GetConsoleErrCheck ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINT16 Index; - BM_MENU_ENTRY *NewMenuEntry; - UINT8 *ConErrCheck; - BM_CONSOLE_CONTEXT *NewConsoleContext; - - ASSERT (CallbackData != NULL); - ConErrCheck = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0]; - for (Index = 0; ((Index < ConsoleErrMenu.MenuNumber) && \ - (Index < MAX_MENU_NUMBER)) ; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); - NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; - ConErrCheck[Index] = NewConsoleContext->IsActive; - } -} - -/** - - Initialize terminal attributes (baudrate, data rate, stop bits, parity and terminal type) - to BMM_FAKE_NV_DATA structure. - - @param CallbackData The BMM context data. - -**/ -VOID -GetTerminalAttribute ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BMM_FAKE_NV_DATA *CurrentFakeNVMap; - BM_MENU_ENTRY *NewMenuEntry; - BM_TERMINAL_CONTEXT *NewTerminalContext; - UINT16 TerminalIndex; - UINT8 AttributeIndex; - - ASSERT (CallbackData != NULL); - - CurrentFakeNVMap = &CallbackData->BmmFakeNvData; - for (TerminalIndex = 0; ((TerminalIndex < TerminalMenu.MenuNumber) && \ - (TerminalIndex < MAX_MENU_NUMBER)); TerminalIndex++) { - NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalIndex); - NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; - for (AttributeIndex = 0; AttributeIndex < sizeof (BaudRateList) / sizeof (BaudRateList [0]); AttributeIndex++) { - if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[AttributeIndex].Value)) { - NewTerminalContext->BaudRateIndex = AttributeIndex; - break; - } - } - for (AttributeIndex = 0; AttributeIndex < sizeof (DataBitsList) / sizeof (DataBitsList[0]); AttributeIndex++) { - if (NewTerminalContext->DataBits == (UINT64) (DataBitsList[AttributeIndex].Value)) { - NewTerminalContext->DataBitsIndex = AttributeIndex; - break; - } - } - - for (AttributeIndex = 0; AttributeIndex < sizeof (ParityList) / sizeof (ParityList[0]); AttributeIndex++) { - if (NewTerminalContext->Parity == (UINT64) (ParityList[AttributeIndex].Value)) { - NewTerminalContext->ParityIndex = AttributeIndex; - break; - } - } - - for (AttributeIndex = 0; AttributeIndex < sizeof (StopBitsList) / sizeof (StopBitsList[0]); AttributeIndex++) { - if (NewTerminalContext->StopBits == (UINT64) (StopBitsList[AttributeIndex].Value)) { - NewTerminalContext->StopBitsIndex = AttributeIndex; - break; - } - } - CurrentFakeNVMap->COMBaudRate[TerminalIndex] = NewTerminalContext->BaudRateIndex; - CurrentFakeNVMap->COMDataRate[TerminalIndex] = NewTerminalContext->DataBitsIndex; - CurrentFakeNVMap->COMStopBits[TerminalIndex] = NewTerminalContext->StopBitsIndex; - CurrentFakeNVMap->COMParity[TerminalIndex] = NewTerminalContext->ParityIndex; - CurrentFakeNVMap->COMTerminalType[TerminalIndex] = NewTerminalContext->TerminalType; - CurrentFakeNVMap->COMFlowControl[TerminalIndex] = NewTerminalContext->FlowControl; - } -} - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c deleted file mode 100644 index 0a3ffbcc30..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c +++ /dev/null @@ -1,332 +0,0 @@ -/** @file - Define some data used for Boot Maint - -Copyright (c) 2004 - 2008, Intel 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 "BootMaint.h" - -VOID *mStartOpCodeHandle = NULL; -VOID *mEndOpCodeHandle = NULL; -EFI_IFR_GUID_LABEL *mStartLabel = NULL; -EFI_IFR_GUID_LABEL *mEndLabel = NULL; - -STRING_DEPOSITORY *FileOptionStrDepository; -STRING_DEPOSITORY *ConsoleOptionStrDepository; -STRING_DEPOSITORY *BootOptionStrDepository; -STRING_DEPOSITORY *BootOptionHelpStrDepository; -STRING_DEPOSITORY *DriverOptionStrDepository; -STRING_DEPOSITORY *DriverOptionHelpStrDepository; -STRING_DEPOSITORY *TerminalStrDepository; - -/// -/// Terminal type string token storage -/// -UINT16 TerminalType[] = { - STRING_TOKEN(STR_COM_TYPE_0), - STRING_TOKEN(STR_COM_TYPE_1), - STRING_TOKEN(STR_COM_TYPE_2), - STRING_TOKEN(STR_COM_TYPE_3), -}; - -/// -/// Flow Control type string token storage -/// -UINT16 mFlowControlType[2] = { - STRING_TOKEN(STR_NONE_FLOW_CONTROL), - STRING_TOKEN(STR_HARDWARE_FLOW_CONTROL) -}; - -UINT32 mFlowControlValue[2] = { - 0, - UART_FLOW_CONTROL_HARDWARE -}; - -/// -/// File system selection menu -/// -BM_MENU_OPTION FsOptionMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Console Input Device Selection Menu -/// -BM_MENU_OPTION ConsoleInpMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Console Output Device Selection Menu -/// -BM_MENU_OPTION ConsoleOutMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Error Output Device Selection Menu -/// -BM_MENU_OPTION ConsoleErrMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Boot Option from variable Menu -/// -BM_MENU_OPTION BootOptionMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Driver Option from variable menu -/// -BM_MENU_OPTION DriverOptionMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy FD Info from LegacyBios.GetBbsInfo() -/// -BM_MENU_OPTION LegacyFDMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy HD Info from LegacyBios.GetBbsInfo() -/// -BM_MENU_OPTION LegacyHDMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy CD Info from LegacyBios.GetBbsInfo() -/// -BM_MENU_OPTION LegacyCDMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy NET Info from LegacyBios.GetBbsInfo() -/// -BM_MENU_OPTION LegacyNETMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Legacy NET Info from LegacyBios.GetBbsInfo() -/// -BM_MENU_OPTION LegacyBEVMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Files and sub-directories in current directory menu -/// -BM_MENU_OPTION DirectoryMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Handles in current system selection menu -/// -BM_MENU_OPTION DriverMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -BM_MENU_OPTION TerminalMenu = { - BM_MENU_OPTION_SIGNATURE, - {NULL}, - 0 -}; - -/// -/// Value and string token correspondency for BaudRate -/// -COM_ATTR BaudRateList[19] = { - { - 115200, - STRING_TOKEN(STR_COM_BAUD_RATE_0) - }, - { - 57600, - STRING_TOKEN(STR_COM_BAUD_RATE_1) - }, - { - 38400, - STRING_TOKEN(STR_COM_BAUD_RATE_2) - }, - { - 19200, - STRING_TOKEN(STR_COM_BAUD_RATE_3) - }, - { - 9600, - STRING_TOKEN(STR_COM_BAUD_RATE_4) - }, - { - 7200, - STRING_TOKEN(STR_COM_BAUD_RATE_5) - }, - { - 4800, - STRING_TOKEN(STR_COM_BAUD_RATE_6) - }, - { - 3600, - STRING_TOKEN(STR_COM_BAUD_RATE_7) - }, - { - 2400, - STRING_TOKEN(STR_COM_BAUD_RATE_8) - }, - { - 2000, - STRING_TOKEN(STR_COM_BAUD_RATE_9) - }, - { - 1800, - STRING_TOKEN(STR_COM_BAUD_RATE_10) - }, - { - 1200, - STRING_TOKEN(STR_COM_BAUD_RATE_11) - }, - { - 600, - STRING_TOKEN(STR_COM_BAUD_RATE_12) - }, - { - 300, - STRING_TOKEN(STR_COM_BAUD_RATE_13) - }, - { - 150, - STRING_TOKEN(STR_COM_BAUD_RATE_14) - }, - { - 134, - STRING_TOKEN(STR_COM_BAUD_RATE_15) - }, - { - 110, - STRING_TOKEN(STR_COM_BAUD_RATE_16) - }, - { - 75, - STRING_TOKEN(STR_COM_BAUD_RATE_17) - }, - { - 50, - STRING_TOKEN(STR_COM_BAUD_RATE_18) - } -}; - -/// -/// Value and string token correspondency for DataBits -/// -COM_ATTR DataBitsList[4] = { - { - 5, - STRING_TOKEN(STR_COM_DATA_BITS_0) - }, - { - 6, - STRING_TOKEN(STR_COM_DATA_BITS_1) - }, - { - 7, - STRING_TOKEN(STR_COM_DATA_BITS_2) - }, - { - 8, - STRING_TOKEN(STR_COM_DATA_BITS_3) - } -}; - -/// -/// Value and string token correspondency for Parity -/// -COM_ATTR ParityList[5] = { - { - NoParity, - STRING_TOKEN(STR_COM_PAR_0) - }, - { - EvenParity, - STRING_TOKEN(STR_COM_PAR_1) - }, - { - OddParity, - STRING_TOKEN(STR_COM_PAR_2) - }, - { - MarkParity, - STRING_TOKEN(STR_COM_PAR_3) - }, - { - SpaceParity, - STRING_TOKEN(STR_COM_PAR_4) - } -}; - -/// -/// Value and string token correspondency for Baudreate -/// -COM_ATTR StopBitsList[3] = { - { - OneStopBit, - STRING_TOKEN(STR_COM_STOP_BITS_0) - }, - { - OneFiveStopBits, - STRING_TOKEN(STR_COM_STOP_BITS_1) - }, - { - TwoStopBits, - STRING_TOKEN(STR_COM_STOP_BITS_2) - } -}; - -/// -/// Guid for messaging path, used in Serial port setting. -/// -EFI_GUID TerminalTypeGuid[4] = { - DEVICE_PATH_MESSAGING_PC_ANSI, - DEVICE_PATH_MESSAGING_VT_100, - DEVICE_PATH_MESSAGING_VT_100_PLUS, - DEVICE_PATH_MESSAGING_VT_UTF8 -}; diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr deleted file mode 100644 index 056694ebef..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr +++ /dev/null @@ -1,127 +0,0 @@ -///** @file -// -// File Explorer Formset -// -// 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 -// 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 "FormGuid.h" - -formset - guid = FILE_EXPLORE_FORMSET_GUID, - title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE), - help = STRING_TOKEN(STR_NULL_STRING), - classguid = FILE_EXPLORE_FORMSET_GUID, - - varstore FILE_EXPLORER_NV_DATA, - varid = VARSTORE_ID_BOOT_MAINT, - name = FeData, - guid = FILE_EXPLORE_FORMSET_GUID; - - form formid = FORM_FILE_EXPLORER_ID, - title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); - - label FORM_FILE_EXPLORER_ID; - label LABEL_END; - endform; - - form formid = FORM_BOOT_ADD_DESCRIPTION_ID, - title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE); - - label FORM_BOOT_ADD_DESCRIPTION_ID; - label LABEL_END; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - string varid = FeData.BootDescriptionData, - questionid = KEY_VALUE_BOOT_DESCRIPTION, - prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - minsize = 6, - maxsize = 75, - endstring; - - string varid = FeData.BootOptionalData, - questionid = KEY_VALUE_BOOT_OPTION, - prompt = STRING_TOKEN(STR_OPTIONAL_DATA), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - minsize = 0, - maxsize = 120, - endstring; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - text - help = STRING_TOKEN(STR_SAVE_AND_EXIT), - text = STRING_TOKEN(STR_SAVE_AND_EXIT), - flags = INTERACTIVE, - key = KEY_VALUE_SAVE_AND_EXIT_BOOT; - - text - help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), - text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), - flags = INTERACTIVE, - key = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT; - - endform; - - form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID, - title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); - - label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; - label LABEL_END; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - string varid = FeData.DriverDescriptionData, - questionid = KEY_VALUE_DRIVER_DESCRIPTION, - prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - minsize = 6, - maxsize = 75, - endstring; - - string varid = FeData.DriverOptionalData, - questionid = KEY_VALUE_DRIVER_OPTION, - prompt = STRING_TOKEN(STR_OPTIONAL_DATA), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - minsize = 0, - maxsize = 120, - endstring; - - checkbox varid = FeData.ForceReconnect, - prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), - help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), - flags = CHECKBOX_DEFAULT, - key = 0, - endcheckbox; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - text - help = STRING_TOKEN(STR_SAVE_AND_EXIT), - text = STRING_TOKEN(STR_SAVE_AND_EXIT), - flags = INTERACTIVE, - key = KEY_VALUE_SAVE_AND_EXIT_DRIVER; //BUGBUB: allow duplicate key in one formset??? - - text - help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), - text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), - flags = INTERACTIVE, - key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER; - - endform; - -endformset; \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c deleted file mode 100644 index f804984fa9..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c +++ /dev/null @@ -1,469 +0,0 @@ -/** @file - File explorer related functions. - -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 -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 "BootMaint.h" - -/** - Update the File Explore page. - - @param CallbackData The BMM context data. - @param MenuOption Pointer to menu options to display. - -**/ -VOID -UpdateFileExplorePage ( - IN BMM_CALLBACK_DATA *CallbackData, - BM_MENU_OPTION *MenuOption - ) -{ - UINTN Index; - BM_MENU_ENTRY *NewMenuEntry; - BM_FILE_CONTEXT *NewFileContext; - EFI_FORM_ID FormId; - - NewMenuEntry = NULL; - NewFileContext = NULL; - FormId = 0; - - RefreshUpdateData (); - mStartLabel->Number = FORM_FILE_EXPLORER_ID; - - for (Index = 0; Index < MenuOption->MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); - NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; - - if (NewFileContext->IsBootLegacy) { - continue; - } - - if ((NewFileContext->IsDir) || (FileExplorerStateBootFromFile == CallbackData->FeCurrentState)) { - // - // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile. - // - HiiCreateActionOpCode ( - mStartOpCodeHandle, - (UINT16) (FILE_OPTION_OFFSET + Index), - NewMenuEntry->DisplayStringToken, - STRING_TOKEN (STR_NULL_STRING), - EFI_IFR_FLAG_CALLBACK, - 0 - ); - } else { - // - // Create Goto opcode for file in FileExplorerStateAddBootOption or FileExplorerStateAddDriverOptionState. - // - if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { - FormId = FORM_BOOT_ADD_DESCRIPTION_ID; - } else if (FileExplorerStateAddDriverOptionState == CallbackData->FeCurrentState) { - FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; - } - - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FormId, - NewMenuEntry->DisplayStringToken, - STRING_TOKEN (STR_NULL_STRING), - EFI_IFR_FLAG_CALLBACK, - (UINT16) (FILE_OPTION_GOTO_OFFSET + Index) - ); - } - } - - HiiUpdateForm ( - CallbackData->FeHiiHandle, - &gFileExploreFormSetGuid, - FORM_FILE_EXPLORER_ID, - mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID - mEndOpCodeHandle // LABEL_END - ); -} - -/** - Update the file explower page with the refershed file system. - - - @param CallbackData BMM context data - @param KeyValue Key value to identify the type of data to expect. - - @retval TRUE Inform the caller to create a callback packet to exit file explorer. - @retval FALSE Indicate that there is no need to exit file explorer. - -**/ -BOOLEAN -UpdateFileExplorer ( - IN BMM_CALLBACK_DATA *CallbackData, - IN UINT16 KeyValue - ) -{ - UINT16 FileOptionMask; - BM_MENU_ENTRY *NewMenuEntry; - BM_FILE_CONTEXT *NewFileContext; - EFI_FORM_ID FormId; - BOOLEAN ExitFileExplorer; - EFI_STATUS Status; - - NewMenuEntry = NULL; - NewFileContext = NULL; - ExitFileExplorer = FALSE; - - FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue); - - if (FileExplorerDisplayUnknown == CallbackData->FeDisplayContext) { - // - // First in, display file system. - // - BOpt_FreeMenu (&FsOptionMenu); - BOpt_FindFileSystem (CallbackData); - CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu); - - UpdateFileExplorePage (CallbackData, &FsOptionMenu); - - CallbackData->FeDisplayContext = FileExplorerDisplayFileSystem; - } else { - if (FileExplorerDisplayFileSystem == CallbackData->FeDisplayContext) { - NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask); - } else if (FileExplorerDisplayDirectory == CallbackData->FeDisplayContext) { - NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask); - } - - NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; - - if (NewFileContext->IsDir ) { - CallbackData->FeDisplayContext = FileExplorerDisplayDirectory; - - RemoveEntryList (&NewMenuEntry->Link); - BOpt_FreeMenu (&DirectoryMenu); - Status = BOpt_FindFiles (CallbackData, NewMenuEntry); - if (EFI_ERROR (Status)) { - ExitFileExplorer = TRUE; - goto exit; - } - CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu); - BOpt_DestroyMenuEntry (NewMenuEntry); - - UpdateFileExplorePage (CallbackData, &DirectoryMenu); - - } else { - switch (CallbackData->FeCurrentState) { - case FileExplorerStateBootFromFile: - // - // Restore to original mode before launching boot option. - // - BdsSetConsoleMode (FALSE); - - // - // Here boot from file - // - BootThisFile (NewFileContext); - // - // Set proper video resolution and text mode for setup. - // - BdsSetConsoleMode (TRUE); - ExitFileExplorer = TRUE; - break; - - case FileExplorerStateAddBootOption: - case FileExplorerStateAddDriverOptionState: - if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { - FormId = FORM_BOOT_ADD_DESCRIPTION_ID; - if (!CallbackData->FeFakeNvData.BootOptionChanged) { - ZeroMem (CallbackData->FeFakeNvData.BootOptionalData, sizeof (CallbackData->FeFakeNvData.BootOptionalData)); - ZeroMem (CallbackData->FeFakeNvData.BootDescriptionData, sizeof (CallbackData->FeFakeNvData.BootDescriptionData)); - } - } else { - FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; - if (!CallbackData->FeFakeNvData.DriverOptionChanged) { - ZeroMem (CallbackData->FeFakeNvData.DriverOptionalData, sizeof (CallbackData->FeFakeNvData.DriverOptionalData)); - ZeroMem (CallbackData->FeFakeNvData.DriverDescriptionData, sizeof (CallbackData->FeFakeNvData.DriverDescriptionData)); - } - } - - CallbackData->MenuEntry = NewMenuEntry; - CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath; - - // - // Create Subtitle op-code for the display string of the option. - // - RefreshUpdateData (); - mStartLabel->Number = FormId; - - HiiCreateSubTitleOpCode ( - mStartOpCodeHandle, - NewMenuEntry->DisplayStringToken, - 0, - 0, - 0 - ); - - HiiUpdateForm ( - CallbackData->FeHiiHandle, - &gFileExploreFormSetGuid, - FormId, - mStartOpCodeHandle, // Label FormId - mEndOpCodeHandle // LABEL_END - ); - break; - - default: - break; - } - } - } - exit: - return ExitFileExplorer; -} - -/** - This function applies changes in a driver's configuration. - Input is a Configuration, which has the routing data for this - driver followed by name / value configuration pairs. The driver - must apply those pairs to its configurable storage. If the - driver's configuration is stored in a linear block of data - and the driver's name / value pairs are in - format, it may use the ConfigToBlock helper function (above) to - simplify the job. Currently not implemented. - - @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param[in] Configuration A null-terminated Unicode string in - format. - @param[out] Progress A pointer to a string filled in with the - offset of the most recent '&' before the - first failing name / value pair (or the - beginn ing 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 have been distributed or are - awaiting distribution. - @retval EFI_OUT_OF_RESOURCES Not enough memory to store the - parts of the results that must be - stored awaiting possible future - protocols. - @retval EFI_INVALID_PARAMETERS Passing in a NULL for the - Results parameter would result - in this type of error. - @retval EFI_NOT_FOUND Target for the specified routing data - was not found. -**/ -EFI_STATUS -EFIAPI -FileExplorerRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ) -{ - EFI_STATUS Status; - UINTN BufferSize; - EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; - FILE_EXPLORER_NV_DATA *FeData; - BMM_CALLBACK_DATA *Private; - - if (Progress == NULL) { - return EFI_INVALID_PARAMETER; - } - *Progress = Configuration; - - if (Configuration == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check routing data in . - // Note: there is no name for Name/Value storage, only GUID will be checked - // - if (!HiiIsConfigHdrMatch (Configuration, &gFileExploreFormSetGuid, mFileExplorerStorageName)) { - return EFI_NOT_FOUND; - } - - Status = gBS->LocateProtocol ( - &gEfiHiiConfigRoutingProtocolGuid, - NULL, - (VOID**) &ConfigRouting - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Private = FE_CALLBACK_DATA_FROM_THIS (This); - // - // Get Buffer Storage data from EFI variable - // - BufferSize = sizeof (FILE_EXPLORER_NV_DATA ); - FeData = &Private->FeFakeNvData; - - // - // Convert to buffer data by helper function ConfigToBlock() - // - Status = ConfigRouting->ConfigToBlock ( - ConfigRouting, - Configuration, - (UINT8 *) FeData, - &BufferSize, - Progress - ); - ASSERT_EFI_ERROR (Status); - - if (FeData->BootDescriptionData[0] != 0x00 || FeData->BootOptionalData[0] != 0x00) { - Status = Var_UpdateBootOption (Private, FeData); - if (EFI_ERROR (Status)) { - return Status; - } - - BOpt_GetBootOptions (Private); - CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); - } - - if (FeData->DriverDescriptionData[0] != 0x00 || FeData->DriverOptionalData[0] != 0x00) { - Status = Var_UpdateDriverOption ( - Private, - Private->FeHiiHandle, - FeData->DriverDescriptionData, - FeData->DriverOptionalData, - FeData->ForceReconnect - ); - if (EFI_ERROR (Status)) { - return Status; - } - - BOpt_GetDriverOptions (Private); - CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); - } - - return EFI_SUCCESS; -} - -/** - This function processes the results of changes in configuration. - When user select a interactive opcode, this callback will be triggered. - Based on the Question(QuestionId) that triggers the callback, the corresponding - actions is performed. It handles: - - 1) the addition of boot option. - 2) the addition of driver option. - 3) exit from file browser - 4) update of file content if a dir is selected. - 5) boot the file if a file is selected in "boot from file" - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be saved. - @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. - @retval EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL. -**/ -EFI_STATUS -EFIAPI -FileExplorerCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - BMM_CALLBACK_DATA *Private; - FILE_EXPLORER_NV_DATA *NvRamMap; - EFI_STATUS Status; - - if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { - // - // All other action return unsupported. - // - return EFI_UNSUPPORTED; - } - - Status = EFI_SUCCESS; - Private = FE_CALLBACK_DATA_FROM_THIS (This); - - // - // Retrieve uncommitted data from Form Browser - // - NvRamMap = &Private->FeFakeNvData; - HiiGetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap); - - if (Action == EFI_BROWSER_ACTION_CHANGED) { - if ((Value == NULL) || (ActionRequest == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) { - NvRamMap->BootOptionChanged = FALSE; - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; - } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { - NvRamMap->DriverOptionChanged = FALSE; - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; - } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { - // - // Discard changes and exit formset - // - NvRamMap->DriverOptionalData[0] = 0x0000; - NvRamMap->DriverDescriptionData[0] = 0x0000; - NvRamMap->DriverOptionChanged = FALSE; - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) { - // - // Discard changes and exit formset - // - NvRamMap->BootOptionalData[0] = 0x0000; - NvRamMap->BootDescriptionData[0] = 0x0000; - NvRamMap->BootOptionChanged = FALSE; - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) { - NvRamMap->BootOptionChanged = TRUE; - } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) { - NvRamMap->DriverOptionChanged = TRUE; - } else if (QuestionId < FILE_OPTION_OFFSET) { - // - // Exit File Explorer formset - // - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - } else if (QuestionId >= FILE_OPTION_OFFSET && QuestionId < FILE_OPTION_GOTO_OFFSET) { - // - // Update forms may return TRUE or FALSE, need to check here. - // - if (UpdateFileExplorer (Private, QuestionId)) { - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - } - } - } else if (Action == EFI_BROWSER_ACTION_CHANGING) { - if (Value == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (QuestionId >= FILE_OPTION_GOTO_OFFSET) { - // - // function will always return FALSE, no need to check here. - // - UpdateFileExplorer (Private, QuestionId); - } - } - - // - // Pass changed uncommitted data back to Form Browser - // - HiiSetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap, NULL); - - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h deleted file mode 100644 index bf99999760..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h +++ /dev/null @@ -1,243 +0,0 @@ -/** @file - Formset guids, form id and VarStore data structure for Boot Maintenance Manager. - -Copyright (c) 2004 - 2015, Intel 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 _FORM_GUID_H_ -#define _FORM_GUID_H_ - -#include - -#define FORM_MAIN_ID 0x1001 -#define FORM_BOOT_ADD_ID 0x1002 -#define FORM_BOOT_DEL_ID 0x1003 -#define FORM_BOOT_CHG_ID 0x1004 -#define FORM_DRV_ADD_ID 0x1005 -#define FORM_DRV_DEL_ID 0x1006 -#define FORM_DRV_CHG_ID 0x1007 -#define FORM_CON_MAIN_ID 0x1008 -#define FORM_CON_IN_ID 0x1009 -#define FORM_CON_OUT_ID 0x100A -#define FORM_CON_ERR_ID 0x100B -#define FORM_FILE_SEEK_ID 0x100C -#define FORM_FILE_NEW_SEEK_ID 0x100D -#define FORM_DRV_ADD_FILE_ID 0x100E -#define FORM_DRV_ADD_HANDLE_ID 0x100F -#define FORM_DRV_ADD_HANDLE_DESC_ID 0x1010 -#define FORM_BOOT_NEXT_ID 0x1011 -#define FORM_TIME_OUT_ID 0x1012 -#define FORM_RESET 0x1013 -#define FORM_BOOT_SETUP_ID 0x1014 -#define FORM_DRIVER_SETUP_ID 0x1015 -#define FORM_BOOT_LEGACY_DEVICE_ID 0x1016 -#define FORM_CON_COM_ID 0x1017 -#define FORM_CON_COM_SETUP_ID 0x1018 -#define FORM_SET_FD_ORDER_ID 0x1019 -#define FORM_SET_HD_ORDER_ID 0x101A -#define FORM_SET_CD_ORDER_ID 0x101B -#define FORM_SET_NET_ORDER_ID 0x101C -#define FORM_SET_BEV_ORDER_ID 0x101D -#define FORM_FILE_EXPLORER_ID 0x101E -#define FORM_BOOT_ADD_DESCRIPTION_ID 0x101F -#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x1020 -#define FORM_CON_MODE_ID 0x1021 -#define FORM_BOOT_FROM_FILE_ID 0x1022 - -#define MAXIMUM_FORM_ID 0x10FF - -#define KEY_VALUE_COM_SET_BAUD_RATE 0x1101 -#define KEY_VALUE_COM_SET_DATA_BITS 0x1102 -#define KEY_VALUE_COM_SET_STOP_BITS 0x1103 -#define KEY_VALUE_COM_SET_PARITY 0x1104 -#define KEY_VALUE_COM_SET_TERMI_TYPE 0x1105 -#define KEY_VALUE_MAIN_BOOT_NEXT 0x1106 -#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x1107 -#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x1108 -#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x1109 -#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x110A -#define KEY_VALUE_SAVE_AND_EXIT 0x110B -#define KEY_VALUE_NO_SAVE_AND_EXIT 0x110C -#define KEY_VALUE_BOOT_FROM_FILE 0x110D -#define KEY_VALUE_BOOT_DESCRIPTION 0x110E -#define KEY_VALUE_BOOT_OPTION 0x110F -#define KEY_VALUE_DRIVER_DESCRIPTION 0x1110 -#define KEY_VALUE_DRIVER_OPTION 0x1111 - -#define MAXIMUM_NORMAL_KEY_VALUE 0x11FF - -// -// Varstore ID defined for Buffer Storage -// -#define VARSTORE_ID_BOOT_MAINT 0x1000 -#define VARSTORE_ID_FILE_EXPLORER 0x1001 - -// -// End Label -// -#define LABEL_END 0xffff -#define MAX_MENU_NUMBER 100 - -/// -/// This is the structure that will be used to store the -/// question's current value. Use it at initialize time to -/// set default value for each question. When using at run -/// time, this map is returned by the callback function, -/// so dynamically changing the question's value will be -/// possible through this mechanism -/// -typedef struct { - // - // Three questions displayed at the main page - // for Timeout, BootNext Variables respectively - // - UINT16 BootTimeOut; - UINT16 BootNext; - - // - // This is the COM1 Attributes value storage - // - UINT8 COM1BaudRate; - UINT8 COM1DataRate; - UINT8 COM1StopBits; - UINT8 COM1Parity; - UINT8 COM1TerminalType; - - // - // This is the COM2 Attributes value storage - // - UINT8 COM2BaudRate; - UINT8 COM2DataRate; - UINT8 COM2StopBits; - UINT8 COM2Parity; - UINT8 COM2TerminalType; - - // - // Driver Option Add Handle page storage - // - UINT16 DriverAddHandleDesc[MAX_MENU_NUMBER]; - UINT16 DriverAddHandleOptionalData[MAX_MENU_NUMBER]; - UINT8 DriverAddActive; - UINT8 DriverAddForceReconnect; - - // - // Console Input/Output/Errorout using COM port check storage - // - UINT8 ConsoleInputCOM1; - UINT8 ConsoleInputCOM2; - UINT8 ConsoleOutputCOM1; - UINT8 ConsoleOutputCOM2; - UINT8 ConsoleErrorCOM1; - UINT8 ConsoleErrorCOM2; - - // - // At most 100 input/output/errorout device for console storage - // - UINT8 ConsoleCheck[MAX_MENU_NUMBER]; - // - // At most 100 input/output/errorout device for console storage - // - UINT8 ConsoleInCheck[MAX_MENU_NUMBER]; - UINT8 ConsoleOutCheck[MAX_MENU_NUMBER]; - UINT8 ConsoleErrCheck[MAX_MENU_NUMBER]; - - // - // Boot Option Order storage - // The value is the OptionNumber+1 because the order list value cannot be 0 - // Use UINT32 to hold the potential value 0xFFFF+1=0x10000 - // - UINT32 BootOptionOrder[MAX_MENU_NUMBER]; - - // - // Driver Option Order storage - // The value is the OptionNumber+1 because the order list value cannot be 0 - // Use UINT32 to hold the potential value 0xFFFF+1=0x10000 - // - UINT32 DriverOptionOrder[MAX_MENU_NUMBER]; - - // - // Boot Option Delete storage - // - BOOLEAN BootOptionDel[MAX_MENU_NUMBER]; - BOOLEAN BootOptionDelMark[MAX_MENU_NUMBER]; - - // - // Driver Option Delete storage - // - BOOLEAN DriverOptionDel[MAX_MENU_NUMBER]; - BOOLEAN DriverOptionDelMark[MAX_MENU_NUMBER]; - - // - // This is the Terminal Attributes value storage - // - UINT8 COMBaudRate[MAX_MENU_NUMBER]; - UINT8 COMDataRate[MAX_MENU_NUMBER]; - UINT8 COMStopBits[MAX_MENU_NUMBER]; - UINT8 COMParity[MAX_MENU_NUMBER]; - UINT8 COMTerminalType[MAX_MENU_NUMBER]; - UINT8 COMFlowControl[MAX_MENU_NUMBER]; - - // - // Legacy Device Order Selection Storage - // - UINT8 LegacyFD[MAX_MENU_NUMBER]; - UINT8 LegacyHD[MAX_MENU_NUMBER]; - UINT8 LegacyCD[MAX_MENU_NUMBER]; - UINT8 LegacyNET[MAX_MENU_NUMBER]; - UINT8 LegacyBEV[MAX_MENU_NUMBER]; - - // - // We use DisableMap array to record the enable/disable state of each boot device - // It should be taken as a bit array, from left to right there are totally 256 bits - // the most left one stands for BBS table item 0, and the most right one stands for item 256 - // If the bit is 1, it means the boot device has been disabled. - // - UINT8 DisableMap[32]; - - // - // Console Output Text Mode - // - UINT16 ConsoleOutMode; - - // - // UINT16 PadArea[10]; - // -} BMM_FAKE_NV_DATA; - -// -// Key used by File Explorer forms -// -#define KEY_VALUE_SAVE_AND_EXIT_BOOT 0x1000 -#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT 0x1001 -#define KEY_VALUE_SAVE_AND_EXIT_DRIVER 0x1002 -#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER 0x1003 - -// -// Description data and optional data size -// -#define DESCRIPTION_DATA_SIZE 75 -#define OPTIONAL_DATA_SIZE 127 - -/// -/// This is the data structure used by File Explorer formset -/// -typedef struct { - UINT16 BootDescriptionData[DESCRIPTION_DATA_SIZE]; - UINT16 BootOptionalData[OPTIONAL_DATA_SIZE]; - UINT16 DriverDescriptionData[DESCRIPTION_DATA_SIZE]; - UINT16 DriverOptionalData[OPTIONAL_DATA_SIZE]; - BOOLEAN BootOptionChanged; - BOOLEAN DriverOptionChanged; - UINT8 Active; - UINT8 ForceReconnect; -} FILE_EXPLORER_NV_DATA; - -#endif - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c deleted file mode 100644 index b13ed11630..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c +++ /dev/null @@ -1,1391 +0,0 @@ -/** @file -Dynamically update the pages. - -Copyright (c) 2004 - 2015, Intel 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 "BootMaint.h" - -/** - Refresh the global UpdateData structure. - -**/ -VOID -RefreshUpdateData ( - VOID - ) -{ - // - // Free current updated date - // - if (mStartOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (mStartOpCodeHandle); - } - - // - // Create new OpCode Handle - // - mStartOpCodeHandle = HiiAllocateOpCodeHandle (); - - // - // Create Hii Extend Label OpCode as the start opcode - // - mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - -} - -/** - Add a "Go back to main page" tag in front of the form when there are no - "Apply changes" and "Discard changes" tags in the end of the form. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdatePageStart ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - RefreshUpdateData (); - mStartLabel->Number = CallbackData->BmmCurrentPageId; - - if (!(CallbackData->BmmAskSaveOrNot)) { - // - // Add a "Go back to main page" tag in front of the form when there are no - // "Apply changes" and "Discard changes" tags in the end of the form. - // - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FORM_MAIN_ID, - STRING_TOKEN (STR_FORM_GOTO_MAIN), - STRING_TOKEN (STR_FORM_GOTO_MAIN), - 0, - FORM_MAIN_ID - ); - } - -} - -/** - Create the "Apply changes" and "Discard changes" tags. And - ensure user can return to the main page. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdatePageEnd ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - // - // Create the "Apply changes" and "Discard changes" tags. - // - if (CallbackData->BmmAskSaveOrNot) { - HiiCreateSubTitleOpCode ( - mStartOpCodeHandle, - STRING_TOKEN (STR_NULL_STRING), - 0, - 0, - 0 - ); - - HiiCreateActionOpCode ( - mStartOpCodeHandle, - KEY_VALUE_SAVE_AND_EXIT, - STRING_TOKEN (STR_SAVE_AND_EXIT), - STRING_TOKEN (STR_NULL_STRING), - EFI_IFR_FLAG_CALLBACK, - 0 - ); - } - - // - // Ensure user can return to the main page. - // - HiiCreateActionOpCode ( - mStartOpCodeHandle, - KEY_VALUE_NO_SAVE_AND_EXIT, - STRING_TOKEN (STR_NO_SAVE_AND_EXIT), - STRING_TOKEN (STR_NULL_STRING), - EFI_IFR_FLAG_CALLBACK, - 0 - ); - - HiiUpdateForm ( - CallbackData->BmmHiiHandle, - &gBootMaintFormSetGuid, - CallbackData->BmmCurrentPageId, - mStartOpCodeHandle, // Label CallbackData->BmmCurrentPageId - mEndOpCodeHandle // LABEL_END - ); -} - -/** - Clean up the dynamic opcode at label and form specified by both LabelId. - - @param LabelId It is both the Form ID and Label ID for opcode deletion. - @param CallbackData The BMM context data. - -**/ -VOID -CleanUpPage ( - IN UINT16 LabelId, - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - RefreshUpdateData (); - - // - // Remove all op-codes from dynamic page - // - mStartLabel->Number = LabelId; - HiiUpdateForm ( - CallbackData->BmmHiiHandle, - &gBootMaintFormSetGuid, - LabelId, - mStartOpCodeHandle, // Label LabelId - mEndOpCodeHandle // LABEL_END - ); -} - -/** - Boot a file selected by user at File Expoloer of BMM. - - @param FileContext The file context data, which contains the device path - of the file to be boot from. - - @retval EFI_SUCCESS The function completed successfull. - @return Other value if the boot from the file fails. - -**/ -EFI_STATUS -BootThisFile ( - IN BM_FILE_CONTEXT *FileContext - ) -{ - EFI_STATUS Status; - UINTN ExitDataSize; - CHAR16 *ExitData; - BDS_COMMON_OPTION *Option; - - Option = (BDS_COMMON_OPTION *) AllocatePool (sizeof (BDS_COMMON_OPTION)); - ASSERT (Option != NULL); - Option->Description = (CHAR16 *) AllocateCopyPool (StrSize (FileContext->FileName), FileContext->FileName); - Option->DevicePath = FileContext->DevicePath; - Option->LoadOptionsSize = 0; - Option->LoadOptions = NULL; - - // - // Since current no boot from removable media directly is allowed */ - // - gST->ConOut->ClearScreen (gST->ConOut); - - ExitDataSize = 0; - - Status = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData); - - return Status; - -} - -/** - Create a list of Goto Opcode for all terminal devices logged - by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID. - - @param CallbackData The BMM context data. -**/ -VOID -UpdateConCOMPage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - UINT16 Index; - - CallbackData->BmmAskSaveOrNot = FALSE; - - UpdatePageStart (CallbackData); - - - for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); - - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FORM_CON_COM_SETUP_ID, - NewMenuEntry->DisplayStringToken, - STRING_TOKEN (STR_NULL_STRING), - EFI_IFR_FLAG_CALLBACK, - (UINT16) (TERMINAL_OPTION_OFFSET + Index) - ); - } - - UpdatePageEnd (CallbackData); -} - -/** - Create a lit of boot option from global BootOptionMenu. It - allow user to delete the boot option. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateBootDelPage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT16 Index; - - CallbackData->BmmAskSaveOrNot = TRUE; - - UpdatePageStart (CallbackData); - CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); - - ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0]))); - for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - if (NewLoadContext->IsLegacy) { - continue; - } - - NewLoadContext->Deleted = FALSE; - - if (CallbackData->BmmFakeNvData.BootOptionDel[Index] && !CallbackData->BmmFakeNvData.BootOptionDelMark[Index]) { - // - // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected - // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has - // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser - // through HiiSetBrowserData function. - // - CallbackData->BmmFakeNvData.BootOptionDel[Index] = FALSE; - } - - HiiCreateCheckBoxOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index), - NewMenuEntry->DisplayStringToken, - NewMenuEntry->HelpStringToken, - EFI_IFR_FLAG_CALLBACK, - 0, - NULL - ); - } - - UpdatePageEnd (CallbackData); -} - -/** - Create a lit of driver option from global DriverMenu. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateDrvAddHandlePage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - UINT16 Index; - - CallbackData->BmmAskSaveOrNot = FALSE; - - UpdatePageStart (CallbackData); - - for (Index = 0; Index < DriverMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); - - HiiCreateGotoOpCode ( - mStartOpCodeHandle, - FORM_DRV_ADD_HANDLE_DESC_ID, - NewMenuEntry->DisplayStringToken, - STRING_TOKEN (STR_NULL_STRING), - EFI_IFR_FLAG_CALLBACK, - (UINT16) (HANDLE_OPTION_OFFSET + Index) - ); - } - - UpdatePageEnd (CallbackData); -} - -/** - Create a lit of driver option from global DriverOptionMenu. It - allow user to delete the driver option. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateDrvDelPage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT16 Index; - - CallbackData->BmmAskSaveOrNot = TRUE; - - UpdatePageStart (CallbackData); - - CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu); - - ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0]))); - for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - NewLoadContext->Deleted = FALSE; - - if (CallbackData->BmmFakeNvData.DriverOptionDel[Index] && !CallbackData->BmmFakeNvData.DriverOptionDelMark[Index]) { - // - // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected - // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has - // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser - // through HiiSetBrowserData function. - // - CallbackData->BmmFakeNvData.DriverOptionDel[Index] = FALSE; - } - - HiiCreateCheckBoxOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index), - NewMenuEntry->DisplayStringToken, - NewMenuEntry->HelpStringToken, - EFI_IFR_FLAG_CALLBACK, - 0, - NULL - ); - } - - UpdatePageEnd (CallbackData); -} - -/** - Prepare the page to allow user to add description for - a Driver Option. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateDriverAddHandleDescPage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - - CallbackData->BmmFakeNvData.DriverAddActive = 0x01; - CallbackData->BmmFakeNvData.DriverAddForceReconnect = 0x00; - CallbackData->BmmAskSaveOrNot = TRUE; - NewMenuEntry = CallbackData->MenuEntry; - - UpdatePageStart (CallbackData); - - HiiCreateSubTitleOpCode ( - mStartOpCodeHandle, - NewMenuEntry->DisplayStringToken, - 0, - 0, - 0 - ); - - HiiCreateStringOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID, - VARSTORE_ID_BOOT_MAINT, - DRV_ADD_HANDLE_DESC_VAR_OFFSET, - STRING_TOKEN (STR_LOAD_OPTION_DESC), - STRING_TOKEN (STR_NULL_STRING), - 0, - 0, - 6, - 75, - NULL - ); - - HiiCreateCheckBoxOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID, - VARSTORE_ID_BOOT_MAINT, - DRV_ADD_RECON_VAR_OFFSET, - STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), - STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), - 0, - 0, - NULL - ); - - HiiCreateStringOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID, - VARSTORE_ID_BOOT_MAINT, - DRIVER_ADD_OPTION_VAR_OFFSET, - STRING_TOKEN (STR_OPTIONAL_DATA), - STRING_TOKEN (STR_NULL_STRING), - 0, - 0, - 6, - 75, - NULL - ); - - UpdatePageEnd (CallbackData); -} - -/** - Update console page. - - @param UpdatePageId The form ID to be updated. - @param ConsoleMenu The console menu list. - @param CallbackData The BMM context data. - -**/ -VOID -UpdateConsolePage ( - IN UINT16 UpdatePageId, - IN BM_MENU_OPTION *ConsoleMenu, - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - UINT16 Index; - UINT8 CheckFlags; - UINT8 *ConsoleCheck; - EFI_QUESTION_ID QuestionIdBase; - UINT16 VariableOffsetBase; - - UpdatePageStart (CallbackData); - - ConsoleCheck = NULL; - QuestionIdBase = 0; - VariableOffsetBase = 0; - - switch (UpdatePageId) { - case FORM_CON_IN_ID: - ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleInCheck[0]; - QuestionIdBase = CON_IN_DEVICE_QUESTION_ID; - VariableOffsetBase = CON_IN_DEVICE_VAR_OFFSET; - break; - - case FORM_CON_OUT_ID: - ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0]; - QuestionIdBase = CON_OUT_DEVICE_QUESTION_ID; - VariableOffsetBase = CON_OUT_DEVICE_VAR_OFFSET; - break; - - case FORM_CON_ERR_ID: - ConsoleCheck = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0]; - QuestionIdBase = CON_ERR_DEVICE_QUESTION_ID; - VariableOffsetBase = CON_ERR_DEVICE_VAR_OFFSET; - break; - } - ASSERT (ConsoleCheck != NULL); - - for (Index = 0; ((Index < ConsoleMenu->MenuNumber) && \ - (Index < MAX_MENU_NUMBER)) ; Index++) { - CheckFlags = 0; - if (UpdatePageId != FORM_CON_ERR_ID) { - CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT; - } - NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); - HiiCreateCheckBoxOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (QuestionIdBase + Index), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (VariableOffsetBase + Index), - NewMenuEntry->DisplayStringToken, - NewMenuEntry->HelpStringToken, - 0, - CheckFlags, - NULL - ); - } - - UpdatePageEnd (CallbackData); -} - -/** - Update the page's NV Map if user has changed the order - a list. This list can be Boot Order or Driver Order. - - @param UpdatePageId The form ID to be updated. - @param OptionMenu The new list. - @param CallbackData The BMM context data. - -**/ -VOID -UpdateOrderPage ( - IN UINT16 UpdatePageId, - IN BM_MENU_OPTION *OptionMenu, - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - UINT16 Index; - UINT16 OptionIndex; - VOID *OptionsOpCodeHandle; - BOOLEAN BootOptionFound; - UINT32 *OptionOrder; - EFI_QUESTION_ID QuestionId; - UINT16 VarOffset; - - - UpdatePageStart (CallbackData); - - CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); - - OptionOrder = NULL; - QuestionId = 0; - VarOffset = 0; - switch (UpdatePageId) { - - case FORM_BOOT_CHG_ID: - //GetBootOrder (CallbackData); - OptionOrder = CallbackData->BmmFakeNvData.BootOptionOrder; - QuestionId = BOOT_OPTION_ORDER_QUESTION_ID; - VarOffset = BOOT_OPTION_ORDER_VAR_OFFSET; - break; - - case FORM_DRV_CHG_ID: - //GetDriverOrder (CallbackData); - OptionOrder = CallbackData->BmmFakeNvData.DriverOptionOrder; - QuestionId = DRIVER_OPTION_ORDER_QUESTION_ID; - VarOffset = DRIVER_OPTION_ORDER_VAR_OFFSET; - break; - } - ASSERT (OptionOrder != NULL); - - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - NewMenuEntry = NULL; - for (OptionIndex = 0; (OptionIndex < MAX_MENU_NUMBER && OptionOrder[OptionIndex] != 0); OptionIndex++) { - BootOptionFound = FALSE; - for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); - if ((UINT32) (NewMenuEntry->OptionNumber + 1) == OptionOrder[OptionIndex]) { - BootOptionFound = TRUE; - break; - } - } - if (BootOptionFound) { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - NewMenuEntry->DisplayStringToken, - 0, - EFI_IFR_TYPE_NUM_SIZE_32, - OptionOrder[OptionIndex] - ); - } - } - - if (OptionMenu->MenuNumber > 0) { - HiiCreateOrderedListOpCode ( - mStartOpCodeHandle, // Container for dynamic created opcodes - QuestionId, // Question ID - VARSTORE_ID_BOOT_MAINT, // VarStore ID - VarOffset, // Offset in Buffer Storage - STRING_TOKEN (STR_CHANGE_ORDER), // Question prompt text - STRING_TOKEN (STR_CHANGE_ORDER), // Question help text - 0, // Question flag - 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET - EFI_IFR_TYPE_NUM_SIZE_32, // Data type of Question value - 100, // Maximum container - OptionsOpCodeHandle, // Option Opcode list - NULL // Default Opcode is NULL - ); - } - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - - UpdatePageEnd (CallbackData); -} - -/** - Create the dynamic page to allow user to set - the "BootNext" value. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateBootNextPage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINTN NumberOfOptions; - UINT16 Index; - VOID *OptionsOpCodeHandle; - - NumberOfOptions = BootOptionMenu.MenuNumber; - CallbackData->BmmAskSaveOrNot = TRUE; - - UpdatePageStart (CallbackData); - CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); - - if (NumberOfOptions > 0) { - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - //CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber); - - for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - - if (NewLoadContext->IsBootNext) { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - NewMenuEntry->DisplayStringToken, - EFI_IFR_OPTION_DEFAULT, - EFI_IFR_TYPE_NUM_SIZE_16, - Index - ); - //CallbackData->BmmFakeNvData.BootNext = Index; - } else { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - NewMenuEntry->DisplayStringToken, - 0, - EFI_IFR_TYPE_NUM_SIZE_16, - Index - ); - } - } - - if (CallbackData->BmmFakeNvData.BootNext == Index) { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - STRING_TOKEN (STR_NONE), - EFI_IFR_OPTION_DEFAULT, - EFI_IFR_TYPE_NUM_SIZE_16, - Index - ); - } else { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - STRING_TOKEN (STR_NONE), - 0, - EFI_IFR_TYPE_NUM_SIZE_16, - Index - ); - } - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID, - VARSTORE_ID_BOOT_MAINT, - BOOT_NEXT_VAR_OFFSET, - STRING_TOKEN (STR_BOOT_NEXT), - STRING_TOKEN (STR_BOOT_NEXT_HELP), - 0, - EFI_IFR_NUMERIC_SIZE_2, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - } - - UpdatePageEnd (CallbackData); -} - -/** - Create the dynamic page to allow user to set the "TimeOut" value. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateTimeOutPage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINT16 BootTimeOut; - VOID *DefaultOpCodeHandle; - - CallbackData->BmmAskSaveOrNot = TRUE; - - UpdatePageStart (CallbackData); - - BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); - - DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (DefaultOpCodeHandle != NULL); - HiiCreateDefaultOpCode (DefaultOpCodeHandle, EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_NUM_SIZE_16, BootTimeOut); - - HiiCreateNumericOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID, - VARSTORE_ID_BOOT_MAINT, - BOOT_TIME_OUT_VAR_OFFSET, - STRING_TOKEN (STR_NUM_AUTO_BOOT), - STRING_TOKEN (STR_HLP_AUTO_BOOT), - 0, - EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC, - 0, - 65535, - 0, - DefaultOpCodeHandle - ); - - HiiFreeOpCodeHandle (DefaultOpCodeHandle); - - //CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut; - - UpdatePageEnd (CallbackData); -} - -/** - Refresh the text mode page. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateConModePage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINTN Mode; - UINTN Index; - UINTN Col; - UINTN Row; - CHAR16 ModeString[50]; - CHAR16 *PStr; - UINTN MaxMode; - UINTN ValidMode; - EFI_STRING_ID *ModeToken; - EFI_STATUS Status; - VOID *OptionsOpCodeHandle; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; - - ConOut = gST->ConOut; - Index = 0; - ValidMode = 0; - MaxMode = (UINTN) (ConOut->Mode->MaxMode); - - CallbackData->BmmAskSaveOrNot = TRUE; - - UpdatePageStart (CallbackData); - - // - // Check valid mode - // - for (Mode = 0; Mode < MaxMode; Mode++) { - Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); - if (EFI_ERROR (Status)) { - continue; - } - ValidMode++; - } - - if (ValidMode == 0) { - return; - } - - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - ModeToken = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode); - ASSERT(ModeToken != NULL); - - // - // Determin which mode should be the first entry in menu - // - // GetConsoleOutMode (CallbackData); - - // - // Build text mode options - // - for (Mode = 0; Mode < MaxMode; Mode++) { - Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); - if (EFI_ERROR (Status)) { - continue; - } - - // - // Build mode string Column x Row - // - UnicodeValueToString (ModeString, 0, Col, 0); - PStr = &ModeString[0]; - StrCatS (PStr, sizeof (ModeString) / sizeof (ModeString[0]), L" x "); - PStr = PStr + StrLen (PStr); - UnicodeValueToString (PStr , 0, Row, 0); - - ModeToken[Index] = HiiSetString (CallbackData->BmmHiiHandle, 0, ModeString, NULL); - - if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - ModeToken[Index], - EFI_IFR_OPTION_DEFAULT, - EFI_IFR_TYPE_NUM_SIZE_16, - (UINT16) Mode - ); - } else { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - ModeToken[Index], - 0, - EFI_IFR_TYPE_NUM_SIZE_16, - (UINT16) Mode - ); - } - Index++; - } - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) CON_MODE_QUESTION_ID, - VARSTORE_ID_BOOT_MAINT, - CON_MODE_VAR_OFFSET, - STRING_TOKEN (STR_CON_MODE_SETUP), - STRING_TOKEN (STR_CON_MODE_SETUP), - EFI_IFR_FLAG_RESET_REQUIRED, - EFI_IFR_NUMERIC_SIZE_2, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - FreePool (ModeToken); - - UpdatePageEnd (CallbackData); -} - -/** - Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits, - Parity, Stop Bits, Terminal Type. - - @param CallbackData The BMM context data. - -**/ -VOID -UpdateTerminalPage ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - UINT8 Index; - UINT8 CheckFlags; - BM_MENU_ENTRY *NewMenuEntry; - VOID *OptionsOpCodeHandle; - UINTN CurrentTerminal; - - UpdatePageStart (CallbackData); - - CurrentTerminal = CallbackData->CurrentTerminal; - NewMenuEntry = BOpt_GetMenuEntry ( - &TerminalMenu, - CurrentTerminal - ); - - if (NewMenuEntry == NULL) { - return ; - } - - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) { - CheckFlags = 0; - if (BaudRateList[Index].Value == 115200) { - CheckFlags |= EFI_IFR_OPTION_DEFAULT; - } - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - BaudRateList[Index].StringToken, - CheckFlags, - EFI_IFR_TYPE_NUM_SIZE_8, - Index - ); - } - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (COM_BAUD_RATE_QUESTION_ID + CurrentTerminal), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (COM_BAUD_RATE_VAR_OFFSET + CurrentTerminal), - STRING_TOKEN (STR_COM_BAUD_RATE), - STRING_TOKEN (STR_COM_BAUD_RATE), - 0, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - for (Index = 0; Index < sizeof (DataBitsList) / sizeof (DataBitsList[0]); Index++) { - CheckFlags = 0; - - if (DataBitsList[Index].Value == 8) { - CheckFlags |= EFI_IFR_OPTION_DEFAULT; - } - - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - DataBitsList[Index].StringToken, - CheckFlags, - EFI_IFR_TYPE_NUM_SIZE_8, - Index - ); - } - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (COM_DATA_RATE_QUESTION_ID + CurrentTerminal), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (COM_DATA_RATE_VAR_OFFSET + CurrentTerminal), - STRING_TOKEN (STR_COM_DATA_BITS), - STRING_TOKEN (STR_COM_DATA_BITS), - 0, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - for (Index = 0; Index < sizeof (ParityList) / sizeof (ParityList[0]); Index++) { - CheckFlags = 0; - if (ParityList[Index].Value == NoParity) { - CheckFlags |= EFI_IFR_OPTION_DEFAULT; - } - - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - ParityList[Index].StringToken, - CheckFlags, - EFI_IFR_TYPE_NUM_SIZE_8, - Index - ); - } - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (COM_PARITY_QUESTION_ID + CurrentTerminal), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (COM_PARITY_VAR_OFFSET + CurrentTerminal), - STRING_TOKEN (STR_COM_PARITY), - STRING_TOKEN (STR_COM_PARITY), - 0, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - for (Index = 0; Index < sizeof (StopBitsList) / sizeof (StopBitsList[0]); Index++) { - CheckFlags = 0; - if (StopBitsList[Index].Value == OneStopBit) { - CheckFlags |= EFI_IFR_OPTION_DEFAULT; - } - - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - StopBitsList[Index].StringToken, - CheckFlags, - EFI_IFR_TYPE_NUM_SIZE_8, - Index - ); - } - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (COM_STOP_BITS_QUESTION_ID + CurrentTerminal), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (COM_STOP_BITS_VAR_OFFSET + CurrentTerminal), - STRING_TOKEN (STR_COM_STOP_BITS), - STRING_TOKEN (STR_COM_STOP_BITS), - 0, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - for (Index = 0; Index < 4; Index++) { - CheckFlags = 0; - if (Index == 0) { - CheckFlags |= EFI_IFR_OPTION_DEFAULT; - } - - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - (EFI_STRING_ID) TerminalType[Index], - CheckFlags, - EFI_IFR_TYPE_NUM_SIZE_8, - Index - ); - } - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (COM_TERMINAL_QUESTION_ID + CurrentTerminal), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (COM_TERMINAL_VAR_OFFSET + CurrentTerminal), - STRING_TOKEN (STR_COM_TERMI_TYPE), - STRING_TOKEN (STR_COM_TERMI_TYPE), - 0, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - for (Index = 0; Index < sizeof (mFlowControlType) / sizeof (mFlowControlType[0]); Index++) { - CheckFlags = 0; - if (Index == 0) { - CheckFlags |= EFI_IFR_OPTION_DEFAULT; - } - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - (EFI_STRING_ID) mFlowControlType[Index], - CheckFlags, - EFI_IFR_TYPE_NUM_SIZE_8, - mFlowControlValue[Index] - ); - } - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (COM_FLOWCONTROL_QUESTION_ID + CurrentTerminal), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (COM_FLOWCONTROL_VAR_OFFSET + CurrentTerminal), - STRING_TOKEN (STR_COM_FLOW_CONTROL), - STRING_TOKEN (STR_COM_FLOW_CONTROL), - 0, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - - UpdatePageEnd (CallbackData); -} - -/** - Dispatch the correct update page function to call based on - the UpdatePageId. - - @param UpdatePageId The form ID. - @param CallbackData The BMM context data. - -**/ -VOID -UpdatePageBody ( - IN UINT16 UpdatePageId, - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - CleanUpPage (UpdatePageId, CallbackData); - switch (UpdatePageId) { - case FORM_CON_IN_ID: - UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData); - break; - - case FORM_CON_OUT_ID: - UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData); - break; - - case FORM_CON_ERR_ID: - UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData); - break; - - case FORM_BOOT_CHG_ID: - UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData); - break; - - case FORM_DRV_CHG_ID: - UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData); - break; - - default: - break; - } -} - -/** - Create a dynamic page so that Legacy Device boot order - can be set for specified device type. - - @param UpdatePageId The form ID. It also spefies the legacy device type. - @param CallbackData The BMM context data. - - -**/ -VOID -UpdateSetLegacyDeviceOrderPage ( - IN UINT16 UpdatePageId, - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - LEGACY_DEV_ORDER_ENTRY *DevOrder; - BM_MENU_OPTION *OptionMenu; - BM_MENU_ENTRY *NewMenuEntry; - EFI_STRING_ID StrRef; - EFI_STRING_ID StrRefHelp; - BBS_TYPE BbsType; - UINTN VarSize; - UINTN Pos; - UINTN Bit; - UINT16 Index; - UINT16 Key; - CHAR16 String[100]; - CHAR16 *TypeStr; - CHAR16 *TypeStrHelp; - UINT16 VarDevOrder; - UINT8 *VarData; - UINT8 *LegacyOrder; - UINT8 *OldData; - UINT8 *DisMap; - VOID *OptionsOpCodeHandle; - - OptionMenu = NULL; - Key = 0; - StrRef = 0; - StrRefHelp = 0; - TypeStr = NULL; - TypeStrHelp = NULL; - BbsType = BBS_FLOPPY; - LegacyOrder = NULL; - OldData = NULL; - DisMap = NULL; - - CallbackData->BmmAskSaveOrNot = TRUE; - UpdatePageStart (CallbackData); - - DisMap = ZeroMem (CallbackData->BmmOldFakeNVData.DisableMap, sizeof (CallbackData->BmmOldFakeNVData.DisableMap)); - - // - // Create oneof option list - // - switch (UpdatePageId) { - case FORM_SET_FD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; - Key = (UINT16) LEGACY_FD_QUESTION_ID; - TypeStr = STR_FLOPPY; - TypeStrHelp = STR_FLOPPY_HELP; - BbsType = BBS_FLOPPY; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD; - OldData = CallbackData->BmmOldFakeNVData.LegacyFD; - break; - - case FORM_SET_HD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; - Key = (UINT16) LEGACY_HD_QUESTION_ID; - TypeStr = STR_HARDDISK; - TypeStrHelp = STR_HARDDISK_HELP; - BbsType = BBS_HARDDISK; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD; - OldData = CallbackData->BmmOldFakeNVData.LegacyHD; - break; - - case FORM_SET_CD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; - Key = (UINT16) LEGACY_CD_QUESTION_ID; - TypeStr = STR_CDROM; - TypeStrHelp = STR_CDROM_HELP; - BbsType = BBS_CDROM; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD; - OldData = CallbackData->BmmOldFakeNVData.LegacyCD; - break; - - case FORM_SET_NET_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; - Key = (UINT16) LEGACY_NET_QUESTION_ID; - TypeStr = STR_NET; - TypeStrHelp = STR_NET_HELP; - BbsType = BBS_EMBED_NETWORK; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET; - OldData = CallbackData->BmmOldFakeNVData.LegacyNET; - break; - - case FORM_SET_BEV_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; - Key = (UINT16) LEGACY_BEV_QUESTION_ID; - TypeStr = STR_BEV; - TypeStrHelp = STR_BEV_HELP; - BbsType = BBS_BEV_DEVICE; - LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV; - OldData = CallbackData->BmmOldFakeNVData.LegacyBEV; - break; - - default: - DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n")); - return; - } - - CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); - - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); - // - // Create OneOf for each legacy device - // - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - NewMenuEntry->DisplayStringToken, - 0, - EFI_IFR_TYPE_NUM_SIZE_8, - (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex - ); - } - - // - // Create OneOf for item "Disabled" - // - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE), - 0, - EFI_IFR_TYPE_NUM_SIZE_8, - 0xFF - ); - - // - // Get Device Order from variable - // - VarData = BdsLibGetVariableAndSize ( - VAR_LEGACY_DEV_ORDER, - &gEfiLegacyDevOrderVariableGuid, - &VarSize - ); - - if (NULL != VarData) { - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; - while (VarData < VarData + VarSize) { - if (DevOrder->BbsType == BbsType) { - break; - } - - VarData = (UINT8 *)((UINTN)VarData + sizeof (BBS_TYPE)); - VarData += *(UINT16 *) VarData; - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; - } - // - // Create oneof tag here for FD/HD/CD #1 #2 - // - for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { - // - // Create the string for oneof tag - // - UnicodeSPrint (String, sizeof (String), TypeStr, Index); - StrRef = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL); - - UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index); - StrRefHelp = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL); - - HiiCreateOneOfOpCode ( - mStartOpCodeHandle, - (EFI_QUESTION_ID) (Key + Index), - VARSTORE_ID_BOOT_MAINT, - (UINT16) (Key + Index - CONFIG_OPTION_OFFSET), - StrRef, - StrRefHelp, - EFI_IFR_FLAG_CALLBACK, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - VarDevOrder = *(UINT16 *) ((UINTN) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16)); - - if (0xFF00 == (VarDevOrder & 0xFF00)) { - LegacyOrder[Index] = 0xFF; - Pos = (VarDevOrder & 0xFF) / 8; - Bit = 7 - ((VarDevOrder & 0xFF) % 8); - DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); - } else { - LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF); - } - } - } - - CopyMem (OldData, LegacyOrder, 100); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - - UpdatePageEnd (CallbackData); -} - - -/** - Dispatch the display to the next page based on NewPageId. - - @param Private The BMM context data. - @param NewPageId The original page ID. - -**/ -VOID -UpdatePageId ( - BMM_CALLBACK_DATA *Private, - UINT16 NewPageId - ) -{ - // - // For the question don't impact the page update, just ignore it. - // - if (((NewPageId >= BOOT_OPTION_DEL_QUESTION_ID) && (NewPageId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) || - ((NewPageId >= DRIVER_OPTION_DEL_QUESTION_ID) && (NewPageId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER))) { - return; - } - - if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) { - // - // If we select a handle to add driver option, advance to the add handle description page. - // - NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID; - } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) { - // - // Return to main page after "Save Changes" or "Discard Changes". - // - NewPageId = FORM_MAIN_ID; - } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) { - NewPageId = FORM_CON_COM_SETUP_ID; - } - - if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) { - Private->BmmPreviousPageId = Private->BmmCurrentPageId; - Private->BmmCurrentPageId = NewPageId; - } -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c deleted file mode 100644 index b933dd9699..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c +++ /dev/null @@ -1,1380 +0,0 @@ -/** @file - Variable operation that will be used by bootmaint - -Copyright (c) 2004 - 2015, Intel 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 "BootMaint.h" - -/** - Delete Boot Option that represent a Deleted state in BootOptionMenu. - After deleting this boot option, call Var_ChangeBootOrder to - make sure BootOrder is in valid state. - - @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to - BM_LOAD_CONTEXT marked for deletion is deleted. - @retval EFI_NOT_FOUND If can not find the boot option want to be deleted. - @return Others If failed to update the "BootOrder" variable after deletion. - -**/ -EFI_STATUS -Var_DelBootOption ( - VOID - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT16 BootString[10]; - EFI_STATUS Status; - UINTN Index; - UINTN Index2; - - Status = EFI_SUCCESS; - Index2 = 0; - for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2)); - if (NULL == NewMenuEntry) { - return EFI_NOT_FOUND; - } - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - if (!NewLoadContext->Deleted) { - continue; - } - - UnicodeSPrint ( - BootString, - sizeof (BootString), - L"Boot%04x", - NewMenuEntry->OptionNumber - ); - - EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid); - Index2++; - // - // If current Load Option is the same as BootNext, - // must delete BootNext in order to make sure - // there will be no panic on next boot - // - if (NewLoadContext->IsBootNext) { - EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid); - } - - RemoveEntryList (&NewMenuEntry->Link); - BOpt_DestroyMenuEntry (NewMenuEntry); - NewMenuEntry = NULL; - } - - BootOptionMenu.MenuNumber -= Index2; - - Status = Var_ChangeBootOrder (); - return Status; -} - -/** - After any operation on Boot####, there will be a discrepancy in BootOrder. - Since some are missing but in BootOrder, while some are present but are - not reflected by BootOrder. Then a function rebuild BootOrder from - scratch by content from BootOptionMenu is needed. - - - - - @retval EFI_SUCCESS The boot order is updated successfully. - @return EFI_STATUS other than EFI_SUCCESS if failed to - Set the "BootOrder" EFI Variable. - -**/ -EFI_STATUS -Var_ChangeBootOrder ( - VOID - ) -{ - - EFI_STATUS Status; - BM_MENU_ENTRY *NewMenuEntry; - UINT16 *BootOrderList; - UINT16 *BootOrderListPtr; - UINTN BootOrderListSize; - UINTN Index; - - BootOrderList = NULL; - BootOrderListSize = 0; - - // - // First check whether BootOrder is present in current configuration - // - BootOrderList = BdsLibGetVariableAndSize ( - L"BootOrder", - &gEfiGlobalVariableGuid, - &BootOrderListSize - ); - - // - // If exists, delete it to hold new BootOrder - // - if (BootOrderList != NULL) { - EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); - FreePool (BootOrderList); - BootOrderList = NULL; - } - // - // Maybe here should be some check method to ensure that - // no new added boot options will be added - // but the setup engine now will give only one callback - // that is to say, user are granted only one chance to - // decide whether the boot option will be added or not - // there should be no indictor to show whether this - // is a "new" boot option - // - BootOrderListSize = BootOptionMenu.MenuNumber; - - if (BootOrderListSize > 0) { - BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16)); - ASSERT (BootOrderList != NULL); - BootOrderListPtr = BootOrderList; - - // - // Get all current used Boot#### from BootOptionMenu. - // OptionNumber in each BM_LOAD_OPTION is really its - // #### value. - // - for (Index = 0; Index < BootOrderListSize; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); - *BootOrderList = (UINT16) NewMenuEntry->OptionNumber; - BootOrderList++; - } - - BootOrderList = BootOrderListPtr; - - // - // After building the BootOrderList, write it back - // - Status = gRT->SetVariable ( - L"BootOrder", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - BootOrderListSize * sizeof (UINT16), - BootOrderList - ); - // - // Changing variable without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } - return EFI_SUCCESS; -} - -/** - Delete Load Option that represent a Deleted state in BootOptionMenu. - After deleting this Driver option, call Var_ChangeDriverOrder to - make sure DriverOrder is in valid state. - - @retval EFI_SUCCESS Load Option is successfully updated. - @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted. - @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI - Variable. - -**/ -EFI_STATUS -Var_DelDriverOption ( - VOID - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT16 DriverString[12]; - EFI_STATUS Status; - UINTN Index; - UINTN Index2; - - Status = EFI_SUCCESS; - Index2 = 0; - for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2)); - if (NULL == NewMenuEntry) { - return EFI_NOT_FOUND; - } - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - if (!NewLoadContext->Deleted) { - continue; - } - - UnicodeSPrint ( - DriverString, - sizeof (DriverString), - L"Driver%04x", - NewMenuEntry->OptionNumber - ); - - EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid); - Index2++; - - RemoveEntryList (&NewMenuEntry->Link); - BOpt_DestroyMenuEntry (NewMenuEntry); - NewMenuEntry = NULL; - } - - DriverOptionMenu.MenuNumber -= Index2; - - Status = Var_ChangeDriverOrder (); - return Status; -} - -/** - After any operation on Driver####, there will be a discrepancy in - DriverOrder. Since some are missing but in DriverOrder, while some - are present but are not reflected by DriverOrder. Then a function - rebuild DriverOrder from scratch by content from DriverOptionMenu is - needed. - - @retval EFI_SUCCESS The driver order is updated successfully. - @return Other status than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable. - -**/ -EFI_STATUS -Var_ChangeDriverOrder ( - VOID - ) -{ - EFI_STATUS Status; - BM_MENU_ENTRY *NewMenuEntry; - UINT16 *DriverOrderList; - UINT16 *DriverOrderListPtr; - UINTN DriverOrderListSize; - UINTN Index; - - DriverOrderList = NULL; - DriverOrderListSize = 0; - - // - // First check whether DriverOrder is present in current configuration - // - DriverOrderList = BdsLibGetVariableAndSize ( - L"DriverOrder", - &gEfiGlobalVariableGuid, - &DriverOrderListSize - ); - - // - // If exists, delete it to hold new DriverOrder - // - if (DriverOrderList != NULL) { - EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); - FreePool (DriverOrderList); - DriverOrderList = NULL; - } - - DriverOrderListSize = DriverOptionMenu.MenuNumber; - - if (DriverOrderListSize > 0) { - DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16)); - ASSERT (DriverOrderList != NULL); - DriverOrderListPtr = DriverOrderList; - - // - // Get all current used Driver#### from DriverOptionMenu. - // OptionNumber in each BM_LOAD_OPTION is really its - // #### value. - // - for (Index = 0; Index < DriverOrderListSize; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); - *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber; - DriverOrderList++; - } - - DriverOrderList = DriverOrderListPtr; - - // - // After building the DriverOrderList, write it back - // - Status = gRT->SetVariable ( - L"DriverOrder", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - DriverOrderListSize * sizeof (UINT16), - DriverOrderList - ); - // - // Changing variable without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } - return EFI_SUCCESS; -} - -/** - Update the device path of "ConOut", "ConIn" and "ErrOut" - based on the new BaudRate, Data Bits, parity and Stop Bits - set. - -**/ -VOID -Var_UpdateAllConsoleOption ( - VOID - ) -{ - EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; - EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; - EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; - EFI_STATUS Status; - - OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid); - InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid); - ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid); - if (OutDevicePath != NULL) { - ChangeVariableDevicePath (OutDevicePath); - Status = gRT->SetVariable ( - L"ConOut", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - GetDevicePathSize (OutDevicePath), - OutDevicePath - ); - // - // Changing variable without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } - - if (InpDevicePath != NULL) { - ChangeVariableDevicePath (InpDevicePath); - Status = gRT->SetVariable ( - L"ConIn", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - GetDevicePathSize (InpDevicePath), - InpDevicePath - ); - // - // Changing variable without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } - - if (ErrDevicePath != NULL) { - ChangeVariableDevicePath (ErrDevicePath); - Status = gRT->SetVariable ( - L"ErrOut", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - GetDevicePathSize (ErrDevicePath), - ErrDevicePath - ); - // - // Changing variable without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } -} - -/** - This function delete and build multi-instance device path for - specified type of console device. - - This function clear the EFI variable defined by ConsoleName and - gEfiGlobalVariableGuid. It then build the multi-instance device - path by appending the device path of the Console (In/Out/Err) instance - in ConsoleMenu. Then it scan all corresponding console device by - scanning Terminal (built from device supporting Serial I/O instances) - devices in TerminalMenu. At last, it save a EFI variable specifed - by ConsoleName and gEfiGlobalVariableGuid. - - @param ConsoleName The name for the console device type. They are - usually "ConIn", "ConOut" and "ErrOut". - @param ConsoleMenu The console memu which is a list of console devices. - @param UpdatePageId The flag specifying which type of console device - to be processed. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. - -**/ -EFI_STATUS -Var_UpdateConsoleOption ( - IN UINT16 *ConsoleName, - IN BM_MENU_OPTION *ConsoleMenu, - IN UINT16 UpdatePageId - ) -{ - EFI_DEVICE_PATH_PROTOCOL *ConDevicePath; - BM_MENU_ENTRY *NewMenuEntry; - BM_CONSOLE_CONTEXT *NewConsoleContext; - BM_TERMINAL_CONTEXT *NewTerminalContext; - EFI_STATUS Status; - VENDOR_DEVICE_PATH Vendor; - EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath; - UINTN Index; - - ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid); - if (ConDevicePath != NULL) { - EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid); - FreePool (ConDevicePath); - ConDevicePath = NULL; - }; - - // - // First add all console input device from console input menu - // - for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); - - NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; - if (NewConsoleContext->IsActive) { - ConDevicePath = AppendDevicePathInstance ( - ConDevicePath, - NewConsoleContext->DevicePath - ); - } - } - - for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); - - NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; - if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) || - ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) || - ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID)) - ) { - Vendor.Header.Type = MESSAGING_DEVICE_PATH; - Vendor.Header.SubType = MSG_VENDOR_DP; - - ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0]))); - CopyMem ( - &Vendor.Guid, - &TerminalTypeGuid[NewTerminalContext->TerminalType], - sizeof (EFI_GUID) - ); - SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); - TerminalDevicePath = AppendDevicePathNode ( - NewTerminalContext->DevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) &Vendor - ); - ASSERT (TerminalDevicePath != NULL); - ChangeTerminalDevicePath (&TerminalDevicePath, TRUE); - ConDevicePath = AppendDevicePathInstance ( - ConDevicePath, - TerminalDevicePath - ); - } - } - - if (ConDevicePath != NULL) { - Status = gRT->SetVariable ( - ConsoleName, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - GetDevicePathSize (ConDevicePath), - ConDevicePath - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; - -} - -/** - This function delete and build multi-instance device path ConIn - console device. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. -**/ -EFI_STATUS -Var_UpdateConsoleInpOption ( - VOID - ) -{ - return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID); -} - -/** - This function delete and build multi-instance device path ConOut - console device. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. -**/ -EFI_STATUS -Var_UpdateConsoleOutOption ( - VOID - ) -{ - return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID); -} - -/** - This function delete and build multi-instance device path ErrOut - console device. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. -**/ -EFI_STATUS -Var_UpdateErrorOutOption ( - VOID - ) -{ - return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID); -} - -/** - This function create a currently loaded Drive Option from - the BMM. It then appends this Driver Option to the end of - the "DriverOrder" list. It append this Driver Opotion to the end - of DriverOptionMenu. - - @param CallbackData The BMM context data. - @param HiiHandle The HII handle associated with the BMM formset. - @param DescriptionData The description of this driver option. - @param OptionalData The optional load option. - @param ForceReconnect If to force reconnect. - - @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. - @retval EFI_SUCCESS If function completes successfully. - -**/ -EFI_STATUS -Var_UpdateDriverOption ( - IN BMM_CALLBACK_DATA *CallbackData, - IN EFI_HII_HANDLE HiiHandle, - IN UINT16 *DescriptionData, - IN UINT16 *OptionalData, - IN UINT8 ForceReconnect - ) -{ - UINT16 Index; - UINT16 *DriverOrderList; - UINT16 *NewDriverOrderList; - UINT16 DriverString[12]; - UINTN DriverOrderListSize; - VOID *Buffer; - UINTN BufferSize; - UINT8 *Ptr; - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - BOOLEAN OptionalDataExist; - EFI_STATUS Status; - - OptionalDataExist = FALSE; - - Index = BOpt_GetDriverOptionNumber (); - UnicodeSPrint ( - DriverString, - sizeof (DriverString), - L"Driver%04x", - Index - ); - - if (*DescriptionData == 0x0000) { - StrCpyS (DescriptionData, DESCRIPTION_DATA_SIZE, DriverString); - } - - BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData); - BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); - - if (*OptionalData != 0x0000) { - OptionalDataExist = TRUE; - BufferSize += StrSize (OptionalData); - } - - Buffer = AllocateZeroPool (BufferSize); - if (NULL == Buffer) { - return EFI_OUT_OF_RESOURCES; - } - - NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); - if (NULL == NewMenuEntry) { - FreePool (Buffer); - return EFI_OUT_OF_RESOURCES; - } - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - NewLoadContext->Deleted = FALSE; - NewLoadContext->LoadOptionSize = BufferSize; - Ptr = (UINT8 *) Buffer; - NewLoadContext->LoadOption = Ptr; - *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1); - NewLoadContext->Attributes = *((UINT32 *) Ptr); - NewLoadContext->IsActive = TRUE; - NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); - - Ptr += sizeof (UINT32); - *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); - NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); - - Ptr += sizeof (UINT16); - CopyMem ( - Ptr, - DescriptionData, - StrSize (DescriptionData) - ); - - NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData)); - ASSERT (NewLoadContext->Description != NULL); - NewMenuEntry->DisplayString = NewLoadContext->Description; - CopyMem ( - NewLoadContext->Description, - (VOID *) Ptr, - StrSize (DescriptionData) - ); - - Ptr += StrSize (DescriptionData); - CopyMem ( - Ptr, - CallbackData->LoadContext->FilePathList, - GetDevicePathSize (CallbackData->LoadContext->FilePathList) - ); - - NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); - ASSERT (NewLoadContext->FilePathList != NULL); - - CopyMem ( - NewLoadContext->FilePathList, - (VOID *) Ptr, - GetDevicePathSize (CallbackData->LoadContext->FilePathList) - ); - - NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); - NewMenuEntry->OptionNumber = Index; - NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( - CallbackData, - DriverOptionStrDepository - ); - NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL); - - NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( - CallbackData, - DriverOptionHelpStrDepository - ); - NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL); - - if (OptionalDataExist) { - Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); - - CopyMem ( - Ptr, - OptionalData, - StrSize (OptionalData) - ); - } - - Status = gRT->SetVariable ( - DriverString, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - BufferSize, - Buffer - ); - if (!EFI_ERROR (Status)) { - DriverOrderList = BdsLibGetVariableAndSize ( - L"DriverOrder", - &gEfiGlobalVariableGuid, - &DriverOrderListSize - ); - NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16)); - ASSERT (NewDriverOrderList != NULL); - if (DriverOrderList != NULL) { - CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize); - EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); - } - NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index; - - Status = gRT->SetVariable ( - L"DriverOrder", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - DriverOrderListSize + sizeof (UINT16), - NewDriverOrderList - ); - if (DriverOrderList != NULL) { - FreePool (DriverOrderList); - } - DriverOrderList = NULL; - FreePool (NewDriverOrderList); - if (!EFI_ERROR (Status)) { - InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); - DriverOptionMenu.MenuNumber++; - - // - // Update "change boot order" page used data, append the new add boot - // option at the end. - // - Index = 0; - while (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] != 0) { - Index++; - } - CallbackData->BmmFakeNvData.DriverOptionOrder[Index] = (UINT32) (NewMenuEntry->OptionNumber + 1); - - *DescriptionData = 0x0000; - *OptionalData = 0x0000; - } - } - return EFI_SUCCESS; -} - -/** - This function create a currently loaded Boot Option from - the BMM. It then appends this Boot Option to the end of - the "BootOrder" list. It also append this Boot Opotion to the end - of BootOptionMenu. - - @param CallbackData The BMM context data. - @param NvRamMap The file explorer formset internal state. - - @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. - @retval EFI_SUCCESS If function completes successfully. - -**/ -EFI_STATUS -Var_UpdateBootOption ( - IN BMM_CALLBACK_DATA *CallbackData, - IN FILE_EXPLORER_NV_DATA *NvRamMap - ) -{ - UINT16 *BootOrderList; - UINT16 *NewBootOrderList; - UINTN BootOrderListSize; - UINT16 BootString[10]; - VOID *Buffer; - UINTN BufferSize; - UINT8 *Ptr; - UINT16 Index; - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - BOOLEAN OptionalDataExist; - EFI_STATUS Status; - - OptionalDataExist = FALSE; - - Index = BOpt_GetBootOptionNumber () ; - UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index); - - if (NvRamMap->BootDescriptionData[0] == 0x0000) { - StrCpyS ( - NvRamMap->BootDescriptionData, - sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), - BootString - ); - } - - BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->BootDescriptionData); - BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); - - if (NvRamMap->BootOptionalData[0] != 0x0000) { - OptionalDataExist = TRUE; - BufferSize += StrSize (NvRamMap->BootOptionalData); - } - - Buffer = AllocateZeroPool (BufferSize); - if (NULL == Buffer) { - return EFI_OUT_OF_RESOURCES; - } - - NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); - if (NULL == NewMenuEntry) { - return EFI_OUT_OF_RESOURCES; - } - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - NewLoadContext->Deleted = FALSE; - NewLoadContext->LoadOptionSize = BufferSize; - Ptr = (UINT8 *) Buffer; - NewLoadContext->LoadOption = Ptr; - *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; - NewLoadContext->Attributes = *((UINT32 *) Ptr); - NewLoadContext->IsActive = TRUE; - NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); - - Ptr += sizeof (UINT32); - *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); - NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); - Ptr += sizeof (UINT16); - - CopyMem ( - Ptr, - NvRamMap->BootDescriptionData, - StrSize (NvRamMap->BootDescriptionData) - ); - - NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData)); - ASSERT (NewLoadContext->Description != NULL); - - NewMenuEntry->DisplayString = NewLoadContext->Description; - CopyMem ( - NewLoadContext->Description, - (VOID *) Ptr, - StrSize (NvRamMap->BootDescriptionData) - ); - - Ptr += StrSize (NvRamMap->BootDescriptionData); - CopyMem ( - Ptr, - CallbackData->LoadContext->FilePathList, - GetDevicePathSize (CallbackData->LoadContext->FilePathList) - ); - - NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); - ASSERT (NewLoadContext->FilePathList != NULL); - - CopyMem ( - NewLoadContext->FilePathList, - (VOID *) Ptr, - GetDevicePathSize (CallbackData->LoadContext->FilePathList) - ); - - NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); - NewMenuEntry->OptionNumber = Index; - NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( - CallbackData, - BootOptionStrDepository - ); - NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL); - - NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( - CallbackData, - BootOptionHelpStrDepository - ); - NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->HelpString, NULL); - - if (OptionalDataExist) { - Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); - - CopyMem (Ptr, NvRamMap->BootOptionalData, StrSize (NvRamMap->BootOptionalData)); - } - - Status = gRT->SetVariable ( - BootString, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - BufferSize, - Buffer - ); - if (!EFI_ERROR (Status)) { - - BootOrderList = BdsLibGetVariableAndSize ( - L"BootOrder", - &gEfiGlobalVariableGuid, - &BootOrderListSize - ); - ASSERT (BootOrderList != NULL); - NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16)); - ASSERT (NewBootOrderList != NULL); - CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize); - NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index; - - if (BootOrderList != NULL) { - FreePool (BootOrderList); - } - - Status = gRT->SetVariable ( - L"BootOrder", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - BootOrderListSize + sizeof (UINT16), - NewBootOrderList - ); - if (!EFI_ERROR (Status)) { - - FreePool (NewBootOrderList); - NewBootOrderList = NULL; - InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); - BootOptionMenu.MenuNumber++; - - // - // Update "change driver order" page used data, append the new add driver - // option at the end. - // - Index = 0; - while (CallbackData->BmmFakeNvData.BootOptionOrder[Index] != 0) { - Index++; - } - CallbackData->BmmFakeNvData.BootOptionOrder[Index] = (UINT32) (NewMenuEntry->OptionNumber + 1); - - NvRamMap->BootDescriptionData[0] = 0x0000; - NvRamMap->BootOptionalData[0] = 0x0000; - } - } - return EFI_SUCCESS; -} - -/** - This function update the "BootNext" EFI Variable. If there is - no "BootNext" specified in BMM, this EFI Variable is deleted. - It also update the BMM context data specified the "BootNext" - vaule. - - @param CallbackData The BMM context data. - - @retval EFI_SUCCESS The function complete successfully. - @return The EFI variable can be saved. See gRT->SetVariable - for detail return information. - -**/ -EFI_STATUS -Var_UpdateBootNext ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - BMM_FAKE_NV_DATA *CurrentFakeNVMap; - UINT16 Index; - EFI_STATUS Status; - - Status = EFI_SUCCESS; - CurrentFakeNVMap = &CallbackData->BmmFakeNvData; - for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); - ASSERT (NULL != NewMenuEntry); - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - NewLoadContext->IsBootNext = FALSE; - } - - if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) { - EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid); - return EFI_SUCCESS; - } - - NewMenuEntry = BOpt_GetMenuEntry ( - &BootOptionMenu, - CurrentFakeNVMap->BootNext - ); - ASSERT (NewMenuEntry != NULL); - - NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; - Status = gRT->SetVariable ( - L"BootNext", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - sizeof (UINT16), - &NewMenuEntry->OptionNumber - ); - NewLoadContext->IsBootNext = TRUE; - CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext; - return Status; -} - -/** - This function update the "BootOrder" EFI Variable based on - BMM Formset's NV map. It then refresh BootOptionMenu - with the new "BootOrder" list. - - @param CallbackData The BMM context data. - - @retval EFI_SUCCESS The function complete successfully. - @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. - -**/ -EFI_STATUS -Var_UpdateBootOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - EFI_STATUS Status; - UINT16 Index; - UINT16 OrderIndex; - UINT16 *BootOrderList; - UINTN BootOrderListSize; - UINT16 OptionNumber; - - BootOrderList = NULL; - BootOrderListSize = 0; - - // - // First check whether BootOrder is present in current configuration - // - BootOrderList = BdsLibGetVariableAndSize ( - L"BootOrder", - &gEfiGlobalVariableGuid, - &BootOrderListSize - ); - if (BootOrderList == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0]))); - - for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) { - for (Index = OrderIndex; Index < BootOrderListSize / sizeof (UINT16); Index++) { - if ((BootOrderList[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) { - OptionNumber = BootOrderList[Index]; - CopyMem (&BootOrderList[OrderIndex + 1], &BootOrderList[OrderIndex], (Index - OrderIndex) * sizeof (UINT16)); - BootOrderList[OrderIndex] = OptionNumber; - } - } - } - - Status = gRT->SetVariable ( - L"BootOrder", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - BootOrderListSize, - BootOrderList - ); - // - // Changing the content without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - FreePool (BootOrderList); - - GroupMultipleLegacyBootOption4SameType (); - - BOpt_FreeMenu (&BootOptionMenu); - BOpt_GetBootOptions (CallbackData); - - return Status; - -} - -/** - This function update the "DriverOrder" EFI Variable based on - BMM Formset's NV map. It then refresh DriverOptionMenu - with the new "DriverOrder" list. - - @param CallbackData The BMM context data. - - @retval EFI_SUCCESS The function complete successfully. - @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. - @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. - -**/ -EFI_STATUS -Var_UpdateDriverOrder ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - EFI_STATUS Status; - UINT16 Index; - UINT16 *DriverOrderList; - UINT16 *NewDriverOrderList; - UINTN DriverOrderListSize; - - DriverOrderList = NULL; - DriverOrderListSize = 0; - - // - // First check whether DriverOrder is present in current configuration - // - DriverOrderList = BdsLibGetVariableAndSize ( - L"DriverOrder", - &gEfiGlobalVariableGuid, - &DriverOrderListSize - ); - - NewDriverOrderList = AllocateZeroPool (DriverOrderListSize); - - if (NewDriverOrderList == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // If exists, delete it to hold new DriverOrder - // - if (DriverOrderList != NULL) { - EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); - FreePool (DriverOrderList); - } - - ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0]))); - for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { - NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1); - } - - Status = gRT->SetVariable ( - L"DriverOrder", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - DriverOrderListSize, - NewDriverOrderList - ); - // - // Changing the content without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - BOpt_FreeMenu (&DriverOptionMenu); - BOpt_GetDriverOptions (CallbackData); - return EFI_SUCCESS; -} - -/** - Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable - is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid - is also updated. - - @param CallbackData The context data for BMM. - @param FormId The form id. - - @return EFI_SUCCESS The function completed successfully. - @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found. - @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource -**/ -EFI_STATUS -Var_UpdateBBSOption ( - IN BMM_CALLBACK_DATA *CallbackData, - IN EFI_FORM_ID FormId - ) -{ - UINTN Index; - UINTN Index2; - VOID *BootOptionVar; - CHAR16 VarName[100]; - UINTN OptionSize; - EFI_STATUS Status; - UINT32 *Attribute; - BM_MENU_OPTION *OptionMenu; - UINT8 *LegacyDev; - UINT8 *VarData; - UINTN VarSize; - LEGACY_DEV_ORDER_ENTRY *DevOrder; - UINT8 *OriginalPtr; - UINT8 *DisMap; - UINTN Pos; - UINTN Bit; - UINT16 *NewOrder; - UINT16 Tmp; - UINT16 *EnBootOption; - UINTN EnBootOptionCount; - UINT16 *DisBootOption; - UINTN DisBootOptionCount; - - DisMap = NULL; - NewOrder = NULL; - - switch (FormId) { - case FORM_SET_FD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; - LegacyDev = CallbackData->BmmFakeNvData.LegacyFD; - CallbackData->BbsType = BBS_FLOPPY; - break; - - case FORM_SET_HD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; - LegacyDev = CallbackData->BmmFakeNvData.LegacyHD; - CallbackData->BbsType = BBS_HARDDISK; - break; - - case FORM_SET_CD_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; - LegacyDev = CallbackData->BmmFakeNvData.LegacyCD; - CallbackData->BbsType = BBS_CDROM; - break; - - case FORM_SET_NET_ORDER_ID: - OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; - LegacyDev = CallbackData->BmmFakeNvData.LegacyNET; - CallbackData->BbsType = BBS_EMBED_NETWORK; - break; - - default: - ASSERT (FORM_SET_BEV_ORDER_ID == CallbackData->BmmPreviousPageId); - OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; - LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV; - CallbackData->BbsType = BBS_BEV_DEVICE; - break; - } - - DisMap = CallbackData->BmmOldFakeNVData.DisableMap; - Status = EFI_SUCCESS; - - - // - // Update the Variable "LegacyDevOrder" - // - VarData = (UINT8 *) BdsLibGetVariableAndSize ( - VAR_LEGACY_DEV_ORDER, - &gEfiLegacyDevOrderVariableGuid, - &VarSize - ); - - if (VarData == NULL) { - return EFI_NOT_FOUND; - } - - OriginalPtr = VarData; - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; - - while (VarData < OriginalPtr + VarSize) { - if (DevOrder->BbsType == CallbackData->BbsType) { - break; - } - - VarData += sizeof (BBS_TYPE) + DevOrder->Length; - DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; - } - - if (VarData >= OriginalPtr + VarSize) { - FreePool (OriginalPtr); - return EFI_NOT_FOUND; - } - - NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length)); - if (NewOrder == NULL) { - FreePool (OriginalPtr); - return EFI_OUT_OF_RESOURCES; - } - - for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { - if (0xFF == LegacyDev[Index]) { - break; - } - - NewOrder[Index] = LegacyDev[Index]; - } - // - // Only the enable/disable state of each boot device with same device type can be changed, - // so we can count on the index information in DevOrder. - // DisMap bit array is the only reliable source to check a device's en/dis state, - // so we use DisMap to set en/dis state of each item in NewOrder array - // - for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) { - Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF); - Pos = Tmp / 8; - Bit = 7 - (Tmp % 8); - if ((DisMap[Pos] & (1 << Bit)) != 0) { - NewOrder[Index] = (UINT16) (0xFF00 | Tmp); - Index++; - } - } - - CopyMem ( - DevOrder->Data, - NewOrder, - DevOrder->Length - sizeof (DevOrder->Length) - ); - FreePool (NewOrder); - - Status = gRT->SetVariable ( - VAR_LEGACY_DEV_ORDER, - &gEfiLegacyDevOrderVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, - VarSize, - OriginalPtr - ); - - - // - // Update BootOrder and Boot####.Attribute - // - // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order - // - ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1); - - OrderLegacyBootOption4SameType ( - DevOrder->Data, - DevOrder->Length / sizeof (UINT16) - 1, - &EnBootOption, - &EnBootOptionCount, - &DisBootOption, - &DisBootOptionCount - ); - - // - // 2. Deactivate the DisBootOption and activate the EnBootOption - // - for (Index = 0; Index < DisBootOptionCount; Index++) { - UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]); - BootOptionVar = BdsLibGetVariableAndSize ( - VarName, - &gEfiGlobalVariableGuid, - &OptionSize - ); - if (BootOptionVar != NULL) { - Attribute = (UINT32 *) BootOptionVar; - *Attribute &= ~LOAD_OPTION_ACTIVE; - - Status = gRT->SetVariable ( - VarName, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - OptionSize, - BootOptionVar - ); - // - // Changing the content without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - FreePool (BootOptionVar); - } - } - - for (Index = 0; Index < EnBootOptionCount; Index++) { - UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]); - BootOptionVar = BdsLibGetVariableAndSize ( - VarName, - &gEfiGlobalVariableGuid, - &OptionSize - ); - if (BootOptionVar != NULL) { - Attribute = (UINT32 *) BootOptionVar; - *Attribute |= LOAD_OPTION_ACTIVE; - - Status = gRT->SetVariable ( - VarName, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - OptionSize, - BootOptionVar - ); - // - // Changing the content without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - FreePool (BootOptionVar); - } - } - - BOpt_GetBootOptions (CallbackData); - - FreePool (OriginalPtr); - FreePool (EnBootOption); - FreePool (DisBootOption); - return Status; -} - -/** - Update the Text Mode of Console. - - @param CallbackData The context data for BMM. - - @retval EFI_SUCCSS If the Text Mode of Console is updated. - @return Other value if the Text Mode of Console is not updated. - -**/ -EFI_STATUS -Var_UpdateConMode ( - IN BMM_CALLBACK_DATA *CallbackData - ) -{ - EFI_STATUS Status; - UINTN Mode; - CONSOLE_OUT_MODE ModeInfo; - - Mode = CallbackData->BmmFakeNvData.ConsoleOutMode; - - Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row)); - if (!EFI_ERROR(Status)) { - Status = PcdSet32S (PcdSetupConOutColumn, (UINT32) ModeInfo.Column); - if (!EFI_ERROR (Status)){ - Status = PcdSet32S (PcdSetupConOutRow, (UINT32) ModeInfo.Row); - } - } - - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c deleted file mode 100644 index 6efd783ab2..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c +++ /dev/null @@ -1,399 +0,0 @@ -/** @file - The platform boot manager reference implementation - -Copyright (c) 2004 - 2015, Intel 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 "BootManager.h" - -UINT16 mKeyInput; -LIST_ENTRY mBootOptionsList; -BDS_COMMON_OPTION *gOption; -CHAR16 *mDeviceTypeStr[] = { - L"Legacy BEV", - L"Legacy Floppy", - L"Legacy Hard Drive", - L"Legacy CD ROM", - L"Legacy PCMCIA", - L"Legacy USB", - L"Legacy Embedded Network", - L"Legacy Unknown Device" -}; - - -HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - BOOT_MANAGER_FORMSET_GUID - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - (UINT8) (END_DEVICE_PATH_LENGTH), - (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) - } - } -}; - -BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = { - BOOT_MANAGER_CALLBACK_DATA_SIGNATURE, - NULL, - NULL, - { - FakeExtractConfig, - FakeRouteConfig, - BootManagerCallback - } -}; - -/** - This call back function is registered with Boot Manager formset. - When user selects a boot option, this call back function will - be triggered. The boot option is saved for later processing. - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. - -**/ -EFI_STATUS -EFIAPI -BootManagerCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - BDS_COMMON_OPTION *Option; - LIST_ENTRY *Link; - UINT16 KeyCount; - - if (Action == EFI_BROWSER_ACTION_CHANGED) { - if ((Value == NULL) || (ActionRequest == NULL)) { - return EFI_INVALID_PARAMETER; - } - - // - // Initialize the key count - // - KeyCount = 0; - - for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) { - Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); - - KeyCount++; - - gOption = Option; - - // - // Is this device the one chosen? - // - if (KeyCount == QuestionId) { - // - // Assigning the returned Key to a global allows the original routine to know what was chosen - // - mKeyInput = QuestionId; - - // - // Request to exit SendForm(), so that we could boot the selected option - // - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - break; - } - } - - return EFI_SUCCESS; - } - - // - // All other action return unsupported. - // - return EFI_UNSUPPORTED; -} - -/** - - Registers HII packages for the Boot Manger to HII Database. - It also registers the browser call back function. - - @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully. - @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered. - -**/ -EFI_STATUS -InitializeBootManager ( - VOID - ) -{ - EFI_STATUS Status; - - // - // Install Device Path Protocol and Config Access protocol to driver handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &gBootManagerPrivate.DriverHandle, - &gEfiDevicePathProtocolGuid, - &mBootManagerHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &gBootManagerPrivate.ConfigAccess, - NULL - ); - ASSERT_EFI_ERROR (Status); - - // - // Publish our HII data - // - gBootManagerPrivate.HiiHandle = HiiAddPackages ( - &gBootManagerFormSetGuid, - gBootManagerPrivate.DriverHandle, - BootManagerVfrBin, - BdsDxeStrings, - NULL - ); - if (gBootManagerPrivate.HiiHandle == NULL) { - Status = EFI_OUT_OF_RESOURCES; - } else { - Status = EFI_SUCCESS; - } - return Status; -} - -/** - This function invokes Boot Manager. If all devices have not a chance to be connected, - the connect all will be triggered. It then enumerate all boot options. If - a boot option from the Boot Manager page is selected, Boot Manager will boot - from this boot option. - -**/ -VOID -CallBootManager ( - VOID - ) -{ - EFI_STATUS Status; - BDS_COMMON_OPTION *Option; - LIST_ENTRY *Link; - CHAR16 *ExitData; - UINTN ExitDataSize; - EFI_STRING_ID Token; - EFI_INPUT_KEY Key; - CHAR16 *HelpString; - UINTN HelpSize; - EFI_STRING_ID HelpToken; - UINT16 *TempStr; - EFI_HII_HANDLE HiiHandle; - EFI_BROWSER_ACTION_REQUEST ActionRequest; - VOID *StartOpCodeHandle; - VOID *EndOpCodeHandle; - EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *EndLabel; - UINT16 DeviceType; - BOOLEAN IsLegacyOption; - BOOLEAN NeedEndOp; - - DeviceType = (UINT16) -1; - gOption = NULL; - InitializeListHead (&mBootOptionsList); - - // - // Connect all prior to entering the platform setup menu. - // - if (!gConnectAllHappened) { - BdsLibConnectAllDriversToAllControllers (); - gConnectAllHappened = TRUE; - } - - BdsLibEnumerateAllBootOption (&mBootOptionsList); - - // - // Group the legacy boot options for the same device type - // - GroupMultipleLegacyBootOption4SameType (); - - InitializeListHead (&mBootOptionsList); - BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder"); - - HiiHandle = gBootManagerPrivate.HiiHandle; - - // - // Allocate space for creation of UpdateData Buffer - // - StartOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (StartOpCodeHandle != NULL); - - EndOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (EndOpCodeHandle != NULL); - - // - // Create Hii Extend Label OpCode as the start opcode - // - StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - StartLabel->Number = LABEL_BOOT_OPTION; - - // - // Create Hii Extend Label OpCode as the end opcode - // - EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabel->Number = LABEL_BOOT_OPTION_END; - - mKeyInput = 0; - NeedEndOp = FALSE; - for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) { - Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); - - // - // At this stage we are creating a menu entry, thus the Keys are reproduceable - // - mKeyInput++; - - // - // Don't display the hidden/inactive boot option - // - if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) { - continue; - } - - // - // Group the legacy boot option in the sub title created dynamically - // - IsLegacyOption = (BOOLEAN) ( - (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) && - (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP) - ); - - if (!IsLegacyOption && NeedEndOp) { - NeedEndOp = FALSE; - HiiCreateEndOpCode (StartOpCodeHandle); - } - - if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) { - if (NeedEndOp) { - HiiCreateEndOpCode (StartOpCodeHandle); - } - - DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType; - Token = HiiSetString ( - HiiHandle, - 0, - mDeviceTypeStr[ - MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1) - ], - NULL - ); - HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); - NeedEndOp = TRUE; - } - - ASSERT (Option->Description != NULL); - - Token = HiiSetString (HiiHandle, 0, Option->Description, NULL); - - TempStr = DevicePathToStr (Option->DevicePath); - HelpSize = StrSize (TempStr) + StrSize (L"Device Path : "); - HelpString = AllocateZeroPool (HelpSize); - ASSERT (HelpString != NULL); - StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : "); - StrCatS (HelpString, HelpSize / sizeof (CHAR16), TempStr); - - HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); - - HiiCreateActionOpCode ( - StartOpCodeHandle, - mKeyInput, - Token, - HelpToken, - EFI_IFR_FLAG_CALLBACK, - 0 - ); - } - - if (NeedEndOp) { - HiiCreateEndOpCode (StartOpCodeHandle); - } - - HiiUpdateForm ( - HiiHandle, - &gBootManagerFormSetGuid, - BOOT_MANAGER_FORM_ID, - StartOpCodeHandle, - EndOpCodeHandle - ); - - HiiFreeOpCodeHandle (StartOpCodeHandle); - HiiFreeOpCodeHandle (EndOpCodeHandle); - - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - Status = gFormBrowser2->SendForm ( - gFormBrowser2, - &HiiHandle, - 1, - &gBootManagerFormSetGuid, - 0, - NULL, - &ActionRequest - ); - if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { - EnableResetRequired (); - } - - if (gOption == NULL) { - return ; - } - - // - // Will leave browser, check any reset required change is applied? if yes, reset system - // - SetupResetReminder (); - - // - // Restore to original mode before launching boot option. - // - BdsSetConsoleMode (FALSE); - - // - // parse the selected option - // - Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData); - - if (!EFI_ERROR (Status)) { - gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); - PlatformBdsBootSuccess (gOption); - } else { - gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); - PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize); - gST->ConOut->OutputString ( - gST->ConOut, - GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE)) - ); - gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - } -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h deleted file mode 100644 index e26147183a..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h +++ /dev/null @@ -1,103 +0,0 @@ -/** @file - The platform boot manager reference implement - -Copyright (c) 2004 - 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 _EFI_BOOT_MANAGER_H_ -#define _EFI_BOOT_MANAGER_H_ - -#include "Bds.h" -#include "FrontPage.h" - -#define BOOT_MANAGER_FORM_ID 0x1000 - -#define LABEL_BOOT_OPTION 0x00 -#define LABEL_BOOT_OPTION_END 0x01 - -// -// These are the VFR compiler generated data representing our VFR data. -// -extern UINT8 BootManagerVfrBin[]; - -#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('B', 'M', 'C', 'B') - -typedef struct { - UINTN Signature; - - // - // HII relative handles - // - EFI_HII_HANDLE HiiHandle; - EFI_HANDLE DriverHandle; - - // - // Produced protocols - // - EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; -} BOOT_MANAGER_CALLBACK_DATA; - -/** - This call back function is registered with Boot Manager formset. - When user selects a boot option, this call back function will - be triggered. The boot option is saved for later processing. - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. - -**/ -EFI_STATUS -EFIAPI -BootManagerCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ); - -/** - - Registers HII packages for the Boot Manger to HII Database. - It also registers the browser call back function. - - @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully. - @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered. - -**/ -EFI_STATUS -InitializeBootManager ( - VOID - ); - -/** - This function invokes Boot Manager. If all devices have not a chance to be connected, - the connect all will be triggered. It then enumerate all boot options. If - a boot option from the Boot Manager page is selected, Boot Manager will boot - from this boot option. - -**/ -VOID -CallBootManager ( - VOID - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni deleted file mode 100644 index e62c264da3..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr deleted file mode 100644 index 0d8142c17d..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr +++ /dev/null @@ -1,50 +0,0 @@ -///** @file -// -// Browser formset. -// -// Copyright (c) 2004 - 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 - -#define BOOT_MANAGER_FORM_ID 0x1000 - -#define LABEL_BOOT_OPTION 0x00 -#define LABEL_BOOT_OPTION_END 0x01 - -#define BOOT_MANAGER_CLASS 0x00 -#define BOOT_MANAGER_SUBCLASS 0x00 - -formset - guid = BOOT_MANAGER_FORMSET_GUID, - title = STRING_TOKEN(STR_BM_BANNER), - help = STRING_TOKEN(STR_LAST_STRING), - classguid = BOOT_MANAGER_FORMSET_GUID, - - form formid = BOOT_MANAGER_FORM_ID, - title = STRING_TOKEN(STR_BM_BANNER); - - subtitle text = STRING_TOKEN(STR_LAST_STRING); - subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER); - subtitle text = STRING_TOKEN(STR_LAST_STRING); - - // - // This is where we will dynamically add choices for the Boot Manager - // - label LABEL_BOOT_OPTION; - label LABEL_BOOT_OPTION_END; - - subtitle text = STRING_TOKEN(STR_LAST_STRING); - subtitle text = STRING_TOKEN(STR_HELP_FOOTER); - - endform; - -endformset; diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c deleted file mode 100644 index 6c7fc7ced4..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c +++ /dev/null @@ -1,233 +0,0 @@ -/** @file - BDS routines to handle capsules. - -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 "Bds.h" - -/** - - This routine is called to see if there are any capsules we need to process. - If the boot mode is not UPDATE, then we do nothing. Otherwise find the - capsule HOBS and produce firmware volumes for them via the DXE service. - Then call the dispatcher to dispatch drivers from them. Finally, check - the status of the updates. - - This function should be called by BDS in case we need to do some - sort of processing even if there is no capsule to process. We - need to do this if an earlier update went away and we need to - clear the capsule variable so on the next reset PEI does not see it and - think there is a capsule available. - - @param BootMode the current boot mode - - @retval EFI_INVALID_PARAMETER boot mode is not correct for an update - @retval EFI_SUCCESS There is no error when processing capsule - -**/ -EFI_STATUS -EFIAPI -BdsProcessCapsules ( - EFI_BOOT_MODE BootMode - ) -{ - EFI_STATUS Status; - EFI_PEI_HOB_POINTERS HobPointer; - EFI_CAPSULE_HEADER *CapsuleHeader; - UINT32 Size; - UINT32 CapsuleNumber; - UINT32 CapsuleTotalNumber; - EFI_CAPSULE_TABLE *CapsuleTable; - UINT32 Index; - UINT32 CacheIndex; - UINT32 CacheNumber; - VOID **CapsulePtr; - VOID **CapsulePtrCache; - EFI_GUID *CapsuleGuidCache; - BOOLEAN NeedReset; - - CapsuleNumber = 0; - CapsuleTotalNumber = 0; - CacheIndex = 0; - CacheNumber = 0; - CapsulePtr = NULL; - CapsulePtrCache = NULL; - CapsuleGuidCache = NULL; - NeedReset = FALSE; - - // - // We don't do anything else if the boot mode is not flash-update - // - if (BootMode != BOOT_ON_FLASH_UPDATE) { - DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update.\n")); - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - // - // Find all capsule images from hob - // - HobPointer.Raw = GetHobList (); - while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) { - CapsuleTotalNumber ++; - HobPointer.Raw = GET_NEXT_HOB (HobPointer); - } - - if (CapsuleTotalNumber == 0) { - // - // We didn't find a hob, so had no errors. - // - DEBUG ((EFI_D_ERROR, "We can not find capsule data in capsule update boot mode.\n")); - DEBUG ((EFI_D_ERROR, "Please check the followings are correct if unexpected capsule update error happens.\n")); - DEBUG ((EFI_D_ERROR, "1. CapsuleX64 is built as X64 module when PEI is IA32 and DXE is X64\n")); - DEBUG ((EFI_D_ERROR, "2. Capsule data should persist in memory across a system reset.\n")); - PlatformBdsLockNonUpdatableFlash (); - return EFI_SUCCESS; - } - - // - // Init temp Capsule Data table. - // - CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber); - ASSERT (CapsulePtr != NULL); - CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber); - ASSERT (CapsulePtrCache != NULL); - CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber); - ASSERT (CapsuleGuidCache != NULL); - - // - // Find all capsule images from hob - // - HobPointer.Raw = GetHobList (); - while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) { - CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress; - HobPointer.Raw = GET_NEXT_HOB (HobPointer); - } - - // - //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install - //capsuleTable to configure table with EFI_CAPSULE_GUID - // - - // - // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating - // System to have information persist across a system reset. EFI System Table must - // point to an array of capsules that contains the same CapsuleGuid value. And agents - // searching for this type capsule will look in EFI System Table and search for the - // capsule's Guid and associated pointer to retrieve the data. Two steps below describes - // how to sorting the capsules by the unique guid and install the array to EFI System Table. - // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an - // array for later sorting capsules by CapsuleGuid. - // - for (Index = 0; Index < CapsuleTotalNumber; Index++) { - CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; - if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) { - // - // For each capsule, we compare it with known CapsuleGuid in the CacheArray. - // If already has the Guid, skip it. Whereas, record it in the CacheArray as - // an additional one. - // - CacheIndex = 0; - while (CacheIndex < CacheNumber) { - if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) { - break; - } - CacheIndex++; - } - if (CacheIndex == CacheNumber) { - CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID)); - } - } - } - - // - // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules - // whose guid is the same as it, and malloc memory for an array which preceding - // with UINT32. The array fills with entry point of capsules that have the same - // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install - // this array into EFI System Table, so that agents searching for this type capsule - // will look in EFI System Table and search for the capsule's Guid and associated - // pointer to retrieve the data. - // - CacheIndex = 0; - while (CacheIndex < CacheNumber) { - CapsuleNumber = 0; - for (Index = 0; Index < CapsuleTotalNumber; Index++) { - CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; - if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) { - if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) { - // - // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid. - // - CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader; - } - } - } - if (CapsuleNumber != 0) { - Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*); - CapsuleTable = AllocateRuntimePool (Size); - ASSERT (CapsuleTable != NULL); - CapsuleTable->CapsuleArrayNumber = CapsuleNumber; - CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*)); - Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable); - ASSERT_EFI_ERROR (Status); - } - CacheIndex++; - } - - // - // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are - // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash - // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional - // type capsule transaction could be extended. It depends on platform policy. - // - for (Index = 0; Index < CapsuleTotalNumber; Index++) { - CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; - if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) { - // - // Always reset system after all capsule processed if FMP capsule exist - // - if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)){ - NeedReset = TRUE; - } - - // - // Call capsule library to process capsule image. - // - ProcessCapsuleImage (CapsuleHeader); - } - } - - if (NeedReset) { - Print(L"Capsule Request Cold Reboot.\n"); - - for (Index = 5; Index > 0; Index--) { - Print(L"\rResetting system in %d seconds ...", Index); - gBS->Stall (1000000); - } - - gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); - - CpuDeadLoop (); - } - - PlatformBdsLockNonUpdatableFlash (); - - // - // Free the allocated temp memory space. - // - FreePool (CapsuleGuidCache); - FreePool (CapsulePtrCache); - FreePool (CapsulePtr); - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c deleted file mode 100644 index af2b18a047..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c +++ /dev/null @@ -1,2591 +0,0 @@ -/** @file - The platform device manager reference implementation - -Copyright (c) 2004 - 2015, Intel 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 "DeviceManager.h" - -DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = { - DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE, - NULL, - NULL, - NULL, - NULL, - { - FakeExtractConfig, - FakeRouteConfig, - DeviceManagerCallback - }, - { - FakeExtractConfig, - FakeRouteConfig, - DriverHealthCallback - } -}; - -#define MAX_MAC_ADDRESS_NODE_LIST_LEN 10 - -// -// Which Mac Address string is select -// it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form. -// -EFI_STRING mSelectedMacAddrString; - -// -// Which form Id need to be show. -// -EFI_FORM_ID mNextShowFormId = DEVICE_MANAGER_FORM_ID; - -// -// The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID -// -MAC_ADDRESS_NODE_LIST mMacDeviceList; - -DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = { - { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS }, - { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS }, - { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS }, - { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS }, - { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS }, - { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS } -}; - -HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - DEVICE_MANAGER_FORMSET_GUID - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - (UINT8) (END_DEVICE_PATH_LENGTH), - (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) - } - } -}; - -HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - DRIVER_HEALTH_FORMSET_GUID - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - (UINT8) (END_DEVICE_PATH_LENGTH), - (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) - } - } -}; - -/** - This function is invoked if user selected a interactive opcode from Device Manager's - Formset. The decision by user is saved to gCallbackKey for later processing. If - user set VBIOS, the new value is saved to EFI variable. - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. - -**/ -EFI_STATUS -EFIAPI -DeviceManagerCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - UINTN CurIndex; - - if (Action != EFI_BROWSER_ACTION_CHANGING) { - // - // All other action return unsupported. - // - return EFI_UNSUPPORTED; - } - - if (Value == NULL) { - return EFI_INVALID_PARAMETER; - } - - gCallbackKey = QuestionId; - if ((QuestionId < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET) && (QuestionId >= NETWORK_DEVICE_LIST_KEY_OFFSET)) { - // - // If user select the mac address, need to record mac address string to support next form show. - // - for (CurIndex = 0; CurIndex < mMacDeviceList.CurListLen; CurIndex ++) { - if (mMacDeviceList.NodeList[CurIndex].QuestionId == QuestionId) { - mSelectedMacAddrString = HiiGetString (gDeviceManagerPrivate.HiiHandle, mMacDeviceList.NodeList[CurIndex].PromptId, NULL); - } - } - } - - return EFI_SUCCESS; -} - -/** - - This function registers HII packages to HII database. - - @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully. - @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered. - -**/ -EFI_STATUS -InitializeDeviceManager ( - VOID - ) -{ - EFI_STATUS Status; - - // - // Install Device Path Protocol and Config Access protocol to driver handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &gDeviceManagerPrivate.DriverHandle, - &gEfiDevicePathProtocolGuid, - &mDeviceManagerHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &gDeviceManagerPrivate.ConfigAccess, - NULL - ); - ASSERT_EFI_ERROR (Status); - - Status = gBS->InstallMultipleProtocolInterfaces ( - &gDeviceManagerPrivate.DriverHealthHandle, - &gEfiDevicePathProtocolGuid, - &mDriverHealthHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &gDeviceManagerPrivate.DriverHealthConfigAccess, - NULL - ); - ASSERT_EFI_ERROR (Status); - - mMacDeviceList.CurListLen = 0; - mMacDeviceList.MaxListLen = 0; - - return Status; -} - -/** - Extract the displayed formset for given HII handle and class guid. - - @param Handle The HII handle. - @param SetupClassGuid The class guid specifies which form set will be displayed. - @param SkipCount Skip some formsets which has processed before. - @param FormSetTitle Formset title string. - @param FormSetHelp Formset help string. - @param FormSetGuid Return the formset guid for this formset. - - @retval TRUE The formset for given HII handle will be displayed. - @return FALSE The formset for given HII handle will not be displayed. - -**/ -BOOLEAN -ExtractDisplayedHiiFormFromHiiHandle ( - IN EFI_HII_HANDLE Handle, - IN EFI_GUID *SetupClassGuid, - IN UINTN SkipCount, - OUT EFI_STRING_ID *FormSetTitle, - OUT EFI_STRING_ID *FormSetHelp, - OUT EFI_GUID **FormSetGuid - ) -{ - EFI_STATUS Status; - UINTN BufferSize; - EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; - UINT8 *Package; - UINT8 *OpCodeData; - UINT32 Offset; - UINT32 Offset2; - UINT32 PackageListLength; - EFI_HII_PACKAGE_HEADER PackageHeader; - EFI_GUID *ClassGuid; - UINT8 ClassGuidNum; - - ASSERT (Handle != NULL); - ASSERT (SetupClassGuid != NULL); - ASSERT (FormSetTitle != NULL); - ASSERT (FormSetHelp != NULL); - - *FormSetTitle = 0; - *FormSetHelp = 0; - ClassGuidNum = 0; - ClassGuid = NULL; - - // - // Get HII PackageList - // - BufferSize = 0; - HiiPackageList = NULL; - Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); - // - // Handle is a invalid handle. Check if Handle is corrupted. - // - ASSERT (Status != EFI_NOT_FOUND); - // - // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. - // - ASSERT (Status == EFI_BUFFER_TOO_SMALL); - - HiiPackageList = AllocatePool (BufferSize); - ASSERT (HiiPackageList != NULL); - - Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); - if (EFI_ERROR (Status)) { - return FALSE; - } - - // - // Get Form package from this HII package List - // - Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); - Offset2 = 0; - PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); - - while (Offset < PackageListLength) { - Package = ((UINT8 *) HiiPackageList) + Offset; - CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); - - if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { - // - // Search FormSet Opcode in this Form Package - // - Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); - while (Offset2 < PackageHeader.Length) { - OpCodeData = Package + Offset2; - Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - - if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { - if (SkipCount != 0) { - SkipCount --; - continue; - } - - if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) { - // - // Find FormSet OpCode - // - ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3); - ClassGuid = (EFI_GUID *) (VOID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET)); - while (ClassGuidNum-- > 0) { - if (CompareGuid (SetupClassGuid, ClassGuid)) { - CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); - CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); - *FormSetGuid = AllocateCopyPool (sizeof (EFI_GUID), &((EFI_IFR_FORM_SET *) OpCodeData)->Guid); - ASSERT (*FormSetGuid != NULL); - FreePool (HiiPackageList); - return TRUE; - } - ClassGuid ++; - } - } else { - CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); - CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); - *FormSetGuid = AllocateCopyPool (sizeof (EFI_GUID), &((EFI_IFR_FORM_SET *) OpCodeData)->Guid); - ASSERT (*FormSetGuid != NULL); - FreePool (HiiPackageList); - return TRUE; - } - } - } - } - - // - // Go to next package - // - Offset += PackageHeader.Length; - } - - FreePool (HiiPackageList); - - return FALSE; -} - -/** - Get the mac address string from the device path. - if the device path has the vlan, get the vanid also. - - @param MacAddressNode Device path begin with mac address - @param PBuffer Output string buffer contain mac address. - -**/ -BOOLEAN -GetMacAddressString( - IN MAC_ADDR_DEVICE_PATH *MacAddressNode, - OUT CHAR16 **PBuffer - ) -{ - UINTN HwAddressSize; - UINTN Index; - UINT8 *HwAddress; - EFI_DEVICE_PATH_PROTOCOL *Node; - UINT16 VlanId; - CHAR16 *String; - UINTN BufferLen; - - VlanId = 0; - String = NULL; - ASSERT(MacAddressNode != NULL); - - HwAddressSize = sizeof (EFI_MAC_ADDRESS); - if (MacAddressNode->IfType == 0x01 || MacAddressNode->IfType == 0x00) { - HwAddressSize = 6; - } - - // - // The output format is MAC:XX:XX:XX:...\XXXX - // The size is the Number size + ":" size + Vlan size(\XXXX) + End - // - BufferLen = (4 + 2 * HwAddressSize + (HwAddressSize - 1) + 5 + 1) * sizeof (CHAR16); - String = AllocateZeroPool (BufferLen); - if (String == NULL) { - return FALSE; - } - - *PBuffer = String; - StrCpyS (String, BufferLen / sizeof (CHAR16), L"MAC:"); - String += 4; - - // - // Convert the MAC address into a unicode string. - // - HwAddress = &MacAddressNode->MacAddress.Addr[0]; - for (Index = 0; Index < HwAddressSize; Index++) { - String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(HwAddress++), 2); - if (Index < HwAddressSize - 1) { - *String++ = L':'; - } - } - - // - // If VLAN is configured, it will need extra 5 characters like "\0005". - // Plus one unicode character for the null-terminator. - // - Node = (EFI_DEVICE_PATH_PROTOCOL *)MacAddressNode; - while (!IsDevicePathEnd (Node)) { - if (Node->Type == MESSAGING_DEVICE_PATH && Node->SubType == MSG_VLAN_DP) { - VlanId = ((VLAN_DEVICE_PATH *) Node)->VlanId; - } - Node = NextDevicePathNode (Node); - } - - if (VlanId != 0) { - *String++ = L'\\'; - String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, VlanId, 4); - } - - // - // Null terminate the Unicode string - // - *String = L'\0'; - - return TRUE; -} - -/** - Save question id and prompt id to the mac device list. - If the same mac address has saved yet, no need to add more. - - @param MacAddrString Mac address string. - - @retval EFI_SUCCESS Add the item is successful. - @return Other values if failed to Add the item. -**/ -BOOLEAN -AddIdToMacDeviceList ( - IN EFI_STRING MacAddrString - ) -{ - MENU_INFO_ITEM *TempDeviceList; - UINTN Index; - EFI_STRING StoredString; - EFI_STRING_ID PromptId; - EFI_HII_HANDLE HiiHandle; - - HiiHandle = gDeviceManagerPrivate.HiiHandle; - TempDeviceList = NULL; - - for (Index = 0; Index < mMacDeviceList.CurListLen; Index ++) { - StoredString = HiiGetString (HiiHandle, mMacDeviceList.NodeList[Index].PromptId, NULL); - if (StoredString == NULL) { - return FALSE; - } - - // - // Already has save the same mac address to the list. - // - if (StrCmp (MacAddrString, StoredString) == 0) { - return FALSE; - } - } - - PromptId = HiiSetString(HiiHandle, 0, MacAddrString, NULL); - // - // If not in the list, save it. - // - if (mMacDeviceList.MaxListLen > mMacDeviceList.CurListLen + 1) { - mMacDeviceList.NodeList[mMacDeviceList.CurListLen].PromptId = PromptId; - mMacDeviceList.NodeList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); - } else { - mMacDeviceList.MaxListLen += MAX_MAC_ADDRESS_NODE_LIST_LEN; - if (mMacDeviceList.CurListLen != 0) { - TempDeviceList = (MENU_INFO_ITEM *)AllocateCopyPool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen, (VOID *)mMacDeviceList.NodeList); - } else { - TempDeviceList = (MENU_INFO_ITEM *)AllocatePool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen); - } - - if (TempDeviceList == NULL) { - return FALSE; - } - TempDeviceList[mMacDeviceList.CurListLen].PromptId = PromptId; - TempDeviceList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); - - if (mMacDeviceList.CurListLen > 0) { - FreePool(mMacDeviceList.NodeList); - } - - mMacDeviceList.NodeList = TempDeviceList; - } - mMacDeviceList.CurListLen ++; - - return TRUE; -} - -/** - Check the devcie path, try to find whether it has mac address path. - - In this function, first need to check whether this path has mac address path. - second, when the mac address device path has find, also need to deicide whether - need to add this mac address relate info to the menu. - - @param *Node Input device which need to be check. - @param *NeedAddItem Whether need to add the menu in the network device list. - - @retval TRUE Has mac address device path. - @retval FALSE NOT Has mac address device path. - -**/ -BOOLEAN -IsMacAddressDevicePath ( - IN VOID *Node, - OUT BOOLEAN *NeedAddItem - ) -{ - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - CHAR16 *Buffer; - BOOLEAN ReturnVal; - - ASSERT (Node != NULL); - *NeedAddItem = FALSE; - ReturnVal = FALSE; - Buffer = NULL; - - DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; - - // - // find the partition device path node - // - while (!IsDevicePathEnd (DevicePath)) { - if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && - (DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP)) { - ReturnVal = TRUE; - - if (DEVICE_MANAGER_FORM_ID == mNextShowFormId) { - *NeedAddItem = TRUE; - break; - } - - if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH*)DevicePath, &Buffer)) { - break; - } - - if (NETWORK_DEVICE_FORM_ID == mNextShowFormId) { - if (StrCmp (Buffer, mSelectedMacAddrString) == 0) { - *NeedAddItem = TRUE; - } - break; - } - - if (NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) { - // - // Same handle may has two network child handle, so the questionid - // has the offset of SAME_HANDLE_KEY_OFFSET. - // - if (AddIdToMacDeviceList (Buffer)) { - *NeedAddItem = TRUE; - } - break; - } - } - DevicePath = NextDevicePathNode (DevicePath); - } - - if (Buffer != NULL) { - FreePool (Buffer); - } - - return ReturnVal; -} - -/** - Check to see if the device path is for the network device. - - @param Handle The HII handle which include the mac address device path. - @param ItemCount The new add Mac address item count. - - @retval TRUE Need to add new item in the menu. - @return FALSE Do not need to add the menu about the network. - -**/ -BOOLEAN -IsNeedAddNetworkMenu ( - IN EFI_HII_HANDLE Handle, - OUT UINTN *ItemCount - ) -{ - EFI_STATUS Status; - UINTN EntryCount; - UINTN Index; - EFI_HANDLE DriverHandle; - EFI_HANDLE ControllerHandle; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; - EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; - BOOLEAN IsNeedAdd; - - IsNeedAdd = FALSE; - OpenInfoBuffer = NULL; - if ((Handle == NULL) || (ItemCount == NULL)) { - return FALSE; - } - *ItemCount = 0; - - Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle); - if (EFI_ERROR (Status)) { - return FALSE; - } - // - // Get the device path by the got Driver handle . - // - Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath); - if (EFI_ERROR (Status)) { - return FALSE; - } - TmpDevicePath = DevicePath; - - // - // Check whether this device path include mac address device path. - // If this path has mac address path, get the value whether need - // add this info to the menu and return. - // Else check more about the child handle devcie path. - // - if (IsMacAddressDevicePath(TmpDevicePath, &IsNeedAdd)) { - if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) && IsNeedAdd) { - (*ItemCount) = 1; - } - return IsNeedAdd; - } - - // - // Search whether this path is the controller path, not he child handle path. - // And the child handle has the network devcie connected. - // - TmpDevicePath = DevicePath; - Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle); - if (EFI_ERROR (Status)) { - return FALSE; - } - - if (!IsDevicePathEnd (TmpDevicePath)) { - return FALSE; - } - - // - // Retrieve the list of agents that are consuming the specific protocol - // on ControllerHandle. - // The buffer point by OpenInfoBuffer need be free at this function. - // - Status = gBS->OpenProtocolInformation ( - ControllerHandle, - &gEfiPciIoProtocolGuid, - &OpenInfoBuffer, - &EntryCount - ); - if (EFI_ERROR (Status)) { - return FALSE; - } - - // - // Inspect if ChildHandle is one of the agents. - // - Status = EFI_UNSUPPORTED; - for (Index = 0; Index < EntryCount; Index++) { - // - // Query all the children created by the controller handle's driver - // - if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { - Status = gBS->OpenProtocol ( - OpenInfoBuffer[Index].ControllerHandle, - &gEfiDevicePathProtocolGuid, - (VOID **) &ChildDevicePath, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - continue; - } - - // - // Check whether this device path include mac address device path. - // - if (!IsMacAddressDevicePath(ChildDevicePath, &IsNeedAdd)) { - // - // If this path not has mac address path, check the other. - // - continue; - } else { - // - // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more. - // - if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId)) { - if (IsNeedAdd) { - (*ItemCount) += 1; - } - continue; - } else { - // - // If need to update other form, return whether need to add to the menu. - // - goto Done; - } - } - } - } - -Done: - if (OpenInfoBuffer != NULL) { - FreePool (OpenInfoBuffer); - } - return IsNeedAdd; -} - -/** - Get HiiHandle total number. - - @param HiiHandles The input HiiHandle array. - - @retval the Hiihandle count. - -**/ -UINTN -GetHiiHandleCount ( - IN EFI_HII_HANDLE *HiiHandles - ) -{ - UINTN Index; - - for (Index = 0; HiiHandles[Index] != NULL; Index++) { - } - - return Index; -} - -/** - Insert the new HiiHandle + FormsetGuid at the NewPair[InsertOffset]. - - @param HiiHandles The input HiiHandle array. - @param GuidLists The input form set guid lists. - @param ArrayCount The input array count, new array will be arraycount + 1 size. - @param Offset The current used HiiHandle's Offset. - @param FormSetGuid The new found formset guid. - -**/ -VOID -AdjustArrayData ( - IN OUT EFI_HII_HANDLE **HiiHandles, - IN OUT EFI_GUID ***GuidLists, - IN UINTN ArrayCount, - IN UINTN Offset, - IN EFI_GUID *FormSetGuid - ) -{ - EFI_HII_HANDLE *NewHiiHandles; - EFI_GUID **NewGuidLists; - - // - // +2 means include the new HiiHandle and the last empty NULL pointer. - // - NewHiiHandles = AllocateZeroPool ((ArrayCount + 2) * sizeof (EFI_HII_HANDLE)); - ASSERT (NewHiiHandles != NULL); - - CopyMem (NewHiiHandles, *HiiHandles, Offset * sizeof (EFI_HII_HANDLE)); - NewHiiHandles[Offset] = NewHiiHandles[Offset - 1]; - CopyMem (NewHiiHandles + Offset + 1, *HiiHandles + Offset, (ArrayCount - Offset) * sizeof (EFI_HII_HANDLE)); - - NewGuidLists = AllocateZeroPool ((ArrayCount + 2) * sizeof (EFI_GUID *)); - ASSERT (NewGuidLists != NULL); - - CopyMem (NewGuidLists, *GuidLists, Offset * sizeof (EFI_GUID *)); - NewGuidLists[Offset] = FormSetGuid; - - FreePool (*HiiHandles); - *HiiHandles = NewHiiHandles; - FreePool (*GuidLists); - *GuidLists = NewGuidLists; -} - -/** - Call the browser and display the device manager to allow user - to configure the platform. - - This function create the dynamic content for device manager. It includes - section header for all class of devices, one-of opcode to set VBIOS. - - @retval EFI_SUCCESS Operation is successful. - @return Other values if failed to clean up the dynamic content from HII - database. - -**/ -EFI_STATUS -CallDeviceManager ( - VOID - ) -{ - EFI_STATUS Status; - UINTN Index; - EFI_STRING String; - EFI_STRING_ID Token; - EFI_STRING_ID TokenHelp; - EFI_HII_HANDLE *HiiHandles; - EFI_HII_HANDLE HiiHandle; - EFI_STRING_ID FormSetTitle; - EFI_STRING_ID FormSetHelp; - EFI_BROWSER_ACTION_REQUEST ActionRequest; - VOID *StartOpCodeHandle; - VOID *EndOpCodeHandle; - EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *EndLabel; - UINTN NumHandles; - EFI_HANDLE *DriverHealthHandles; - BOOLEAN AddNetworkMenu; - UINTN AddItemCount; - UINTN NewStringLen; - EFI_STRING NewStringTitle; - EFI_GUID **GuidLists; - UINTN HandleNum; - UINTN SkipCount; - EFI_GUID *FormSetGuid; - - GuidLists = NULL; - HiiHandles = NULL; - Status = EFI_SUCCESS; - gCallbackKey = 0; - NumHandles = 0; - DriverHealthHandles = NULL; - AddNetworkMenu = FALSE; - AddItemCount = 0; - SkipCount = 0; - FormSetGuid = NULL; - - // - // Connect all prior to entering the platform setup menu. - // - if (!gConnectAllHappened) { - BdsLibConnectAllDriversToAllControllers (); - gConnectAllHappened = TRUE; - } - - HiiHandle = gDeviceManagerPrivate.HiiHandle; - if (HiiHandle == NULL) { - // - // Publish our HII data. - // - HiiHandle = HiiAddPackages ( - &gDeviceManagerFormSetGuid, - gDeviceManagerPrivate.DriverHandle, - DeviceManagerVfrBin, - BdsDxeStrings, - NULL - ); - if (HiiHandle == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - gDeviceManagerPrivate.HiiHandle = HiiHandle; - } - - // - // If need show the Network device list form, clear the old save list first. - // - if ((mNextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) && (mMacDeviceList.CurListLen > 0)) { - mMacDeviceList.CurListLen = 0; - } - - // - // Update the network device form titile. - // - if (mNextShowFormId == NETWORK_DEVICE_FORM_ID) { - String = HiiGetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NULL); - NewStringLen = StrLen(mSelectedMacAddrString) * 2; - NewStringLen += (StrLen(String) + 2) * 2; - NewStringTitle = AllocatePool (NewStringLen); - UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString); - HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL); - FreePool (String); - FreePool (NewStringTitle); - } - - // - // Allocate space for creation of UpdateData Buffer - // - StartOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (StartOpCodeHandle != NULL); - - EndOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (EndOpCodeHandle != NULL); - - // - // Create Hii Extend Label OpCode as the start opcode - // - StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - // - // According to the next show Form id(mNextShowFormId) to decide which form need to update. - // - StartLabel->Number = (UINT16) (LABEL_FORM_ID_OFFSET + mNextShowFormId); - - // - // Create Hii Extend Label OpCode as the end opcode - // - EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabel->Number = LABEL_END; - - // - // Get all the Hii handles - // - HiiHandles = HiiGetHiiHandles (NULL); - ASSERT (HiiHandles != NULL); - - HandleNum = GetHiiHandleCount (HiiHandles); - GuidLists = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_GUID *)); - ASSERT (GuidLists != NULL); - - // - // Search for formset of each class type - // - for (Index = 0; HiiHandles[Index] != NULL; Index++) { - // - // The QuestionId in the form which will call the driver form has this asssumption. - // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET; - // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET. - // - ASSERT(Index < MAX_KEY_SECTION_LEN); - - if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiHiiPlatformSetupFormsetGuid, SkipCount, &FormSetTitle, &FormSetHelp, &FormSetGuid)) { - SkipCount = 0; - continue; - } - - // - // One HiiHandle has more than one formset can be shown, - // Insert a new pair of HiiHandle + Guid to the HiiHandles and GuidLists list. - // - if (SkipCount > 0) { - AdjustArrayData (&HiiHandles, &GuidLists, HandleNum, Index + 1, FormSetGuid); - HandleNum ++; - Index ++; - } - - String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL); - if (String == NULL) { - String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); - ASSERT (String != NULL); - } - Token = HiiSetString (HiiHandle, 0, String, NULL); - FreePool (String); - - String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL); - if (String == NULL) { - String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); - ASSERT (String != NULL); - } - TokenHelp = HiiSetString (HiiHandle, 0, String, NULL); - FreePool (String); - - // - // Network device process - // - if (IsNeedAddNetworkMenu (HiiHandles[Index], &AddItemCount)) { - if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) { - // - // Only show one menu item "Network Config" in the device manger form. - // - if (!AddNetworkMenu) { - AddNetworkMenu = TRUE; - HiiCreateGotoOpCode ( - StartOpCodeHandle, - INVALID_FORM_ID, - STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE), - STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP), - EFI_IFR_FLAG_CALLBACK, - (EFI_QUESTION_ID) QUESTION_NETWORK_DEVICE_ID - ); - } - } else if (mNextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) { - // - // In network device list form, same mac address device only show one menu. - // - while (AddItemCount > 0) { - HiiCreateGotoOpCode ( - StartOpCodeHandle, - INVALID_FORM_ID, - mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].PromptId, - STRING_TOKEN (STR_NETWORK_DEVICE_HELP), - EFI_IFR_FLAG_CALLBACK, - mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].QuestionId - ); - AddItemCount -= 1; - } - } else if (mNextShowFormId == NETWORK_DEVICE_FORM_ID) { - // - // In network device form, only the selected mac address device need to be show. - // - HiiCreateGotoOpCode ( - StartOpCodeHandle, - INVALID_FORM_ID, - Token, - TokenHelp, - EFI_IFR_FLAG_CALLBACK, - (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET) - ); - } - } else { - // - // - // Not network device process, only need to show at device manger form. - // - if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) { - HiiCreateGotoOpCode ( - StartOpCodeHandle, - INVALID_FORM_ID, - Token, - TokenHelp, - EFI_IFR_FLAG_CALLBACK, - (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET) - ); - } - } - - // - // Try to find more formset in this HiiHandle. - // - SkipCount++; - Index--; - } - - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiDriverHealthProtocolGuid, - NULL, - &NumHandles, - &DriverHealthHandles - ); - - // - // If there are no drivers installed driver health protocol, do not create driver health entry in UI - // - if (NumHandles != 0) { - // - // If driver health protocol is installed, create Driver Health subtitle and entry - // - HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE), 0, 0, 0); - HiiCreateGotoOpCode ( - StartOpCodeHandle, - DRIVER_HEALTH_FORM_ID, - STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY), // Prompt text - STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP), // Help text - EFI_IFR_FLAG_CALLBACK, - DEVICE_MANAGER_KEY_DRIVER_HEALTH // Question ID - ); - - // - // Check All Driver health status - // - if (!PlaformHealthStatusCheck ()) { - // - // At least one driver in the platform are not in healthy status - // - HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH)), NULL); - } else { - // - // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry. - // - HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL); - } - } - - HiiUpdateForm ( - HiiHandle, - &gDeviceManagerFormSetGuid, - mNextShowFormId, - StartOpCodeHandle, - EndOpCodeHandle - ); - - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - Status = gFormBrowser2->SendForm ( - gFormBrowser2, - &HiiHandle, - 1, - &gDeviceManagerFormSetGuid, - mNextShowFormId, - NULL, - &ActionRequest - ); - if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { - EnableResetRequired (); - } - - // - // We will have returned from processing a callback, selected - // a target to display - // - if ((gCallbackKey >= DEVICE_KEY_OFFSET)) { - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - Status = gFormBrowser2->SendForm ( - gFormBrowser2, - &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET], - 1, - GuidLists[gCallbackKey - DEVICE_KEY_OFFSET], - 0, - NULL, - &ActionRequest - ); - - if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { - EnableResetRequired (); - } - - // - // Force return to Device Manager - // - gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; - goto Done; - } - - // - // Driver Health item chose. - // - if (gCallbackKey == DEVICE_MANAGER_KEY_DRIVER_HEALTH) { - CallDriverHealth (); - // - // Force return to Device Manager - // - gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; - goto Done; - } - - // - // Enter from device manager and into the network device list. - // - if (gCallbackKey == QUESTION_NETWORK_DEVICE_ID) { - mNextShowFormId = NETWORK_DEVICE_LIST_FORM_ID; - gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; - goto Done; - } - - // - // In this case, go from the network device list to the specify device. - // - if ((gCallbackKey < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET ) && (gCallbackKey >= NETWORK_DEVICE_LIST_KEY_OFFSET)) { - mNextShowFormId = NETWORK_DEVICE_FORM_ID; - gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; - goto Done; - } - - // - // Select the ESC, the gCallbackKey == 0. - // - if(mNextShowFormId - 1 < DEVICE_MANAGER_FORM_ID) { - mNextShowFormId = DEVICE_MANAGER_FORM_ID; - } else { - mNextShowFormId = (UINT16) (mNextShowFormId - 1); - gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; - } - -Done: - // - // Remove our packagelist from HII database. - // - HiiRemovePackages (HiiHandle); - gDeviceManagerPrivate.HiiHandle = NULL; - - HiiFreeOpCodeHandle (StartOpCodeHandle); - HiiFreeOpCodeHandle (EndOpCodeHandle); - FreePool (HiiHandles); - - for (Index = 0; Index < HandleNum; Index++) { - if (GuidLists[Index] != NULL) { - FreePool (GuidLists[Index]); - } - } - FreePool (GuidLists); - - return Status; -} - -/** - This function is invoked if user selected a interactive opcode from Driver Health's - Formset. The decision by user is saved to gCallbackKey for later processing. - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. - -**/ -EFI_STATUS -EFIAPI -DriverHealthCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - if (Action == EFI_BROWSER_ACTION_CHANGED) { - if ((Value == NULL) || (ActionRequest == NULL)) { - return EFI_INVALID_PARAMETER; - } - - gCallbackKey = QuestionId; - - // - // Request to exit SendForm(), so as to switch to selected form - // - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - - return EFI_SUCCESS; - } - - // - // All other action return unsupported. - // - return EFI_UNSUPPORTED; -} - -/** - Collect and display the platform's driver health relative information, allow user to do interactive - operation while the platform is unhealthy. - - This function display a form which divided into two parts. The one list all modules which has installed - driver health protocol. The list usually contain driver name, controller name, and it's health info. - While the driver name can't be retrieved, will use device path as backup. The other part of the form provide - a choice to the user to repair all platform. - -**/ -VOID -CallDriverHealth ( - VOID - ) -{ - EFI_STATUS Status; - EFI_HII_HANDLE HiiHandle; - EFI_BROWSER_ACTION_REQUEST ActionRequest; - EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *StartLabelRepair; - EFI_IFR_GUID_LABEL *EndLabel; - EFI_IFR_GUID_LABEL *EndLabelRepair; - VOID *StartOpCodeHandle; - VOID *EndOpCodeHandle; - VOID *StartOpCodeHandleRepair; - VOID *EndOpCodeHandleRepair; - UINTN Index; - EFI_STRING_ID Token; - EFI_STRING_ID TokenHelp; - EFI_STRING String; - EFI_STRING TmpString; - EFI_STRING DriverName; - EFI_STRING ControllerName; - LIST_ENTRY DriverHealthList; - DRIVER_HEALTH_INFO *DriverHealthInfo; - LIST_ENTRY *Link; - EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath; - BOOLEAN RebootRequired; - BOOLEAN IsControllerNameEmpty; - UINTN StringSize; - - Index = 0; - DriverHealthInfo = NULL; - DriverDevicePath = NULL; - IsControllerNameEmpty = FALSE; - InitializeListHead (&DriverHealthList); - - HiiHandle = gDeviceManagerPrivate.DriverHealthHiiHandle; - if (HiiHandle == NULL) { - // - // Publish Driver Health HII data. - // - HiiHandle = HiiAddPackages ( - &gDeviceManagerFormSetGuid, - gDeviceManagerPrivate.DriverHealthHandle, - DriverHealthVfrBin, - BdsDxeStrings, - NULL - ); - if (HiiHandle == NULL) { - return; - } - - gDeviceManagerPrivate.DriverHealthHiiHandle = HiiHandle; - } - - // - // Allocate space for creation of UpdateData Buffer - // - StartOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (StartOpCodeHandle != NULL); - - EndOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (EndOpCodeHandle != NULL); - - StartOpCodeHandleRepair = HiiAllocateOpCodeHandle (); - ASSERT (StartOpCodeHandleRepair != NULL); - - EndOpCodeHandleRepair = HiiAllocateOpCodeHandle (); - ASSERT (EndOpCodeHandleRepair != NULL); - - // - // Create Hii Extend Label OpCode as the start opcode - // - StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - StartLabel->Number = LABEL_DRIVER_HEALTH; - - // - // Create Hii Extend Label OpCode as the start opcode - // - StartLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - StartLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - StartLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL; - - // - // Create Hii Extend Label OpCode as the end opcode - // - EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabel->Number = LABEL_DRIVER_HEALTH_END; - - // - // Create Hii Extend Label OpCode as the end opcode - // - EndLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - EndLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL_END; - - HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DH_STATUS_LIST), 0, 0, 1); - - Status = GetAllControllersHealthStatus (&DriverHealthList); - ASSERT (Status != EFI_OUT_OF_RESOURCES); - - Link = GetFirstNode (&DriverHealthList); - - while (!IsNull (&DriverHealthList, Link)) { - DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); - - Status = DriverHealthGetDriverName (DriverHealthInfo->DriverHandle, &DriverName); - if (EFI_ERROR (Status)) { - // - // Can not get the Driver name, so use the Device path - // - DriverDevicePath = DevicePathFromHandle (DriverHealthInfo->DriverHandle); - DriverName = DevicePathToStr (DriverDevicePath); - } - StringSize = StrSize (DriverName); - - Status = DriverHealthGetControllerName ( - DriverHealthInfo->DriverHandle, - DriverHealthInfo->ControllerHandle, - DriverHealthInfo->ChildHandle, - &ControllerName - ); - - if (!EFI_ERROR (Status)) { - IsControllerNameEmpty = FALSE; - StringSize += StrLen (L" ") * sizeof(CHAR16); - StringSize += StrLen (ControllerName) * sizeof(CHAR16); - } else { - IsControllerNameEmpty = TRUE; - } - - // - // Add the message of the Module itself provided after the string item. - // - if ((DriverHealthInfo->MessageList != NULL) && (DriverHealthInfo->MessageList->StringId != 0)) { - TmpString = HiiGetString ( - DriverHealthInfo->MessageList->HiiHandle, - DriverHealthInfo->MessageList->StringId, - NULL - ); - ASSERT (TmpString != NULL); - - StringSize += StrLen (L" ") * sizeof(CHAR16); - StringSize += StrLen (TmpString) * sizeof(CHAR16); - - String = (EFI_STRING) AllocateZeroPool (StringSize); - ASSERT (String != NULL); - - StrCpyS (String, StringSize / sizeof(CHAR16), DriverName); - if (!IsControllerNameEmpty) { - StrCatS (String, StringSize / sizeof(CHAR16), L" "); - StrCatS (String, StringSize / sizeof(CHAR16), ControllerName); - } - - StrCatS (String, StringSize / sizeof(CHAR16), L" "); - StrCatS (String, StringSize / sizeof(CHAR16), TmpString); - - } else { - // - // Update the string will be displayed base on the driver's health status - // - switch(DriverHealthInfo->HealthStatus) { - case EfiDriverHealthStatusRepairRequired: - TmpString = GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED)); - break; - case EfiDriverHealthStatusConfigurationRequired: - TmpString = GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED)); - break; - case EfiDriverHealthStatusFailed: - TmpString = GetStringById (STRING_TOKEN (STR_OPERATION_FAILED)); - break; - case EfiDriverHealthStatusReconnectRequired: - TmpString = GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED)); - break; - case EfiDriverHealthStatusRebootRequired: - TmpString = GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED)); - break; - default: - TmpString = GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY)); - break; - } - ASSERT (TmpString != NULL); - - StringSize += StrLen (TmpString) * sizeof(CHAR16); - - String = (EFI_STRING) AllocateZeroPool (StringSize); - ASSERT (String != NULL); - - StrCpyS (String, StringSize / sizeof (CHAR16), DriverName); - if (!IsControllerNameEmpty) { - StrCatS (String, StringSize / sizeof (CHAR16), L" "); - StrCatS (String, StringSize / sizeof (CHAR16), ControllerName); - } - - StrCatS (String, StringSize / sizeof (CHAR16), TmpString); - } - - FreePool (TmpString); - - Token = HiiSetString (HiiHandle, 0, String, NULL); - FreePool (String); - - TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP)), NULL); - - HiiCreateActionOpCode ( - StartOpCodeHandle, - (EFI_QUESTION_ID) (Index + DRIVER_HEALTH_KEY_OFFSET), - Token, - TokenHelp, - EFI_IFR_FLAG_CALLBACK, - 0 - ); - Index++; - Link = GetNextNode (&DriverHealthList, Link); - } - - // - // Add End Opcode for Subtitle - // - HiiCreateEndOpCode (StartOpCodeHandle); - - HiiCreateSubTitleOpCode (StartOpCodeHandleRepair, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL), 0, 0, 1); - TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP)), NULL); - - if (PlaformHealthStatusCheck ()) { - // - // No action need to do for the platform - // - Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL); - HiiCreateActionOpCode ( - StartOpCodeHandleRepair, - 0, - Token, - TokenHelp, - EFI_IFR_FLAG_READ_ONLY, - 0 - ); - } else { - // - // Create ActionOpCode only while the platform need to do health related operation. - // - Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE)), NULL); - HiiCreateActionOpCode ( - StartOpCodeHandleRepair, - (EFI_QUESTION_ID) DRIVER_HEALTH_REPAIR_ALL_KEY, - Token, - TokenHelp, - EFI_IFR_FLAG_CALLBACK, - 0 - ); - } - - HiiCreateEndOpCode (StartOpCodeHandleRepair); - - Status = HiiUpdateForm ( - HiiHandle, - &gDriverHealthFormSetGuid, - DRIVER_HEALTH_FORM_ID, - StartOpCodeHandle, - EndOpCodeHandle - ); - ASSERT (Status != EFI_NOT_FOUND); - ASSERT (Status != EFI_BUFFER_TOO_SMALL); - - Status = HiiUpdateForm ( - HiiHandle, - &gDriverHealthFormSetGuid, - DRIVER_HEALTH_FORM_ID, - StartOpCodeHandleRepair, - EndOpCodeHandleRepair - ); - ASSERT (Status != EFI_NOT_FOUND); - ASSERT (Status != EFI_BUFFER_TOO_SMALL); - - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - Status = gFormBrowser2->SendForm ( - gFormBrowser2, - &HiiHandle, - 1, - &gDriverHealthFormSetGuid, - DRIVER_HEALTH_FORM_ID, - NULL, - &ActionRequest - ); - if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { - EnableResetRequired (); - } - - // - // We will have returned from processing a callback - user either hit ESC to exit, or selected - // a target to display. - // Process the diver health status states here. - // - if (gCallbackKey >= DRIVER_HEALTH_KEY_OFFSET && gCallbackKey != DRIVER_HEALTH_REPAIR_ALL_KEY) { - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - - Link = GetFirstNode (&DriverHealthList); - Index = 0; - - while (!IsNull (&DriverHealthList, Link)) { - // - // Got the item relative node in the List - // - if (Index == (gCallbackKey - DRIVER_HEALTH_KEY_OFFSET)) { - DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); - // - // Process the driver's healthy status for the specify module - // - RebootRequired = FALSE; - ProcessSingleControllerHealth ( - DriverHealthInfo->DriverHealth, - DriverHealthInfo->ControllerHandle, - DriverHealthInfo->ChildHandle, - DriverHealthInfo->HealthStatus, - &(DriverHealthInfo->MessageList), - DriverHealthInfo->HiiHandle, - &RebootRequired - ); - if (RebootRequired) { - gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); - } - break; - } - Index++; - Link = GetNextNode (&DriverHealthList, Link); - } - - if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { - EnableResetRequired (); - } - - // - // Force return to the form of Driver Health in Device Manager - // - gCallbackKey = DRIVER_HEALTH_RETURN_KEY; - } - - // - // Repair the whole platform - // - if (gCallbackKey == DRIVER_HEALTH_REPAIR_ALL_KEY) { - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - - PlatformRepairAll (&DriverHealthList); - - gCallbackKey = DRIVER_HEALTH_RETURN_KEY; - } - - // - // Remove driver health packagelist from HII database. - // - HiiRemovePackages (HiiHandle); - gDeviceManagerPrivate.DriverHealthHiiHandle = NULL; - - // - // Free driver health info list - // - while (!IsListEmpty (&DriverHealthList)) { - - Link = GetFirstNode(&DriverHealthList); - DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); - RemoveEntryList (Link); - - if (DriverHealthInfo->MessageList != NULL) { - FreePool(DriverHealthInfo->MessageList); - FreePool (DriverHealthInfo); - } - } - - HiiFreeOpCodeHandle (StartOpCodeHandle); - HiiFreeOpCodeHandle (EndOpCodeHandle); - HiiFreeOpCodeHandle (StartOpCodeHandleRepair); - HiiFreeOpCodeHandle (EndOpCodeHandleRepair); - - if (gCallbackKey == DRIVER_HEALTH_RETURN_KEY) { - // - // Force return to Driver Health Form - // - gCallbackKey = DEVICE_MANAGER_KEY_DRIVER_HEALTH; - CallDriverHealth (); - } -} - - -/** - Check the Driver Health status of a single controller and try to process it if not healthy. - - This function called by CheckAllControllersHealthStatus () function in order to process a specify - contoller's health state. - - @param DriverHealthList A Pointer to the list contain all of the platform driver health information. - @param DriverHandle The handle of driver. - @param ControllerHandle The class guid specifies which form set will be displayed. - @param ChildHandle The handle of the child controller to retrieve the health - status on. This is an optional parameter that may be NULL. - @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. - @param HealthStatus The health status of the controller. - - @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL. - @retval HealthStatus The Health status of specify controller. - @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. - @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. - @retval EFI_SUCCESS The Health related operation has been taken successfully. - -**/ -EFI_STATUS -EFIAPI -GetSingleControllerHealthStatus ( - IN OUT LIST_ENTRY *DriverHealthList, - IN EFI_HANDLE DriverHandle, - IN EFI_HANDLE ControllerHandle, OPTIONAL - IN EFI_HANDLE ChildHandle, OPTIONAL - IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, - IN EFI_DRIVER_HEALTH_STATUS *HealthStatus - ) -{ - EFI_STATUS Status; - EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList; - EFI_HII_HANDLE FormHiiHandle; - DRIVER_HEALTH_INFO *DriverHealthInfo; - - if (HealthStatus == NULL) { - // - // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER - // - return EFI_INVALID_PARAMETER; - } - - // - // Assume the HealthStatus is healthy - // - *HealthStatus = EfiDriverHealthStatusHealthy; - - if (DriverHealth == NULL) { - // - // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER - // - return EFI_INVALID_PARAMETER; - } - - if (ControllerHandle == NULL) { - // - // If ControllerHandle is NULL, the return the cumulative health status of the driver - // - Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, HealthStatus, NULL, NULL); - if (*HealthStatus == EfiDriverHealthStatusHealthy) { - // - // Add the driver health related information into the list - // - DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO)); - if (DriverHealthInfo == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE; - DriverHealthInfo->DriverHandle = DriverHandle; - DriverHealthInfo->ControllerHandle = NULL; - DriverHealthInfo->ChildHandle = NULL; - DriverHealthInfo->HiiHandle = NULL; - DriverHealthInfo->DriverHealth = DriverHealth; - DriverHealthInfo->MessageList = NULL; - DriverHealthInfo->HealthStatus = *HealthStatus; - - InsertTailList (DriverHealthList, &DriverHealthInfo->Link); - } - return Status; - } - - MessageList = NULL; - FormHiiHandle = NULL; - - // - // Collect the health status with the optional HII message list - // - Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, HealthStatus, &MessageList, &FormHiiHandle); - - if (EFI_ERROR (Status)) { - // - // If the health status could not be retrieved, then return immediately - // - return Status; - } - - // - // Add the driver health related information into the list - // - DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO)); - if (DriverHealthInfo == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE; - DriverHealthInfo->DriverHandle = DriverHandle; - DriverHealthInfo->ControllerHandle = ControllerHandle; - DriverHealthInfo->ChildHandle = ChildHandle; - DriverHealthInfo->HiiHandle = FormHiiHandle; - DriverHealthInfo->DriverHealth = DriverHealth; - DriverHealthInfo->MessageList = MessageList; - DriverHealthInfo->HealthStatus = *HealthStatus; - - InsertTailList (DriverHealthList, &DriverHealthInfo->Link); - - return EFI_SUCCESS; -} - -/** - Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database, - and queries each EFI Driver Health Protocol to determine if one or more of the controllers - managed by each EFI Driver Health Protocol instance are not healthy. - - @param DriverHealthList A Pointer to the list contain all of the platform driver health - information. - - @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. - @retval EFI_SUCCESS All the controllers in the platform are healthy. - @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. - -**/ -EFI_STATUS -GetAllControllersHealthStatus ( - IN OUT LIST_ENTRY *DriverHealthList - ) -{ - EFI_STATUS Status; - UINTN NumHandles; - EFI_HANDLE *DriverHealthHandles; - EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth; - EFI_DRIVER_HEALTH_STATUS HealthStatus; - UINTN DriverHealthIndex; - EFI_HANDLE *Handles; - UINTN HandleCount; - UINTN ControllerIndex; - UINTN ChildIndex; - - // - // Initialize local variables - // - Handles = NULL; - DriverHealthHandles = NULL; - NumHandles = 0; - HandleCount = 0; - - HealthStatus = EfiDriverHealthStatusHealthy; - - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiDriverHealthProtocolGuid, - NULL, - &NumHandles, - &DriverHealthHandles - ); - - if (Status == EFI_NOT_FOUND || NumHandles == 0) { - // - // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND - // - return EFI_NOT_FOUND; - } - - if (EFI_ERROR (Status) || DriverHealthHandles == NULL) { - // - // If the list of Driver Health Protocol handles can not be retrieved, then - // return EFI_OUT_OF_RESOURCES - // - return EFI_OUT_OF_RESOURCES; - } - - // - // Check the health status of all controllers in the platform - // Start by looping through all the Driver Health Protocol handles in the handle database - // - for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) { - // - // Skip NULL Driver Health Protocol handles - // - if (DriverHealthHandles[DriverHealthIndex] == NULL) { - continue; - } - - // - // Retrieve the Driver Health Protocol from DriverHandle - // - Status = gBS->HandleProtocol ( - DriverHealthHandles[DriverHealthIndex], - &gEfiDriverHealthProtocolGuid, - (VOID **)&DriverHealth - ); - if (EFI_ERROR (Status)) { - // - // If the Driver Health Protocol can not be retrieved, then skip to the next - // Driver Health Protocol handle - // - continue; - } - - // - // Check the health of all the controllers managed by a Driver Health Protocol handle - // - Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], NULL, NULL, DriverHealth, &HealthStatus); - - // - // If Status is an error code, then the health information could not be retrieved, so assume healthy - // and skip to the next Driver Health Protocol handle - // - if (EFI_ERROR (Status)) { - continue; - } - - // - // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next - // Driver Health Protocol handle - // - if (HealthStatus == EfiDriverHealthStatusHealthy) { - continue; - } - - // - // See if the list of all handles in the handle database has been retrieved - // - // - if (Handles == NULL) { - // - // Retrieve the list of all handles from the handle database - // - Status = gBS->LocateHandleBuffer ( - AllHandles, - NULL, - NULL, - &HandleCount, - &Handles - ); - if (EFI_ERROR (Status) || Handles == NULL) { - // - // If all the handles in the handle database can not be retrieved, then - // return EFI_OUT_OF_RESOURCES - // - Status = EFI_OUT_OF_RESOURCES; - goto Done; - } - } - // - // Loop through all the controller handles in the handle database - // - for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) { - // - // Skip NULL controller handles - // - if (Handles[ControllerIndex] == NULL) { - continue; - } - - Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL, DriverHealth, &HealthStatus); - if (EFI_ERROR (Status)) { - // - // If Status is an error code, then the health information could not be retrieved, so assume healthy - // - HealthStatus = EfiDriverHealthStatusHealthy; - } - - // - // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers - // - if (EFI_ERROR (Status)) { - continue; - } - - // - // Loop through all the child handles in the handle database - // - for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) { - // - // Skip NULL child handles - // - if (Handles[ChildIndex] == NULL) { - continue; - } - - Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex], DriverHealth, &HealthStatus); - if (EFI_ERROR (Status)) { - // - // If Status is an error code, then the health information could not be retrieved, so assume healthy - // - HealthStatus = EfiDriverHealthStatusHealthy; - } - - // - // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child - // - if (EFI_ERROR (Status)) { - continue; - } - } - } - } - - Status = EFI_SUCCESS; - -Done: - if (Handles != NULL) { - gBS->FreePool (Handles); - } - if (DriverHealthHandles != NULL) { - gBS->FreePool (DriverHealthHandles); - } - - return Status; -} - - -/** - Check the healthy status of the platform, this function will return immediately while found one driver - in the platform are not healthy. - - @retval FALSE at least one driver in the platform are not healthy. - @retval TRUE No controller install Driver Health Protocol, - or all controllers in the platform are in healthy status. -**/ -BOOLEAN -PlaformHealthStatusCheck ( - VOID - ) -{ - EFI_DRIVER_HEALTH_STATUS HealthStatus; - EFI_STATUS Status; - UINTN Index; - UINTN NoHandles; - EFI_HANDLE *DriverHealthHandles; - EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth; - BOOLEAN AllHealthy; - - // - // Initialize local variables - // - DriverHealthHandles = NULL; - DriverHealth = NULL; - - HealthStatus = EfiDriverHealthStatusHealthy; - - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiDriverHealthProtocolGuid, - NULL, - &NoHandles, - &DriverHealthHandles - ); - // - // There are no handles match the search for Driver Health Protocol has been installed. - // - if (Status == EFI_NOT_FOUND) { - return TRUE; - } - // - // Assume all modules are healthy. - // - AllHealthy = TRUE; - - // - // Found one or more Handles. - // - if (!EFI_ERROR (Status)) { - for (Index = 0; Index < NoHandles; Index++) { - Status = gBS->HandleProtocol ( - DriverHealthHandles[Index], - &gEfiDriverHealthProtocolGuid, - (VOID **) &DriverHealth - ); - if (!EFI_ERROR (Status)) { - Status = DriverHealth->GetHealthStatus ( - DriverHealth, - NULL, - NULL, - &HealthStatus, - NULL, - NULL - ); - } - // - // Get the healthy status of the module - // - if (!EFI_ERROR (Status)) { - if (HealthStatus != EfiDriverHealthStatusHealthy) { - // - // Return immediately one driver's status not in healthy. - // - return FALSE; - } - } - } - } - return AllHealthy; -} - -/** - Processes a single controller using the EFI Driver Health Protocol associated with - that controller. This algorithm continues to query the GetHealthStatus() service until - one of the legal terminal states of the EFI Driver Health Protocol is reached. This may - require the processing of HII Messages, HII Form, and invocation of repair operations. - - @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. - @param ControllerHandle The class guid specifies which form set will be displayed. - @param ChildHandle The handle of the child controller to retrieve the health - status on. This is an optional parameter that may be NULL. - @param HealthStatus The health status of the controller. - @param MessageList An array of warning or error messages associated - with the controller specified by ControllerHandle and - ChildHandle. This is an optional parameter that may be NULL. - @param FormHiiHandle The HII handle for an HII form associated with the - controller specified by ControllerHandle and ChildHandle. - @param RebootRequired Indicate whether a reboot is required to repair the controller. -**/ -VOID -ProcessSingleControllerHealth ( - IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, - IN EFI_HANDLE ControllerHandle, OPTIONAL - IN EFI_HANDLE ChildHandle, OPTIONAL - IN EFI_DRIVER_HEALTH_STATUS HealthStatus, - IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL - IN EFI_HII_HANDLE FormHiiHandle, - IN OUT BOOLEAN *RebootRequired - ) -{ - EFI_STATUS Status; - EFI_DRIVER_HEALTH_STATUS LocalHealthStatus; - - LocalHealthStatus = HealthStatus; - // - // If the module need to be repaired or reconfiguration, will process it until - // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair - // will be in (Health, Failed, Configuration Required). - // - while(LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired || - LocalHealthStatus == EfiDriverHealthStatusRepairRequired) { - - if (LocalHealthStatus == EfiDriverHealthStatusRepairRequired) { - Status = DriverHealth->Repair ( - DriverHealth, - ControllerHandle, - ChildHandle, - RepairNotify - ); - } - // - // Via a form of the driver need to do configuration provided to process of status in - // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in - // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required). - // - if (LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired) { - if (FormHiiHandle != NULL) { - Status = gFormBrowser2->SendForm ( - gFormBrowser2, - &FormHiiHandle, - 1, - &gEfiHiiDriverHealthFormsetGuid, - 0, - NULL, - NULL - ); - ASSERT( !EFI_ERROR (Status)); - } else { - // - // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop - // - break; - } - } - - Status = DriverHealth->GetHealthStatus ( - DriverHealth, - ControllerHandle, - ChildHandle, - &LocalHealthStatus, - NULL, - &FormHiiHandle - ); - ASSERT_EFI_ERROR (Status); - - if (*MessageList != NULL) { - ProcessMessages (*MessageList); - } - } - - // - // Health status in {Healthy, Failed} may also have Messages need to process - // - if (LocalHealthStatus == EfiDriverHealthStatusHealthy || LocalHealthStatus == EfiDriverHealthStatusFailed) { - if (*MessageList != NULL) { - ProcessMessages (*MessageList); - } - } - // - // Check for RebootRequired or ReconnectRequired - // - if (LocalHealthStatus == EfiDriverHealthStatusRebootRequired) { - *RebootRequired = TRUE; - } - - // - // Do reconnect if need. - // - if (LocalHealthStatus == EfiDriverHealthStatusReconnectRequired) { - Status = gBS->DisconnectController (ControllerHandle, NULL, NULL); - if (EFI_ERROR (Status)) { - // - // Disconnect failed. Need to promote reconnect to a reboot. - // - *RebootRequired = TRUE; - } else { - gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE); - } - } -} - - -/** - Reports the progress of a repair operation. - - @param[in] Value A value between 0 and Limit that identifies the current - progress of the repair operation. - - @param[in] Limit The maximum value of Value for the current repair operation. - For example, a driver that wants to specify progress in - percent would use a Limit value of 100. - - @retval EFI_SUCCESS The progress of a repair operation is reported successfully. - -**/ -EFI_STATUS -EFIAPI -RepairNotify ( - IN UINTN Value, - IN UINTN Limit - ) -{ - UINTN Percent; - - if (Limit == 0) { - Print(L"Repair Progress Undefined\n\r"); - } else { - Percent = Value * 100 / Limit; - Print(L"Repair Progress = %3d%%\n\r", Percent); - } - return EFI_SUCCESS; -} - -/** - Processes a set of messages returned by the GetHealthStatus () - service of the EFI Driver Health Protocol - - @param MessageList The MessageList point to messages need to processed. - -**/ -VOID -ProcessMessages ( - IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList - ) -{ - UINTN MessageIndex; - EFI_STRING MessageString; - - for (MessageIndex = 0; - MessageList[MessageIndex].HiiHandle != NULL; - MessageIndex++) { - - MessageString = HiiGetString ( - MessageList[MessageIndex].HiiHandle, - MessageList[MessageIndex].StringId, - NULL - ); - if (MessageString != NULL) { - // - // User can customize the output. Just simply print out the MessageString like below. - // Also can use the HiiHandle to display message on the front page. - // - // Print(L"%s\n",MessageString); - // gBS->Stall (100000); - } - } - -} - -/** - Repair the whole platform. - - This function is the main entry for user choose "Repair All" in the front page. - It will try to do recovery job till all the driver health protocol installed modules - reach a terminal state. - - @param DriverHealthList A Pointer to the list contain all of the platform driver health - information. - -**/ -VOID -PlatformRepairAll ( - IN LIST_ENTRY *DriverHealthList - ) -{ - DRIVER_HEALTH_INFO *DriverHealthInfo; - LIST_ENTRY *Link; - BOOLEAN RebootRequired; - - ASSERT (DriverHealthList != NULL); - - RebootRequired = FALSE; - - for ( Link = GetFirstNode (DriverHealthList) - ; !IsNull (DriverHealthList, Link) - ; Link = GetNextNode (DriverHealthList, Link) - ) { - DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); - // - // Do driver health status operation by each link node - // - ASSERT (DriverHealthInfo != NULL); - - ProcessSingleControllerHealth ( - DriverHealthInfo->DriverHealth, - DriverHealthInfo->ControllerHandle, - DriverHealthInfo->ChildHandle, - DriverHealthInfo->HealthStatus, - &(DriverHealthInfo->MessageList), - DriverHealthInfo->HiiHandle, - &RebootRequired - ); - } - - if (RebootRequired) { - gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); - } -} - -/** - - Select the best matching language according to front page policy for best user experience. - - This function supports both ISO 639-2 and RFC 4646 language codes, but language - code types may not be mixed in a single call to this function. - - @param SupportedLanguages A pointer to a Null-terminated ASCII string that - contains a set of language codes in the format - specified by Iso639Language. - @param Iso639Language If TRUE, then all language codes are assumed to be - in ISO 639-2 format. If FALSE, then all language - codes are assumed to be in RFC 4646 language format. - - @retval NULL The best matching language could not be found in SupportedLanguages. - @retval NULL There are not enough resources available to return the best matching - language. - @retval Other A pointer to a Null-terminated ASCII string that is the best matching - language in SupportedLanguages. -**/ -CHAR8 * -DriverHealthSelectBestLanguage ( - IN CHAR8 *SupportedLanguages, - IN BOOLEAN Iso639Language - ) -{ - CHAR8 *LanguageVariable; - CHAR8 *BestLanguage; - - GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID**)&LanguageVariable, NULL); - - BestLanguage = GetBestLanguage( - SupportedLanguages, - Iso639Language, - (LanguageVariable != NULL) ? LanguageVariable : "", - Iso639Language ? "eng" : "en-US", - NULL - ); - if (LanguageVariable != NULL) { - FreePool (LanguageVariable); - } - - return BestLanguage; -} - - - -/** - - This is an internal worker function to get the Component Name (2) protocol interface - and the language it supports. - - @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @param ComponentName A pointer to the Component Name (2) protocol interface. - @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the - located Component Name (2) instance. - - @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find - the best matching language it support. - @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol. - @retval Other Some error occurs when locating Component Name (2) protocol instance or finding - the supported language. - -**/ -EFI_STATUS -GetComponentNameWorker ( - IN EFI_GUID *ProtocolGuid, - IN EFI_HANDLE DriverBindingHandle, - OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName, - OUT CHAR8 **SupportedLanguage - ) -{ - EFI_STATUS Status; - - // - // Locate Component Name (2) protocol on the driver binging handle. - // - Status = gBS->OpenProtocol ( - DriverBindingHandle, - ProtocolGuid, - (VOID **) ComponentName, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Apply shell policy to select the best language. - // - *SupportedLanguage = DriverHealthSelectBestLanguage ( - (*ComponentName)->SupportedLanguages, - (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid) - ); - if (*SupportedLanguage == NULL) { - Status = EFI_UNSUPPORTED; - } - - return Status; -} - -/** - - This is an internal worker function to get driver name from Component Name (2) protocol interface. - - - @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @param DriverName A pointer to the Unicode string to return. This Unicode string is the name - of the driver specified by This. - - @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol - interface. - @retval Other The driver name cannot be retrieved from Component Name (2) protocol - interface. - -**/ -EFI_STATUS -GetDriverNameWorker ( - IN EFI_GUID *ProtocolGuid, - IN EFI_HANDLE DriverBindingHandle, - OUT CHAR16 **DriverName - ) -{ - EFI_STATUS Status; - CHAR8 *BestLanguage; - EFI_COMPONENT_NAME_PROTOCOL *ComponentName; - - // - // Retrieve Component Name (2) protocol instance on the driver binding handle and - // find the best language this instance supports. - // - Status = GetComponentNameWorker ( - ProtocolGuid, - DriverBindingHandle, - &ComponentName, - &BestLanguage - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the driver name from Component Name (2) protocol instance on the driver binging handle. - // - Status = ComponentName->GetDriverName ( - ComponentName, - BestLanguage, - DriverName - ); - FreePool (BestLanguage); - - return Status; -} - -/** - - This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface - in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name. - If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward - compatibility support. - - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @param DriverName A pointer to the Unicode string to return. This Unicode string is the name - of the driver specified by This. - - @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol - interface. - @retval Other The driver name cannot be retrieved from Component Name (2) protocol - interface. - -**/ -EFI_STATUS -DriverHealthGetDriverName ( - IN EFI_HANDLE DriverBindingHandle, - OUT CHAR16 **DriverName - ) -{ - EFI_STATUS Status; - - // - // Get driver name from UEFI 2.0 Component Name 2 protocol interface. - // - Status = GetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, DriverName); - if (EFI_ERROR (Status)) { - // - // If it fails to get the driver name from Component Name protocol interface, we should fall back on - // EFI 1.1 Component Name protocol interface. - // - Status = GetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, DriverName); - } - - return Status; -} - - - -/** - This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface - in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. - If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward - compatibility support. - - @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @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 bus drivers that attempt to retrieve the name - of the bus controller. It will not be NULL for a bus driver that attempts - to retrieve the name of a child controller. - @param ControllerName A pointer to the Unicode string to return. This Unicode string - is the name of the controller specified by ControllerHandle and ChildHandle. - - @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol - interface. - @retval Other The controller name cannot be retrieved from Component Name (2) protocol. - -**/ -EFI_STATUS -GetControllerNameWorker ( - IN EFI_GUID *ProtocolGuid, - IN EFI_HANDLE DriverBindingHandle, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - CHAR8 *BestLanguage; - EFI_COMPONENT_NAME_PROTOCOL *ComponentName; - - // - // Retrieve Component Name (2) protocol instance on the driver binding handle and - // find the best language this instance supports. - // - Status = GetComponentNameWorker ( - ProtocolGuid, - DriverBindingHandle, - &ComponentName, - &BestLanguage - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the controller name from Component Name (2) protocol instance on the driver binging handle. - // - Status = ComponentName->GetControllerName ( - ComponentName, - ControllerHandle, - ChildHandle, - BestLanguage, - ControllerName - ); - FreePool (BestLanguage); - - return Status; -} - -/** - - This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface - in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. - If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward - compatibility support. - - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @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 bus drivers that attempt to retrieve the name - of the bus controller. It will not be NULL for a bus driver that attempts - to retrieve the name of a child controller. - @param ControllerName A pointer to the Unicode string to return. This Unicode string - is the name of the controller specified by ControllerHandle and ChildHandle. - - @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol - interface. - @retval Other The controller name cannot be retrieved from Component Name (2) protocol. - -**/ -EFI_STATUS -DriverHealthGetControllerName ( - IN EFI_HANDLE DriverBindingHandle, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - - // - // Get controller name from UEFI 2.0 Component Name 2 protocol interface. - // - Status = GetControllerNameWorker ( - &gEfiComponentName2ProtocolGuid, - DriverBindingHandle, - ControllerHandle, - ChildHandle, - ControllerName - ); - if (EFI_ERROR (Status)) { - // - // If it fails to get the controller name from Component Name protocol interface, we should fall back on - // EFI 1.1 Component Name protocol interface. - // - Status = GetControllerNameWorker ( - &gEfiComponentNameProtocolGuid, - DriverBindingHandle, - ControllerHandle, - ChildHandle, - ControllerName - ); - } - - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h deleted file mode 100644 index 95bde8de5a..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h +++ /dev/null @@ -1,523 +0,0 @@ -/** @file - The platform device manager reference implement - -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 _DEVICE_MANAGER_H_ -#define _DEVICE_MANAGER_H_ - -#include "Bds.h" -#include "FrontPage.h" -#include "DeviceManagerVfr.h" -#include - -#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('D', 'M', 'C', 'B') -#define DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'D', 'H') - - -typedef struct { - UINTN Signature; - - /// - /// Device Manager HII relative handles - /// - EFI_HII_HANDLE HiiHandle; - - /// - /// Driver Health HII relative handles - /// - EFI_HII_HANDLE DriverHealthHiiHandle; - - EFI_HANDLE DriverHandle; - EFI_HANDLE DriverHealthHandle; - - /// - /// Device Manager Produced protocols - /// - EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; - - /// - /// Driver Health Produced protocols - /// - EFI_HII_CONFIG_ACCESS_PROTOCOL DriverHealthConfigAccess; - - /// - /// Configuration data - /// - UINT8 VideoBios; -} DEVICE_MANAGER_CALLBACK_DATA; - - -typedef struct { - UINTN Signature; - LIST_ENTRY Link; - - /// - /// HII relative handles - /// - EFI_HII_HANDLE HiiHandle; - - /// - /// Driver relative handles - /// - EFI_HANDLE DriverHandle; - EFI_HANDLE ControllerHandle; - EFI_HANDLE ChildHandle; - - EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth; - /// - /// Driver health messages of the specify Driver - /// - EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList; - - /// - /// Driver Health status - /// - EFI_DRIVER_HEALTH_STATUS HealthStatus; -} DRIVER_HEALTH_INFO; - -typedef struct { - EFI_STRING_ID PromptId; - EFI_QUESTION_ID QuestionId; -}MENU_INFO_ITEM; - -typedef struct { - UINTN CurListLen; - UINTN MaxListLen; - MENU_INFO_ITEM *NodeList; -} MAC_ADDRESS_NODE_LIST; - -#define DEVICE_MANAGER_HEALTH_INFO_FROM_LINK(a) \ - CR (a, \ - DRIVER_HEALTH_INFO, \ - Link, \ - DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE \ - ) - -#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \ - CR (a, \ - DEVICE_MANAGER_CALLBACK_DATA, \ - ConfigAccess, \ - DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \ - ) -typedef struct { - EFI_STRING_ID StringId; - UINT16 Class; -} DEVICE_MANAGER_MENU_ITEM; - -/** - This function is invoked if user selected a interactive opcode from Device Manager's - Formset. The decision by user is saved to gCallbackKey for later processing. If - user set VBIOS, the new value is saved to EFI variable. - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. - -**/ -EFI_STATUS -EFIAPI -DeviceManagerCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ); - -/** - This function is invoked if user selected a interactive opcode from Driver Health's - Formset. The decision by user is saved to gCallbackKey for later processing. - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. - -**/ -EFI_STATUS -EFIAPI -DriverHealthCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ); - - -/** - - This function registers HII packages to HII database. - - @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully. - @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered. - -**/ -EFI_STATUS -InitializeDeviceManager ( - VOID - ); - -/** - - Call the browser and display the device manager to allow user - to configure the platform. - - This function create the dynamic content for device manager. It includes - section header for all class of devices, one-of opcode to set VBIOS. - - @retval EFI_SUCCESS Operation is successful. - @retval Other values if failed to clean up the dynamic content from HII - database. - -**/ -EFI_STATUS -CallDeviceManager ( - VOID - ); - - -/** - Check the Driver Health status of a single controller and try to process it if not healthy. - - This function called by CheckAllControllersHealthStatus () function in order to process a specify - contoller's health state. - - @param DriverHealthList A Pointer to the list contain all of the platform driver health information. - @param DriverHandle The handle of driver. - @param ControllerHandle The class guid specifies which form set will be displayed. - @param ChildHandle The handle of the child controller to retrieve the health - status on. This is an optional parameter that may be NULL. - @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. - @param HealthStatus The health status of the controller. - - @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL. - @retval HealthStatus The Health status of specify controller. - @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. - @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. - @retval EFI_SUCCESS The Health related operation has been taken successfully. - -**/ -EFI_STATUS -EFIAPI -GetSingleControllerHealthStatus ( - IN OUT LIST_ENTRY *DriverHealthList, - IN EFI_HANDLE DriverHandle, - IN EFI_HANDLE ControllerHandle, OPTIONAL - IN EFI_HANDLE ChildHandle, OPTIONAL - IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, - IN EFI_DRIVER_HEALTH_STATUS *HealthStatus - ); - -/** - Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database, - and queries each EFI Driver Health Protocol to determine if one or more of the controllers - managed by each EFI Driver Health Protocol instance are not healthy. - - @param DriverHealthList A Pointer to the list contain all of the platform driver health - information. - - @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. - @retval EFI_SUCCESS All the controllers in the platform are healthy. - @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. - -**/ -EFI_STATUS -GetAllControllersHealthStatus ( - IN OUT LIST_ENTRY *DriverHealthList - ); - -/** - Check the healthy status of the platform, this function will return immediately while found one driver - in the platform are not healthy. - - @retval FALSE at least one driver in the platform are not healthy. - @retval TRUE No controller install Driver Health Protocol, - or all controllers in the platform are in healthy status. -**/ -BOOLEAN -PlaformHealthStatusCheck ( - VOID - ); - -/** - Repair the whole platform. - - This function is the main entry for user choose "Repair All" in the front page. - It will try to do recovery job till all the driver health protocol installed modules - reach a terminal state. - - @param DriverHealthList A Pointer to the list contain all of the platform driver health - information. - -**/ -VOID -PlatformRepairAll ( - IN LIST_ENTRY *DriverHealthList - ); - -/** - Processes a single controller using the EFI Driver Health Protocol associated with - that controller. This algorithm continues to query the GetHealthStatus() service until - one of the legal terminal states of the EFI Driver Health Protocol is reached. This may - require the processing of HII Messages, HII Form, and invocation of repair operations. - - @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. - @param ControllerHandle The class guid specifies which form set will be displayed. - @param ChildHandle The handle of the child controller to retrieve the health - status on. This is an optional parameter that may be NULL. - @param HealthStatus The health status of the controller. - @param MessageList An array of warning or error messages associated - with the controller specified by ControllerHandle and - ChildHandle. This is an optional parameter that may be NULL. - @param FormHiiHandle The HII handle for an HII form associated with the - controller specified by ControllerHandle and ChildHandle. - @param RebootRequired Indicate whether a reboot is required to repair the controller. -**/ -VOID -ProcessSingleControllerHealth ( - IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, - IN EFI_HANDLE ControllerHandle, OPTIONAL - IN EFI_HANDLE ChildHandle, OPTIONAL - IN EFI_DRIVER_HEALTH_STATUS HealthStatus, - IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL - IN EFI_HII_HANDLE FormHiiHandle, - IN OUT BOOLEAN *RebootRequired - ); - -/** - Reports the progress of a repair operation. - - @param[in] Value A value between 0 and Limit that identifies the current - progress of the repair operation. - - @param[in] Limit The maximum value of Value for the current repair operation. - For example, a driver that wants to specify progress in - percent would use a Limit value of 100. - - @retval EFI_SUCCESS The progress of a repair operation is reported successfully. - -**/ -EFI_STATUS -EFIAPI -RepairNotify ( - IN UINTN Value, - IN UINTN Limit - ); - -/** - Processes a set of messages returned by the GetHealthStatus () - service of the EFI Driver Health Protocol - - @param MessageList The MessageList point to messages need to processed. - -**/ -VOID -ProcessMessages ( - IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList - ); - - -/** - Collect and display the platform's driver health relative information, allow user to do interactive - operation while the platform is unhealthy. - - This function display a form which divided into two parts. The one list all modules which has installed - driver health protocol. The list usually contain driver name, controller name, and it's health info. - While the driver name can't be retrieved, will use device path as backup. The other part of the form provide - a choice to the user to repair all platform. - -**/ -VOID -CallDriverHealth ( - VOID - ); - -/** - - Select the best matching language according to front page policy for best user experience. - - This function supports both ISO 639-2 and RFC 4646 language codes, but language - code types may not be mixed in a single call to this function. - - @param SupportedLanguages A pointer to a Null-terminated ASCII string that - contains a set of language codes in the format - specified by Iso639Language. - @param Iso639Language If TRUE, then all language codes are assumed to be - in ISO 639-2 format. If FALSE, then all language - codes are assumed to be in RFC 4646 language format. - - @retval NULL The best matching language could not be found in SupportedLanguages. - @retval NULL There are not enough resources available to return the best matching - language. - @retval Other A pointer to a Null-terminated ASCII string that is the best matching - language in SupportedLanguages. -**/ -CHAR8 * -DriverHealthSelectBestLanguage ( - IN CHAR8 *SupportedLanguages, - IN BOOLEAN Iso639Language - ); - -/** - - This is an internal worker function to get the Component Name (2) protocol interface - and the language it supports. - - @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @param ComponentName A pointer to the Component Name (2) protocol interface. - @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the - located Component Name (2) instance. - - @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find - the best matching language it support. - @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol. - @retval Other Some error occurs when locating Component Name (2) protocol instance or finding - the supported language. - -**/ -EFI_STATUS -GetComponentNameWorker ( - IN EFI_GUID *ProtocolGuid, - IN EFI_HANDLE DriverBindingHandle, - OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName, - OUT CHAR8 **SupportedLanguage - ); - -/** - - This is an internal worker function to get driver name from Component Name (2) protocol interface. - - - @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @param DriverName A pointer to the Unicode string to return. This Unicode string is the name - of the driver specified by This. - - @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol - interface. - @retval Other The driver name cannot be retrieved from Component Name (2) protocol - interface. - -**/ -EFI_STATUS -GetDriverNameWorker ( - IN EFI_GUID *ProtocolGuid, - IN EFI_HANDLE DriverBindingHandle, - OUT CHAR16 **DriverName - ); - -/** - - This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface - in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name. - If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward - compatibility support. - - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @param DriverName A pointer to the Unicode string to return. This Unicode string is the name - of the driver specified by This. - - @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol - interface. - @retval Other The driver name cannot be retrieved from Component Name (2) protocol - interface. - -**/ -EFI_STATUS -DriverHealthGetDriverName ( - IN EFI_HANDLE DriverBindingHandle, - OUT CHAR16 **DriverName - ); - -/** - This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface - in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. - If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward - compatibility support. - - @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @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 bus drivers that attempt to retrieve the name - of the bus controller. It will not be NULL for a bus driver that attempts - to retrieve the name of a child controller. - @param ControllerName A pointer to the Unicode string to return. This Unicode string - is the name of the controller specified by ControllerHandle and ChildHandle. - - @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol - interface. - @retval Other The controller name cannot be retrieved from Component Name (2) protocol. - -**/ -EFI_STATUS -GetControllerNameWorker ( - IN EFI_GUID *ProtocolGuid, - IN EFI_HANDLE DriverBindingHandle, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle, - OUT CHAR16 **ControllerName - ); - -/** - This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface - in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. - If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward - compatibility support. - - @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. - @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 bus drivers that attempt to retrieve the name - of the bus controller. It will not be NULL for a bus driver that attempts - to retrieve the name of a child controller. - @param ControllerName A pointer to the Unicode string to return. This Unicode string - is the name of the controller specified by ControllerHandle and ChildHandle. - - @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol - interface. - @retval Other The controller name cannot be retrieved from Component Name (2) protocol. - -**/ -EFI_STATUS -DriverHealthGetControllerName ( - IN EFI_HANDLE DriverBindingHandle, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle, - OUT CHAR16 **ControllerName - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni deleted file mode 100644 index 1553f10bf9..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr deleted file mode 100644 index 0ad671bdca..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr +++ /dev/null @@ -1,93 +0,0 @@ -///** @file -// -// Device Manager formset. -// -// Copyright (c) 2004 - 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 "DeviceManagerVfr.h" - -#define EFI_DISK_DEVICE_CLASS 0x0001 -#define EFI_VIDEO_DEVICE_CLASS 0x0002 -#define EFI_NETWORK_DEVICE_CLASS 0x0004 -#define EFI_INPUT_DEVICE_CLASS 0x0008 -#define EFI_ON_BOARD_DEVICE_CLASS 0x0010 -#define EFI_OTHER_DEVICE_CLASS 0x0020 - -#define DEVICE_MANAGER_CLASS 0x0000 -#define FRONT_PAGE_SUBCLASS 0x0003 - -formset - guid = DEVICE_MANAGER_FORMSET_GUID, - title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE), - help = STRING_TOKEN(STR_EMPTY_STRING), - classguid = DEVICE_MANAGER_FORMSET_GUID, - - form formid = DEVICE_MANAGER_FORM_ID, - title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE); - - subtitle text = STRING_TOKEN(STR_DEVICES_LIST); - // - // This is where devices get added to the device manager hierarchy - // - label EFI_DISK_DEVICE_CLASS; -// label LABEL_END; // Since next opcode is a label, so this one could be omitted to save code size - - label EFI_VIDEO_DEVICE_CLASS; -// label LABEL_END; - - label EFI_NETWORK_DEVICE_CLASS; -// label LABEL_END; - - label EFI_INPUT_DEVICE_CLASS; -// label LABEL_END; - - label EFI_ON_BOARD_DEVICE_CLASS; -// label LABEL_END; - -// label EFI_OTHER_DEVICE_CLASS; - - label LABEL_DEVICES_LIST; - label LABEL_END; - - subtitle text = STRING_TOKEN(STR_EMPTY_STRING); - - label LABEL_VBIOS; - label LABEL_END; - - subtitle text = STRING_TOKEN(STR_EMPTY_STRING); - subtitle text = STRING_TOKEN(STR_EXIT_STRING); - - endform; - - form formid = NETWORK_DEVICE_LIST_FORM_ID, - title = STRING_TOKEN(STR_FORM_NETWORK_DEVICE_LIST_TITLE); - - subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE_LIST_STRING); - - label LABEL_NETWORK_DEVICE_LIST_ID; - label LABEL_END; - subtitle text = STRING_TOKEN(STR_EMPTY_STRING); - subtitle text = STRING_TOKEN(STR_EXIT_STRING); - endform; - - form formid = NETWORK_DEVICE_FORM_ID, - title = STRING_TOKEN(STR_FORM_NETWORK_DEVICE_TITLE); - - subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE_STRING); - - label LABEL_NETWORK_DEVICE_ID; - label LABEL_END; - subtitle text = STRING_TOKEN(STR_EMPTY_STRING); - subtitle text = STRING_TOKEN(STR_EXIT_STRING); - endform; -endformset; - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h deleted file mode 100644 index b6b086600f..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.h +++ /dev/null @@ -1,56 +0,0 @@ -/** @file - The platform device manager reference implement - -Copyright (c) 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 _DEVICE_MANAGER_VFR_H_ -#define _DEVICE_MANAGER_VFR_H_ - -#include - -#define LABEL_DEVICES_LIST 0x1100 -#define LABEL_NETWORK_DEVICE_LIST_ID 0x1101 -#define LABEL_NETWORK_DEVICE_ID 0x1102 -#define LABEL_END 0xffff -#define LABEL_FORM_ID_OFFSET 0x0100 - -#define LABEL_DRIVER_HEALTH 0x2000 -#define LABEL_DRIVER_HEALTH_END 0x2001 - -#define LABEL_DRIVER_HEALTH_REAPIR_ALL 0x3000 -#define LABEL_DRIVER_HEALTH_REAPIR_ALL_END 0x3001 - -#define LABEL_VBIOS 0x0040 - -#define INVALID_FORM_ID 0x0FFF -#define DEVICE_MANAGER_FORM_ID 0x1000 -#define NETWORK_DEVICE_LIST_FORM_ID 0x1001 -#define NETWORK_DEVICE_FORM_ID 0x1002 -#define DRIVER_HEALTH_FORM_ID 0x1003 -#define DEVICE_KEY_OFFSET 0x4000 -#define NETWORK_DEVICE_LIST_KEY_OFFSET 0x2000 -#define DEVICE_MANAGER_KEY_VBIOS 0x3000 -#define MAX_KEY_SECTION_LEN 0x1000 - -#define DEVICE_MANAGER_KEY_DRIVER_HEALTH 0x1111 -#define DRIVER_HEALTH_KEY_OFFSET 0x2000 -#define DRIVER_HEALTH_REPAIR_ALL_KEY 0x3000 -#define DRIVER_HEALTH_RETURN_KEY 0x4000 - -#define QUESTION_NETWORK_DEVICE_ID 0x3FFF -// -// These are the VFR compiler generated data representing our VFR data. -// -extern UINT8 DeviceManagerVfrBin[]; -extern UINT8 DriverHealthVfrBin[]; - -#endif diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DriverHealthVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DriverHealthVfr.Vfr deleted file mode 100644 index cb1a8f887b..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DriverHealthVfr.Vfr +++ /dev/null @@ -1,38 +0,0 @@ -///** @file -// -// Driver Health formset. -// -// Copyright (c) 2004 - 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 "DeviceManagerVfr.h" - -formset - guid = DRIVER_HEALTH_FORMSET_GUID, - title = STRING_TOKEN(STR_DH_BANNER), - help = STRING_TOKEN(STR_EMPTY_STRING), - classguid = DRIVER_HEALTH_FORMSET_GUID, - - form formid = DRIVER_HEALTH_FORM_ID, - title = STRING_TOKEN(STR_DH_BANNER); - - label LABEL_DRIVER_HEALTH; - label LABEL_DRIVER_HEALTH_END; - - subtitle text = STRING_TOKEN(STR_LAST_STRING); - label LABEL_DRIVER_HEALTH_REAPIR_ALL; - label LABEL_DRIVER_HEALTH_REAPIR_ALL_END; - - subtitle text = STRING_TOKEN(STR_LAST_STRING); - subtitle text = STRING_TOKEN(STR_HELP_FOOTER); - subtitle text = STRING_TOKEN(STR_LAST_STRING); - endform; -endformset; diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c deleted file mode 100644 index f04da16598..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c +++ /dev/null @@ -1,1480 +0,0 @@ -/** @file - FrontPage routines to handle the callbacks and browser calls - -Copyright (c) 2004 - 2016, Intel 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 "Bds.h" -#include "FrontPage.h" -#include "Language.h" -#include "Hotkey.h" - -BOOLEAN mModeInitialized = FALSE; - -BOOLEAN gConnectAllHappened = FALSE; -UINTN gCallbackKey; -CHAR8 *mLanguageString; - -// -// Boot video resolution and text mode. -// -UINT32 mBootHorizontalResolution = 0; -UINT32 mBootVerticalResolution = 0; -UINT32 mBootTextModeColumn = 0; -UINT32 mBootTextModeRow = 0; -// -// BIOS setup video resolution and text mode. -// -UINT32 mSetupTextModeColumn = 0; -UINT32 mSetupTextModeRow = 0; -UINT32 mSetupHorizontalResolution = 0; -UINT32 mSetupVerticalResolution = 0; - -EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2; - -FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = { - FRONT_PAGE_CALLBACK_DATA_SIGNATURE, - NULL, - NULL, - NULL, - { - FakeExtractConfig, - FakeRouteConfig, - FrontPageCallback - } -}; - -HII_VENDOR_DEVICE_PATH mFrontPageHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - FRONT_PAGE_FORMSET_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 illegal syntax, or unknown name. - @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. - -**/ -EFI_STATUS -EFIAPI -FakeExtractConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Request, - OUT EFI_STRING *Progress, - OUT EFI_STRING *Results - ) -{ - if (Progress == NULL || Results == NULL) { - return EFI_INVALID_PARAMETER; - } - *Progress = Request; - return EFI_NOT_FOUND; -} - -/** - 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 -FakeRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ) -{ - if (Configuration == NULL || Progress == NULL) { - return EFI_INVALID_PARAMETER; - } - - *Progress = Configuration; - if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName) - && !HiiIsConfigHdrMatch (Configuration, &gFileExploreFormSetGuid, mFileExplorerStorageName)) { - return EFI_NOT_FOUND; - } - - *Progress = Configuration + StrLen (Configuration); - return EFI_SUCCESS; -} - -/** - This function processes the results of changes in configuration. - - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action Specifies the type of action taken by the browser. - @param QuestionId A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be saved. - @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. - -**/ -EFI_STATUS -EFIAPI -FrontPageCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - CHAR8 *LangCode; - CHAR8 *Lang; - UINTN Index; - - if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { - // - // All other action return unsupported. - // - return EFI_UNSUPPORTED; - } - - gCallbackKey = QuestionId; - - if (Action == EFI_BROWSER_ACTION_CHANGED) { - if ((Value == NULL) || (ActionRequest == NULL)) { - return EFI_INVALID_PARAMETER; - } - - switch (QuestionId) { - case FRONT_PAGE_KEY_CONTINUE: - // - // This is the continue - clear the screen and return an error to get out of FrontPage loop - // - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - break; - - case FRONT_PAGE_KEY_LANGUAGE: - // - // Allocate working buffer for RFC 4646 language in supported LanguageString. - // - Lang = AllocatePool (AsciiStrSize (mLanguageString)); - ASSERT (Lang != NULL); - - Index = 0; - LangCode = mLanguageString; - while (*LangCode != 0) { - GetNextLanguage (&LangCode, Lang); - - if (Index == Value->u8) { - break; - } - - Index++; - } - - if (Index == Value->u8) { - BdsDxeSetVariableAndReportStatusCodeOnError ( - L"PlatformLang", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - AsciiStrSize (Lang), - Lang - ); - } else { - ASSERT (FALSE); - } - - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - - FreePool (Lang); - break; - - default: - break; - } - } else if (Action == EFI_BROWSER_ACTION_CHANGING) { - if (Value == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // 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) - // - switch (QuestionId) { - case FRONT_PAGE_KEY_BOOT_MANAGER: - // - // Boot Manager - // - break; - - case FRONT_PAGE_KEY_DEVICE_MANAGER: - // - // Device Manager - // - break; - - case FRONT_PAGE_KEY_BOOT_MAINTAIN: - // - // Boot Maintenance Manager - // - break; - - default: - gCallbackKey = 0; - break; - } - } - - return EFI_SUCCESS; -} - -/** - Initialize HII information for the FrontPage - - - @param InitializeHiiData TRUE if HII elements need to be initialized. - - @retval EFI_SUCCESS The operation is successful. - @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed. - -**/ -EFI_STATUS -InitializeFrontPage ( - IN BOOLEAN InitializeHiiData - ) -{ - EFI_STATUS Status; - CHAR8 *LangCode; - CHAR8 *Lang; - UINTN LangSize; - CHAR8 *CurrentLang; - UINTN OptionCount; - CHAR16 *StringBuffer; - EFI_HII_HANDLE HiiHandle; - VOID *OptionsOpCodeHandle; - VOID *StartOpCodeHandle; - VOID *EndOpCodeHandle; - EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *EndLabel; - EFI_HII_STRING_PROTOCOL *HiiString; - UINTN StringSize; - - Lang = NULL; - StringBuffer = NULL; - - if (InitializeHiiData) { - // - // Initialize the Device Manager - // - InitializeDeviceManager (); - - // - // Initialize the Device Manager - // - InitializeBootManager (); - - gCallbackKey = 0; - - // - // Locate Hii relative protocols - // - Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Install Device Path Protocol and Config Access protocol to driver handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &gFrontPagePrivate.DriverHandle, - &gEfiDevicePathProtocolGuid, - &mFrontPageHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &gFrontPagePrivate.ConfigAccess, - NULL - ); - ASSERT_EFI_ERROR (Status); - - // - // Publish our HII data - // - gFrontPagePrivate.HiiHandle = HiiAddPackages ( - &gFrontPageFormSetGuid, - gFrontPagePrivate.DriverHandle, - FrontPageVfrBin, - BdsDxeStrings, - NULL - ); - if (gFrontPagePrivate.HiiHandle == NULL) { - return EFI_OUT_OF_RESOURCES; - } - } - - - // - // Init OpCode Handle and Allocate space for creation of UpdateData Buffer - // - StartOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (StartOpCodeHandle != NULL); - - EndOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (EndOpCodeHandle != NULL); - - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - // - // Create Hii Extend Label OpCode as the start opcode - // - StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - StartLabel->Number = LABEL_SELECT_LANGUAGE; - - // - // Create Hii Extend Label OpCode as the end opcode - // - EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabel->Number = LABEL_END; - - // - // Collect the languages from what our current Language support is based on our VFR - // - HiiHandle = gFrontPagePrivate.HiiHandle; - - GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLang, NULL); - - // - // Get Support language list from variable. - // - if (mLanguageString == NULL){ - GetEfiGlobalVariable2 (L"PlatformLangCodes", (VOID**)&mLanguageString, NULL); - if (mLanguageString == NULL) { - mLanguageString = AllocateCopyPool ( - AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)), - (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes) - ); - ASSERT (mLanguageString != NULL); - } - } - - if (gFrontPagePrivate.LanguageToken == NULL) { - // - // Count the language list number. - // - LangCode = mLanguageString; - Lang = AllocatePool (AsciiStrSize (mLanguageString)); - ASSERT (Lang != NULL); - OptionCount = 0; - while (*LangCode != 0) { - GetNextLanguage (&LangCode, Lang); - OptionCount ++; - } - - // - // Allocate extra 1 as the end tag. - // - gFrontPagePrivate.LanguageToken = AllocateZeroPool ((OptionCount + 1) * sizeof (EFI_STRING_ID)); - ASSERT (gFrontPagePrivate.LanguageToken != NULL); - - Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString); - ASSERT_EFI_ERROR (Status); - - LangCode = mLanguageString; - OptionCount = 0; - while (*LangCode != 0) { - GetNextLanguage (&LangCode, Lang); - - StringSize = 0; - Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); - if (Status == EFI_BUFFER_TOO_SMALL) { - StringBuffer = AllocateZeroPool (StringSize); - ASSERT (StringBuffer != NULL); - Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); - ASSERT_EFI_ERROR (Status); - } - - if (EFI_ERROR (Status)) { - LangSize = AsciiStrSize (Lang); - StringBuffer = AllocatePool (LangSize * sizeof (CHAR16)); - ASSERT (StringBuffer != NULL); - AsciiStrToUnicodeStrS (Lang, StringBuffer, LangSize); - } - - ASSERT (StringBuffer != NULL); - gFrontPagePrivate.LanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL); - FreePool (StringBuffer); - - OptionCount++; - } - } - - ASSERT (gFrontPagePrivate.LanguageToken != NULL); - LangCode = mLanguageString; - OptionCount = 0; - if (Lang == NULL) { - Lang = AllocatePool (AsciiStrSize (mLanguageString)); - ASSERT (Lang != NULL); - } - while (*LangCode != 0) { - GetNextLanguage (&LangCode, Lang); - - if (CurrentLang != NULL && AsciiStrCmp (Lang, CurrentLang) == 0) { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - gFrontPagePrivate.LanguageToken[OptionCount], - EFI_IFR_OPTION_DEFAULT, - EFI_IFR_NUMERIC_SIZE_1, - (UINT8) OptionCount - ); - } else { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - gFrontPagePrivate.LanguageToken[OptionCount], - 0, - EFI_IFR_NUMERIC_SIZE_1, - (UINT8) OptionCount - ); - } - - OptionCount++; - } - - if (CurrentLang != NULL) { - FreePool (CurrentLang); - } - FreePool (Lang); - - HiiCreateOneOfOpCode ( - StartOpCodeHandle, - FRONT_PAGE_KEY_LANGUAGE, - 0, - 0, - STRING_TOKEN (STR_LANGUAGE_SELECT), - STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), - EFI_IFR_FLAG_CALLBACK, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - Status = HiiUpdateForm ( - HiiHandle, - &gFrontPageFormSetGuid, - FRONT_PAGE_FORM_ID, - StartOpCodeHandle, // LABEL_SELECT_LANGUAGE - EndOpCodeHandle // LABEL_END - ); - - HiiFreeOpCodeHandle (StartOpCodeHandle); - HiiFreeOpCodeHandle (EndOpCodeHandle); - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - return Status; -} - -/** - Call the browser and display the front page - - @return Status code that will be returned by - EFI_FORM_BROWSER2_PROTOCOL.SendForm (). - -**/ -EFI_STATUS -CallFrontPage ( - VOID - ) -{ - EFI_STATUS Status; - EFI_BROWSER_ACTION_REQUEST ActionRequest; - - // - // Begin waiting for USER INPUT - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT) - ); - - ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; - Status = gFormBrowser2->SendForm ( - gFormBrowser2, - &gFrontPagePrivate.HiiHandle, - 1, - &gFrontPageFormSetGuid, - 0, - NULL, - &ActionRequest - ); - // - // Check whether user change any option setting which needs a reset to be effective - // - if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { - EnableResetRequired (); - } - - return Status; -} - -/** - 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 returns EFI_SUCCESS always. - -**/ -EFI_STATUS -GetProducerString ( - IN EFI_GUID *ProducerGuid, - IN EFI_STRING_ID Token, - OUT CHAR16 **String - ) -{ - EFI_STRING TmpString; - - TmpString = HiiGetPackageString (ProducerGuid, Token, NULL); - if (TmpString == NULL) { - *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); - } else { - *String = TmpString; - } - - return EFI_SUCCESS; -} - -/** - Convert Processor Frequency Data to a string. - - @param ProcessorFrequency The frequency data to process - @param Base10Exponent The exponent based on 10 - @param String The string that is created - -**/ -VOID -ConvertProcessorToString ( - IN UINT16 ProcessorFrequency, - IN UINT16 Base10Exponent, - OUT CHAR16 **String - ) -{ - CHAR16 *StringBuffer; - UINTN Index; - UINT32 FreqMhz; - - if (Base10Exponent >= 6) { - FreqMhz = ProcessorFrequency; - for (Index = 0; Index < (UINTN) (Base10Exponent - 6); Index++) { - FreqMhz *= 10; - } - } else { - FreqMhz = 0; - } - - StringBuffer = AllocateZeroPool (0x20); - ASSERT (StringBuffer != NULL); - Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3); - StrCatS (StringBuffer, 0x20 / sizeof (CHAR16), L"."); - UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2); - StrCatS (StringBuffer, 0x20 / sizeof (CHAR16), L" GHz"); - *String = (CHAR16 *) StringBuffer; - return ; -} - - -/** - Convert Memory Size to a string. - - @param MemorySize The size of the memory to process - @param String The string that is created - -**/ -VOID -ConvertMemorySizeToString ( - IN UINT32 MemorySize, - OUT CHAR16 **String - ) -{ - CHAR16 *StringBuffer; - - StringBuffer = AllocateZeroPool (0x20); - ASSERT (StringBuffer != NULL); - UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6); - StrCatS (StringBuffer, 0x20 / sizeof (CHAR16), L" MB RAM"); - - *String = (CHAR16 *) StringBuffer; - - return ; -} - -/** - - 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 - // - *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); - } else { - *String = AllocatePool (StrSize * sizeof (CHAR16)); - AsciiStrToUnicodeStrS (OptionalStrStart, *String, StrSize); - } - - return EFI_SUCCESS; -} - - -/** - Update the banner information for the Front Page based on DataHub information. - -**/ -VOID -UpdateFrontPageStrings ( - VOID - ) -{ - UINT8 StrIndex; - CHAR16 *NewString; - BOOLEAN Find[5]; - EFI_STATUS Status; - EFI_STRING_ID TokenToUpdate; - EFI_SMBIOS_HANDLE SmbiosHandle; - EFI_SMBIOS_PROTOCOL *Smbios; - SMBIOS_TABLE_TYPE0 *Type0Record; - SMBIOS_TABLE_TYPE1 *Type1Record; - SMBIOS_TABLE_TYPE4 *Type4Record; - SMBIOS_TABLE_TYPE19 *Type19Record; - EFI_SMBIOS_TABLE_HEADER *Record; - - ZeroMem (Find, sizeof (Find)); - - // - // Update Front Page strings - // - Status = gBS->LocateProtocol ( - &gEfiSmbiosProtocolGuid, - NULL, - (VOID **) &Smbios - ); - if (!EFI_ERROR (Status)) { - SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; - do { - Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); - if (EFI_ERROR(Status)) { - break; - } - - if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) { - Type0Record = (SMBIOS_TABLE_TYPE0 *) Record; - StrIndex = Type0Record->BiosVersion; - GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString); - TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION); - HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); - FreePool (NewString); - Find[0] = TRUE; - } - - if (Record->Type == EFI_SMBIOS_TYPE_SYSTEM_INFORMATION) { - Type1Record = (SMBIOS_TABLE_TYPE1 *) Record; - StrIndex = Type1Record->ProductName; - GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString); - TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL); - HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); - FreePool (NewString); - Find[1] = TRUE; - } - - if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) { - Type4Record = (SMBIOS_TABLE_TYPE4 *) Record; - StrIndex = Type4Record->ProcessorVersion; - GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString); - TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL); - HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); - FreePool (NewString); - Find[2] = TRUE; - } - - if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) { - Type4Record = (SMBIOS_TABLE_TYPE4 *) Record; - ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString); - TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED); - HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); - FreePool (NewString); - Find[3] = TRUE; - } - - if ( Record->Type == EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) { - Type19Record = (SMBIOS_TABLE_TYPE19 *) Record; - ConvertMemorySizeToString ( - (UINT32)(RShiftU64((Type19Record->EndingAddress - Type19Record->StartingAddress + 1), 10)), - &NewString - ); - TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE); - HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); - FreePool (NewString); - Find[4] = TRUE; - } - } while ( !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4])); - } - return ; -} - - -/** - Function waits for a given event to fire, or for an optional timeout to expire. - - @param Event The event to wait for - @param Timeout An optional timeout value in 100 ns units. - - @retval EFI_SUCCESS Event fired before Timeout expired. - @retval EFI_TIME_OUT Timout expired before Event fired.. - -**/ -EFI_STATUS -WaitForSingleEvent ( - IN EFI_EVENT Event, - IN UINT64 Timeout OPTIONAL - ) -{ - UINTN Index; - EFI_STATUS Status; - EFI_EVENT TimerEvent; - EFI_EVENT WaitList[2]; - - if (Timeout != 0) { - // - // Create a timer event - // - Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); - if (!EFI_ERROR (Status)) { - // - // Set the timer event - // - gBS->SetTimer ( - TimerEvent, - TimerRelative, - Timeout - ); - - // - // Wait for the original event or the timer - // - WaitList[0] = Event; - WaitList[1] = TimerEvent; - Status = gBS->WaitForEvent (2, WaitList, &Index); - gBS->CloseEvent (TimerEvent); - - // - // If the timer expired, change the return to timed out - // - if (!EFI_ERROR (Status) && Index == 1) { - Status = EFI_TIMEOUT; - } - } - } else { - // - // No timeout... just wait on the event - // - Status = gBS->WaitForEvent (1, &Event, &Index); - ASSERT (!EFI_ERROR (Status)); - ASSERT (Index == 0); - } - - return Status; -} - -/** - Function show progress bar to wait for user input. - - - @param TimeoutDefault The fault time out value before the system continue to boot. - - @retval EFI_SUCCESS User pressed some key except "Enter" - @retval EFI_TIME_OUT Timeout expired or user press "Enter" - -**/ -EFI_STATUS -ShowProgress ( - 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; - - if (TimeoutDefault != 0) { - DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n")); - - SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); - SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); - SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); - - TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION)); - - if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { - // - // Clear the progress status bar first - // - if (TmpStr != NULL) { - PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0); - } - } - - - TimeoutRemain = TimeoutDefault; - while (TimeoutRemain != 0) { - DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain)); - - Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND); - if (Status != EFI_TIMEOUT) { - break; - } - TimeoutRemain--; - - if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { - // - // Show progress - // - if (TmpStr != NULL) { - PlatformBdsShowProgress ( - Foreground, - Background, - TmpStr, - Color, - ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault), - 0 - ); - } - } - } - - if (TmpStr != NULL) { - gBS->FreePool (TmpStr); - } - - // - // Timeout expired - // - if (TimeoutRemain == 0) { - return EFI_TIMEOUT; - } - } - - // - // User pressed some key - // - if (!PcdGetBool (PcdConInConnectOnDemand)) { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - if (EFI_ERROR (Status)) { - return Status; - } - - if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { - // - // User pressed enter, equivalent to select "continue" - // - return EFI_TIMEOUT; - } - } - - 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 -PlatformBdsEnterFrontPage ( - IN UINT16 TimeoutDefault, - IN BOOLEAN ConnectAllHappened - ) -{ - EFI_STATUS Status; - EFI_STATUS StatusHotkey; - EFI_BOOT_LOGO_PROTOCOL *BootLogo; - EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; - UINTN BootTextColumn; - UINTN BootTextRow; - UINT64 OsIndication; - UINTN DataSize; - EFI_INPUT_KEY Key; - - 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; - } - - - // - // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set - // - OsIndication = 0; - DataSize = sizeof(UINT64); - Status = gRT->GetVariable ( - L"OsIndications", - &gEfiGlobalVariableGuid, - NULL, - &DataSize, - &OsIndication - ); - - // - // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot - // - if (!EFI_ERROR(Status) && ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0)) { - // - // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS - // - OsIndication &= ~((UINT64)EFI_OS_INDICATIONS_BOOT_TO_FW_UI); - Status = gRT->SetVariable ( - L"OsIndications", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - sizeof(UINT64), - &OsIndication - ); - // - // Changing the content without increasing its size with current variable implementation shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - // - // Follow generic rule, Call ReadKeyStroke to connect ConIn before enter UI - // - if (PcdGetBool (PcdConInConnectOnDemand)) { - gST->ConIn->ReadKeyStroke(gST->ConIn, &Key); - } - - // - // Ensure screen is clear when switch Console from Graphics mode to Text mode - // - gST->ConOut->EnableCursor (gST->ConOut, TRUE); - gST->ConOut->ClearScreen (gST->ConOut); - - } else { - - HotkeyBoot (); - if (TimeoutDefault != 0xffff) { - Status = ShowProgress (TimeoutDefault); - StatusHotkey = HotkeyBoot (); - - if (!FeaturePcdGet(PcdBootlogoOnlyEnable) || !EFI_ERROR(Status) || !EFI_ERROR(StatusHotkey)){ - // - // Ensure screen is clear when switch Console from Graphics mode to Text mode - // Skip it in normal boot - // - gST->ConOut->EnableCursor (gST->ConOut, TRUE); - gST->ConOut->ClearScreen (gST->ConOut); - } - - if (EFI_ERROR (Status)) { - // - // Timeout or user press enter to continue - // - goto Exit; - } - } - } - - // - // Boot Logo is corrupted, report it using Boot Logo protocol. - // - Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); - if (!EFI_ERROR (Status) && (BootLogo != NULL)) { - BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0); - } - - // - // Install BM HiiPackages. - // Keep BootMaint HiiPackage, so that it can be covered by global setting. - // - InitBMPackage (); - - Status = EFI_SUCCESS; - do { - // - // Set proper video resolution and text mode for setup - // - BdsSetConsoleMode (TRUE); - - InitializeFrontPage (FALSE); - - // - // Update Front Page strings - // - UpdateFrontPageStrings (); - - gCallbackKey = 0; - CallFrontPage (); - - // - // 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: - // - // Remove the installed BootMaint HiiPackages when exit. - // - FreeBMPackage (); - - // - // User chose to run the Boot Manager - // - CallBootManager (); - - // - // Reinstall BootMaint HiiPackages after exiting from Boot Manager. - // - InitBMPackage (); - 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 ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE)); - - if (mLanguageString != NULL) { - FreePool (mLanguageString); - mLanguageString = NULL; - } - // - //Will leave browser, check any reset required change is applied? if yes, reset system - // - SetupResetReminder (); - - // - // Remove the installed BootMaint HiiPackages when exit. - // - FreeBMPackage (); - -Exit: - // - // Automatically load current entry - // Note: The following lines of code only execute when Auto boot - // takes affect - // - PERF_END (NULL, "BdsTimeOut", "BDS", 0); -} - -/** - This function will change video resolution and text mode - according to defined setup mode or defined boot mode - - @param IsSetupMode Indicate mode is changed to setup mode or boot mode. - - @retval EFI_SUCCESS Mode is changed successfully. - @retval Others Mode failed to be changed. - -**/ -EFI_STATUS -EFIAPI -BdsSetConsoleMode ( - BOOLEAN IsSetupMode - ) -{ - EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; - UINTN SizeOfInfo; - EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; - UINT32 MaxGopMode; - UINT32 MaxTextMode; - UINT32 ModeNumber; - UINT32 NewHorizontalResolution; - UINT32 NewVerticalResolution; - UINT32 NewColumns; - UINT32 NewRows; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - EFI_STATUS Status; - UINTN Index; - UINTN CurrentColumn; - UINTN CurrentRow; - - MaxGopMode = 0; - MaxTextMode = 0; - - // - // Get current video resolution and text mode - // - 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) || (SimpleTextOut == NULL)) { - return EFI_UNSUPPORTED; - } - - if (IsSetupMode) { - // - // The requried resolution and text mode is setup mode. - // - NewHorizontalResolution = mSetupHorizontalResolution; - NewVerticalResolution = mSetupVerticalResolution; - NewColumns = mSetupTextModeColumn; - NewRows = mSetupTextModeRow; - } else { - // - // The required resolution and text mode is boot mode. - // - NewHorizontalResolution = mBootHorizontalResolution; - NewVerticalResolution = mBootVerticalResolution; - NewColumns = mBootTextModeColumn; - NewRows = mBootTextModeRow; - } - - if (GraphicsOutput != NULL) { - MaxGopMode = GraphicsOutput->Mode->MaxMode; - } - - if (SimpleTextOut != NULL) { - MaxTextMode = SimpleTextOut->Mode->MaxMode; - } - - // - // 1. If current video resolution is same with required video resolution, - // video resolution need not be changed. - // 1.1. If current text mode is same with required text mode, text mode need not be changed. - // 1.2. If current text mode is different from required text mode, text mode need be changed. - // 2. If current video resolution is different from required video resolution, we need restart whole console drivers. - // - for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) { - Status = GraphicsOutput->QueryMode ( - GraphicsOutput, - ModeNumber, - &SizeOfInfo, - &Info - ); - if (!EFI_ERROR (Status)) { - if ((Info->HorizontalResolution == NewHorizontalResolution) && - (Info->VerticalResolution == NewVerticalResolution)) { - if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) && - (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) { - // - // Current resolution is same with required resolution, check if text mode need be set - // - Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow); - ASSERT_EFI_ERROR (Status); - if (CurrentColumn == NewColumns && CurrentRow == NewRows) { - // - // If current text mode is same with required text mode. Do nothing - // - FreePool (Info); - return EFI_SUCCESS; - } else { - // - // If current text mode is different from requried text mode. Set new video mode - // - for (Index = 0; Index < MaxTextMode; Index++) { - Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow); - if (!EFI_ERROR(Status)) { - if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) { - // - // Required text mode is supported, set it. - // - Status = SimpleTextOut->SetMode (SimpleTextOut, Index); - ASSERT_EFI_ERROR (Status); - // - // Update text mode PCD. - // - Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn); - ASSERT_EFI_ERROR (Status); - Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow); - ASSERT_EFI_ERROR (Status); - FreePool (Info); - return EFI_SUCCESS; - } - } - } - if (Index == MaxTextMode) { - // - // If requried text mode is not supported, return error. - // - FreePool (Info); - return EFI_UNSUPPORTED; - } - } - } else { - // - // If current video resolution is not same with the new one, set new video resolution. - // In this case, the driver which produces simple text out need be restarted. - // - Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber); - if (!EFI_ERROR (Status)) { - FreePool (Info); - break; - } - } - } - FreePool (Info); - } - } - - if (ModeNumber == MaxGopMode) { - // - // If the resolution is not supported, return error. - // - return EFI_UNSUPPORTED; - } - - // - // Set PCD to Inform GraphicsConsole to change video resolution. - // Set PCD to Inform Consplitter to change text mode. - // - Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution); - ASSERT_EFI_ERROR (Status); - Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution); - ASSERT_EFI_ERROR (Status); - Status = PcdSet32S (PcdConOutColumn, NewColumns); - ASSERT_EFI_ERROR (Status); - Status = PcdSet32S (PcdConOutRow, NewRows); - ASSERT_EFI_ERROR (Status); - - - // - // Video mode is changed, so restart graphics console driver and higher level driver. - // Reconnect graphics console driver and higher level driver. - // Locate all the handles with GOP protocol and reconnect it. - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiSimpleTextOutProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - if (!EFI_ERROR (Status)) { - for (Index = 0; Index < HandleCount; Index++) { - gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); - } - for (Index = 0; Index < HandleCount; Index++) { - gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); - } - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - } - } - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h deleted file mode 100644 index a7b1c5bca0..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h +++ /dev/null @@ -1,254 +0,0 @@ -/** @file - FrontPage routines to handle the callbacks and browser calls - -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. - -**/ - -#ifndef _FRONT_PAGE_H_ -#define _FRONT_PAGE_H_ - -#include "DeviceMngr/DeviceManager.h" -#include "BootMaint/BootMaint.h" -#include "BootMngr/BootManager.h" -#include "String.h" - - -// -// These are the VFR compiler generated data representing our VFR data. -// -extern UINT8 FrontPageVfrBin[]; - -extern EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2; - -extern UINTN gCallbackKey; -extern BOOLEAN gConnectAllHappened; - -// -// 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; - - -#define ONE_SECOND 10000000 - -/// -/// The size of a 3 character ISO639 language code. -/// -#define ISO_639_2_ENTRY_SIZE 3 - -// -// This is the VFR compiler generated header file which defines the -// string identifiers. -// -#define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001 - -// -// These are defined as the same with vfr file -// -#define FRONT_PAGE_FORM_ID 0x1000 - -#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 LABEL_SELECT_LANGUAGE 0x1000 -#define LABEL_END 0xffff - -#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('F', 'P', 'C', 'B') - -typedef struct { - UINTN Signature; - - // - // HII relative handles - // - EFI_HII_HANDLE HiiHandle; - EFI_HANDLE DriverHandle; - EFI_STRING_ID *LanguageToken; - - // - // Produced protocols - // - EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; -} FRONT_PAGE_CALLBACK_DATA; - -#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \ - CR (a, \ - FRONT_PAGE_CALLBACK_DATA, \ - ConfigAccess, \ - FRONT_PAGE_CALLBACK_DATA_SIGNATURE \ - ) - -/** - 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. - -**/ -EFI_STATUS -EFIAPI -FakeExtractConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Request, - OUT EFI_STRING *Progress, - OUT EFI_STRING *Results - ); - -/** - 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 -FakeRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ); - -/** - This function processes the results of changes in configuration. - - - @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action - Specifies the type of action taken by the browser. - @param QuestionId - A unique value which is sent to the original exporting driver - so that it can identify the type of data to expect. - @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 The callback successfully handled the action. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be saved. - @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. - -**/ -EFI_STATUS -EFIAPI -FrontPageCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ); - -/** - Initialize HII information for the FrontPage - - - @param InitializeHiiData TRUE if HII elements need to be initialized. - - @retval EFI_SUCCESS The operation is successful. - @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed. - -**/ -EFI_STATUS -InitializeFrontPage ( - IN BOOLEAN InitializeHiiData - ); - -/** - 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 returns EFI_SUCCESS always. - -**/ -EFI_STATUS -GetProducerString ( - IN EFI_GUID *ProducerGuid, - IN EFI_STRING_ID Token, - OUT CHAR16 **String - ); - -/** - 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 -PlatformBdsEnterFrontPage ( - IN UINT16 TimeoutDefault, - IN BOOLEAN ConnectAllHappened - ); - -/** - This function will change video resolution and text mode - according to defined setup mode or defined boot mode - - @param IsSetupMode Indicate mode is changed to setup mode or boot mode. - - @retval EFI_SUCCESS Mode is changed successfully. - @retval Others Mode failed to be changed. - -**/ -EFI_STATUS -EFIAPI -BdsSetConsoleMode ( - BOOLEAN IsSetupMode - ); - -#endif // _FRONT_PAGE_H_ - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni deleted file mode 100644 index 3c083b4998..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr deleted file mode 100644 index a2d92dff51..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr +++ /dev/null @@ -1,137 +0,0 @@ -///** @file -// -// Browser formset. -// -// Copyright (c) 2007 - 2015, Intel 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 - -#define FRONT_PAGE_CLASS 0x0000 -#define FRONT_PAGE_SUBCLASS 0x0002 - -#define FRONT_PAGE_FORM_ID 0x1000 - -#define FRONT_PAGE_ITEM_ONE 0x0001 -#define FRONT_PAGE_ITEM_TWO 0x0002 -#define FRONT_PAGE_ITEM_THREE 0x0003 -#define FRONT_PAGE_ITEM_FOUR 0x0004 -#define FRONT_PAGE_ITEM_FIVE 0x0005 - -#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 LABEL_SELECT_LANGUAGE 0x1000 -#define LABEL_TIMEOUT 0x2000 -#define LABEL_END 0xffff - -formset - guid = FRONT_PAGE_FORMSET_GUID, - title = STRING_TOKEN(STR_FRONT_PAGE_TITLE), - help = STRING_TOKEN(STR_NULL_STRING), - classguid = FRONT_PAGE_FORMSET_GUID, - - form formid = FRONT_PAGE_FORM_ID, - title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); - - banner - title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL), - line 1, - align left; - - banner - title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL), - line 2, - align left; - - banner - title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED), - line 2, - align right; - - banner - title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION), - line 3, - align left; - - banner - title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE), - line 3, - align right; - -// banner -// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT), -// line 0, -// align left; - -// banner -// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT), -// line 0, -// align right; - -// banner -// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT), -// line 1, -// align left; - -// banner -// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT), -// line 1, -// align right; - -// banner -// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT), -// line 2, -// align left; - -// banner -// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT), -// line 3, -// align left; - - - text - help = STRING_TOKEN(STR_CONTINUE_HELP), - text = STRING_TOKEN(STR_CONTINUE_PROMPT), - flags = INTERACTIVE, - key = FRONT_PAGE_KEY_CONTINUE; - - label LABEL_SELECT_LANGUAGE; - // - // This is where we will dynamically add a OneOf type op-code to select - // Languages from the currently available choices - // - label LABEL_END; - - goto FRONT_PAGE_ITEM_THREE, - prompt = STRING_TOKEN(STR_BOOT_MANAGER), - help = STRING_TOKEN(STR_BOOT_MANAGER_HELP), - flags = INTERACTIVE, - key = FRONT_PAGE_KEY_BOOT_MANAGER; - - goto FRONT_PAGE_ITEM_FOUR, - prompt = STRING_TOKEN(STR_DEVICE_MANAGER), - help = STRING_TOKEN(STR_DEVICE_MANAGER_HELP), - flags = INTERACTIVE, - key = FRONT_PAGE_KEY_DEVICE_MANAGER; - - goto FRONT_PAGE_ITEM_FIVE, - prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER), - help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP), - flags = INTERACTIVE, - key = FRONT_PAGE_KEY_BOOT_MAINTAIN; - - endform; - -endformset; diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c deleted file mode 100644 index e061991ea2..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c +++ /dev/null @@ -1,597 +0,0 @@ -/** @file - Provides a way for 3rd party applications to register themselves for launch by the - Boot Manager based on hot key - -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 -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 "Hotkey.h" - - -LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList); -BDS_COMMON_OPTION *mHotkeyBootOption = NULL; -EFI_EVENT mHotkeyEvent; -VOID *mHotkeyRegistration; - - -/** - Check if the Key Option is valid or not. - - @param KeyOption The Hot Key Option to be checked. - - @retval TRUE The Hot Key Option is valid. - @retval FALSE The Hot Key Option is invalid. - -**/ -BOOLEAN -IsKeyOptionValid ( - IN EFI_KEY_OPTION *KeyOption -) -{ - UINT16 BootOptionName[10]; - UINT8 *BootOptionVar; - UINTN BootOptionSize; - UINT32 Crc; - - // - // Check whether corresponding Boot Option exist - // - UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption); - BootOptionVar = BdsLibGetVariableAndSize ( - BootOptionName, - &gEfiGlobalVariableGuid, - &BootOptionSize - ); - - if (BootOptionVar == NULL || BootOptionSize == 0) { - return FALSE; - } - - // - // Check CRC for Boot Option - // - gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc); - FreePool (BootOptionVar); - - return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE); -} - -/** - Try to boot the boot option triggered by hotkey. - @retval EFI_SUCCESS There is HotkeyBootOption & it is processed - @retval EFI_NOT_FOUND There is no HotkeyBootOption -**/ -EFI_STATUS -HotkeyBoot ( - VOID - ) -{ - EFI_STATUS Status; - UINTN ExitDataSize; - CHAR16 *ExitData; - - if (mHotkeyBootOption == NULL) { - return EFI_NOT_FOUND; - } - - BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath); - - // - // Clear the screen before launch this BootOption - // - gST->ConOut->Reset (gST->ConOut, FALSE); - - Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData); - - if (EFI_ERROR (Status)) { - // - // Call platform action to indicate the boot fail - // - mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); - PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize); - } else { - // - // Call platform action to indicate the boot success - // - mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); - PlatformBdsBootSuccess (mHotkeyBootOption); - } - FreePool (mHotkeyBootOption->Description); - FreePool (mHotkeyBootOption->DevicePath); - FreePool (mHotkeyBootOption->LoadOptions); - FreePool (mHotkeyBootOption); - - mHotkeyBootOption = NULL; - - return EFI_SUCCESS; -} - -/** - - This is the common notification function for HotKeys, it will be registered - with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle. - - @param KeyData A pointer to a buffer that is filled in with the keystroke - information for the key that was pressed. - - @retval EFI_SUCCESS KeyData is successfully processed. - @return EFI_NOT_FOUND Fail to find boot option variable. -**/ -EFI_STATUS -EFIAPI -HotkeyCallback ( - IN EFI_KEY_DATA *KeyData -) -{ - BOOLEAN HotkeyCatched; - LIST_ENTRY BootLists; - LIST_ENTRY *Link; - BDS_HOTKEY_OPTION *Hotkey; - UINT16 Buffer[10]; - EFI_STATUS Status; - EFI_KEY_DATA *HotkeyData; - - if (mHotkeyBootOption != NULL) { - // - // Do not process sequential hotkey stroke until the current boot option returns - // - return EFI_SUCCESS; - } - - Status = EFI_SUCCESS; - - for ( Link = GetFirstNode (&mHotkeyList) - ; !IsNull (&mHotkeyList, Link) - ; Link = GetNextNode (&mHotkeyList, Link) - ) { - HotkeyCatched = FALSE; - Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link); - - // - // Is this Key Stroke we are waiting for? - // - ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0]))); - HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey]; - if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) && - (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) && - (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? - (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE - ) - ) { - // - // For hotkey of key combination, transit to next waiting state - // - Hotkey->WaitingKey++; - - if (Hotkey->WaitingKey == Hotkey->CodeCount) { - // - // Received the whole key stroke sequence - // - HotkeyCatched = TRUE; - } - } else { - // - // Receive an unexpected key stroke, reset to initial waiting state - // - Hotkey->WaitingKey = 0; - } - - if (HotkeyCatched) { - // - // Reset to initial waiting state - // - Hotkey->WaitingKey = 0; - - // - // Launch its BootOption - // - InitializeListHead (&BootLists); - - UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber); - mHotkeyBootOption = BdsLibVariableToOption (&BootLists, Buffer); - } - } - - return Status; -} - -/** - Register the common HotKey notify function to given SimpleTextInEx protocol instance. - - @param SimpleTextInEx Simple Text Input Ex protocol instance - - @retval EFI_SUCCESS Register hotkey notification function successfully. - @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures. - -**/ -EFI_STATUS -HotkeyRegisterNotify ( - IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx -) -{ - UINTN Index; - EFI_STATUS Status; - LIST_ENTRY *Link; - BDS_HOTKEY_OPTION *Hotkey; - - // - // Register notification function for each hotkey - // - Link = GetFirstNode (&mHotkeyList); - - while (!IsNull (&mHotkeyList, Link)) { - Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link); - - Index = 0; - do { - Status = SimpleTextInEx->RegisterKeyNotify ( - SimpleTextInEx, - &Hotkey->KeyData[Index], - HotkeyCallback, - &Hotkey->NotifyHandle - ); - if (EFI_ERROR (Status)) { - // - // some of the hotkey registry failed - // - return Status; - } - Index ++; - } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA)))); - - Link = GetNextNode (&mHotkeyList, Link); - } - - return EFI_SUCCESS; -} - -/** - Callback function for SimpleTextInEx protocol install events - - @param Event the event that is signaled. - @param Context not used here. - -**/ -VOID -EFIAPI -HotkeyEvent ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - UINTN BufferSize; - EFI_HANDLE Handle; - EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx; - - while (TRUE) { - BufferSize = sizeof (EFI_HANDLE); - Status = gBS->LocateHandle ( - ByRegisterNotify, - NULL, - mHotkeyRegistration, - &BufferSize, - &Handle - ); - if (EFI_ERROR (Status)) { - // - // If no more notification events exist - // - return ; - } - - Status = gBS->HandleProtocol ( - Handle, - &gEfiSimpleTextInputExProtocolGuid, - (VOID **) &SimpleTextInEx - ); - ASSERT_EFI_ERROR (Status); - - HotkeyRegisterNotify (SimpleTextInEx); - } -} - -/** - Insert Key Option to hotkey list. - - @param KeyOption The Hot Key Option to be added to hotkey list. - - @retval EFI_SUCCESS Add to hotkey list success. - @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource. -**/ -EFI_STATUS -HotkeyInsertList ( - IN EFI_KEY_OPTION *KeyOption -) -{ - BDS_HOTKEY_OPTION *HotkeyLeft; - BDS_HOTKEY_OPTION *HotkeyRight; - UINTN Index; - EFI_BOOT_KEY_DATA KeyOptions; - UINT32 KeyShiftStateLeft; - UINT32 KeyShiftStateRight; - EFI_INPUT_KEY *InputKey; - EFI_KEY_DATA *KeyData; - - HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION)); - if (HotkeyLeft == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE; - HotkeyLeft->BootOptionNumber = KeyOption->BootOption; - - KeyOptions = KeyOption->KeyData; - - HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount; - - // - // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState - // - KeyShiftStateRight = EFI_SHIFT_STATE_VALID; - if (KeyOptions.Options.ShiftPressed) { - KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED; - } - if (KeyOptions.Options.ControlPressed) { - KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED; - } - if (KeyOptions.Options.AltPressed) { - KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED; - } - if (KeyOptions.Options.LogoPressed) { - KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED; - } - if (KeyOptions.Options.MenuPressed) { - KeyShiftStateRight |= EFI_MENU_KEY_PRESSED; - } - if (KeyOptions.Options.SysReqPressed) { - KeyShiftStateRight |= EFI_SYS_REQ_PRESSED; - } - - KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1); - - InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION)); - - Index = 0; - KeyData = &HotkeyLeft->KeyData[0]; - do { - // - // If Key CodeCount is 0, then only KeyData[0] is used; - // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used - // - KeyData->Key.ScanCode = InputKey[Index].ScanCode; - KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar; - KeyData->KeyState.KeyShiftState = KeyShiftStateLeft; - - Index++; - KeyData++; - } while (Index < HotkeyLeft->CodeCount); - InsertTailList (&mHotkeyList, &HotkeyLeft->Link); - - if (KeyShiftStateLeft != KeyShiftStateRight) { - // - // Need an extra hotkey for shift key on right - // - HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft); - if (HotkeyRight == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Index = 0; - KeyData = &HotkeyRight->KeyData[0]; - do { - // - // Key.ScanCode and Key.UnicodeChar have already been initialized, - // only need to update KeyState.KeyShiftState - // - KeyData->KeyState.KeyShiftState = KeyShiftStateRight; - - Index++; - KeyData++; - } while (Index < HotkeyRight->CodeCount); - InsertTailList (&mHotkeyList, &HotkeyRight->Link); - } - - return EFI_SUCCESS; -} - -/** - Return TRUE when the variable pointed by Name and Guid is a Key#### variable. - - @param Name The name of the variable. - @param Guid The GUID of the variable. - @param OptionNumber Return the option number parsed from the Name. - - @retval TRUE The variable pointed by Name and Guid is a Key#### variable. - @retval FALSE The variable pointed by Name and Guid isn't a Key#### variable. -**/ -BOOLEAN -IsKeyOptionVariable ( - CHAR16 *Name, - EFI_GUID *Guid, - UINT16 *OptionNumber - ) -{ - UINTN Index; - - if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) || - (StrSize (Name) != sizeof (L"Key####")) || - (StrnCmp (Name, L"Key", 3) != 0) - ) { - return FALSE; - } - - *OptionNumber = 0; - for (Index = 3; Index < 7; Index++) { - if ((Name[Index] >= L'0') && (Name[Index] <= L'9')) { - *OptionNumber = *OptionNumber * 16 + Name[Index] - L'0'; - } else if ((Name[Index] >= L'A') && (Name[Index] <= L'F')) { - *OptionNumber = *OptionNumber * 16 + Name[Index] - L'A' + 10; - } else { - return FALSE; - } - } - - return TRUE; -} - -/** - Return an array of key option numbers. - - @param Count Return the count of key option numbers. - - @return UINT16* Pointer to an array of key option numbers; -**/ -UINT16 * -EFIAPI -HotkeyGetOptionNumbers ( - OUT UINTN *Count - ) -{ - EFI_STATUS Status; - UINTN Index; - CHAR16 *Name; - EFI_GUID Guid; - UINTN NameSize; - UINTN NewNameSize; - UINT16 *OptionNumbers; - UINT16 OptionNumber; - - if (Count == NULL) { - return NULL; - } - - *Count = 0; - OptionNumbers = NULL; - - NameSize = sizeof (CHAR16); - Name = AllocateZeroPool (NameSize); - ASSERT (Name != NULL); - while (TRUE) { - NewNameSize = NameSize; - Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid); - if (Status == EFI_BUFFER_TOO_SMALL) { - Name = ReallocatePool (NameSize, NewNameSize, Name); - ASSERT (Name != NULL); - Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid); - NameSize = NewNameSize; - } - - if (Status == EFI_NOT_FOUND) { - break; - } - ASSERT_EFI_ERROR (Status); - - if (IsKeyOptionVariable (Name ,&Guid, &OptionNumber)) { - OptionNumbers = ReallocatePool ( - *Count * sizeof (UINT16), - (*Count + 1) * sizeof (UINT16), - OptionNumbers - ); - ASSERT (OptionNumbers != NULL); - for (Index = 0; Index < *Count; Index++) { - if (OptionNumber < OptionNumbers[Index]) { - break; - } - } - CopyMem (&OptionNumbers[Index + 1], &OptionNumbers[Index], (*Count - Index) * sizeof (UINT16)); - OptionNumbers[Index] = OptionNumber; - (*Count)++; - } - } - - FreePool (Name); - - return OptionNumbers; -} - -/** - - Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options. - - @retval EFI_SUCCESS Hotkey services successfully initialized. -**/ -EFI_STATUS -InitializeHotkeyService ( - VOID - ) -{ - EFI_STATUS Status; - UINT32 BootOptionSupport; - UINT16 *KeyOptionNumbers; - UINTN KeyOptionCount; - UINTN Index; - CHAR16 KeyOptionName[8]; - EFI_KEY_OPTION *KeyOption; - - // - // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP. - // with maximum number of key presses of 3 - // Do not report the hotkey capability if PcdConInConnectOnDemand is enabled. - // - BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP; - if (!PcdGetBool (PcdConInConnectOnDemand)) { - BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY; - SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3); - } - - Status = gRT->SetVariable ( - L"BootOptionSupport", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - sizeof (UINT32), - &BootOptionSupport - ); - // - // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - - KeyOptionNumbers = HotkeyGetOptionNumbers (&KeyOptionCount); - for (Index = 0; Index < KeyOptionCount; Index ++) { - UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumbers[Index]); - GetEfiGlobalVariable2 (KeyOptionName, (VOID **) &KeyOption, NULL); - ASSERT (KeyOption != NULL); - if (IsKeyOptionValid (KeyOption)) { - HotkeyInsertList (KeyOption); - } - FreePool (KeyOption); - } - - if (KeyOptionNumbers != NULL) { - FreePool (KeyOptionNumbers); - } - - // - // Register Protocol notify for Hotkey service - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - HotkeyEvent, - NULL, - &mHotkeyEvent - ); - ASSERT_EFI_ERROR (Status); - - // - // Register for protocol notifications on this event - // - Status = gBS->RegisterProtocolNotify ( - &gEfiSimpleTextInputExProtocolGuid, - mHotkeyEvent, - &mHotkeyRegistration - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h deleted file mode 100644 index 4ee5563a22..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h +++ /dev/null @@ -1,67 +0,0 @@ -/** @file - Provides a way for 3rd party applications to register themselves for launch by the - Boot Manager based on hot key - -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. - -**/ - -#ifndef _HOTKEY_H_ -#define _HOTKEY_H_ - -#include "Bds.h" -#include "String.h" - -#define SET_BOOT_OPTION_SUPPORT_KEY_COUNT(a, c) { \ - (a) = ((a) & ~EFI_BOOT_OPTION_SUPPORT_COUNT) | (((c) << LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT)) & EFI_BOOT_OPTION_SUPPORT_COUNT); \ - } - -#define BDS_HOTKEY_OPTION_SIGNATURE SIGNATURE_32 ('B', 'd', 'K', 'O') - - -typedef struct { - UINTN Signature; - LIST_ENTRY Link; - - VOID *NotifyHandle; - UINT16 BootOptionNumber; - UINT8 CodeCount; - UINT8 WaitingKey; - EFI_KEY_DATA KeyData[3]; -} BDS_HOTKEY_OPTION; - -#define BDS_HOTKEY_OPTION_FROM_LINK(a) CR (a, BDS_HOTKEY_OPTION, Link, BDS_HOTKEY_OPTION_SIGNATURE) - -/** - - Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options. - - - @param VOID - - @retval EFI_SUCCESS Hotkey services successfully initialized. - -**/ -EFI_STATUS -InitializeHotkeyService ( - VOID - ); - -/** - Try to boot the boot option triggered by hotkey. - @retval EFI_SUCCESS There is HotkeyBootOption & it is processed - @retval EFI_NOT_FOUND There is no HotkeyBootOption -**/ -EFI_STATUS -HotkeyBoot ( - VOID - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c b/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c deleted file mode 100644 index ddb2f93980..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c +++ /dev/null @@ -1,48 +0,0 @@ -/** @file - Set the level of support for Hardware Error Record Persistence that is - implemented by the platform. - -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. - -**/ - -#include "HwErrRecSupport.h" - -/** - Set the HwErrRecSupport variable contains a binary UINT16 that supplies the - level of support for Hardware Error Record Persistence that is implemented - by the platform. - -**/ -VOID -InitializeHwErrRecSupport ( - VOID - ) -{ - EFI_STATUS Status; - UINT16 HardwareErrorRecordLevel; - - HardwareErrorRecordLevel = PcdGet16 (PcdHardwareErrorRecordLevel); - - if (HardwareErrorRecordLevel != 0) { - // - // If level value equal 0, no need set to 0 to variable area because UEFI specification - // define same behavior between no value or 0 value for L"HwErrRecSupport". - // - Status = gRT->SetVariable ( - L"HwErrRecSupport", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - sizeof (UINT16), - &HardwareErrorRecordLevel - ); - ASSERT_EFI_ERROR(Status); - } -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h b/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h deleted file mode 100644 index 0cf597acc7..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h +++ /dev/null @@ -1,32 +0,0 @@ -/** @file - Set the level of support for Hardware Error Record Persistence that is - implemented by the platform. - -Copyright (c) 2007 - 2008, Intel 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 _HW_ERR_REC_SUPPORT_H_ -#define _HW_ERR_REC_SUPPORT_H_ - -#include "Bds.h" - -/** - Set the HwErrRecSupport variable contains a binary UINT16 that supplies the - level of support for Hardware Error Record Persistence that is implemented - by the platform. - -**/ -VOID -InitializeHwErrRecSupport ( - VOID - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c deleted file mode 100644 index 39455e44da..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c +++ /dev/null @@ -1,499 +0,0 @@ -/** @file - Language settings - -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 -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 "Language.h" -#include "FrontPage.h" - -EFI_GUID mFontPackageGuid = { - 0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc} -}; - -#define NARROW_GLYPH_NUMBER 8 -#define WIDE_GLYPH_NUMBER 75 - -typedef struct { - /// - /// This 4-bytes total array length is required by HiiAddPackages() - /// - UINT32 Length; - - // - // This is the Font package definition - // - EFI_HII_PACKAGE_HEADER Header; - UINT16 NumberOfNarrowGlyphs; - UINT16 NumberOfWideGlyphs; - EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER]; - EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER]; -} FONT_PACK_BIN; - -FONT_PACK_BIN mFontBin = { - sizeof (FONT_PACK_BIN), - { - sizeof (FONT_PACK_BIN) - sizeof (UINT32), - EFI_HII_PACKAGE_SIMPLE_FONTS, - }, - NARROW_GLYPH_NUMBER, - 0, - { // Narrow Glyphs - { - 0x05d0, - 0x00, - { - 0x00, - 0x00, - 0x00, - 0x4E, - 0x6E, - 0x62, - 0x32, - 0x32, - 0x3C, - 0x68, - 0x4C, - 0x4C, - 0x46, - 0x76, - 0x72, - 0x00, - 0x00, - 0x00, - 0x00 - } - }, - { - 0x05d1, - 0x00, - { - 0x00, - 0x00, - 0x00, - 0x78, - 0x7C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x7E, - 0x7E, - 0x00, - 0x00, - 0x00, - 0x00 - } - }, - { - 0x05d2, - 0x00, - { - 0x00, - 0x00, - 0x00, - 0x78, - 0x7C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x1C, - 0x3E, - 0x66, - 0x66, - 0x00, - 0x00, - 0x00, - 0x00 - } - }, - { - 0x05d3, - 0x00, - { - 0x00, - 0x00, - 0x00, - 0x7E, - 0x7E, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x00, - 0x00, - 0x00, - 0x00 - } - }, - { - 0x05d4, - 0x00, - { - 0x00, - 0x00, - 0x00, - 0x7C, - 0x7E, - 0x06, - 0x06, - 0x06, - 0x06, - 0x66, - 0x66, - 0x66, - 0x66, - 0x66, - 0x66, - 0x00, - 0x00, - 0x00, - 0x00 - } - }, - { - 0x05d5, - 0x00, - { - 0x00, - 0x00, - 0x00, - 0x3C, - 0x3C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x00, - 0x00, - 0x00, - 0x00 - } - }, - { - 0x05d6, - 0x00, - { - 0x00, - 0x00, - 0x00, - 0x38, - 0x38, - 0x1E, - 0x1E, - 0x18, - 0x18, - 0x18, - 0x18, - 0x18, - 0x18, - 0x18, - 0x18, - 0x00, - 0x00, - 0x00, - 0x00 - } - }, - { - 0x0000, - 0x00, - { - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00 - } - } - } -}; - -/** - Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver. - -**/ -VOID -ExportFonts ( - VOID - ) -{ - EFI_HII_HANDLE HiiHandle; - - HiiHandle = HiiAddPackages ( - &mFontPackageGuid, - gImageHandle, - &mFontBin, - NULL - ); - ASSERT (HiiHandle != NULL); -} - -/** - Get next language from language code list (with separator ';'). - - If LangCode is NULL, then ASSERT. - If Lang is NULL, then ASSERT. - - @param LangCode On input: point to first language in the list. On - output: 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; -} - -/** - Check if lang is in supported language codes according to language string. - - This code is used to check if lang is in in supported language codes. It can handle - RFC4646 and ISO639 language tags. - In ISO639 language tags, take 3-characters as a delimitation to find matched string. - In RFC4646 language tags, take semicolon as a delimitation to find matched string. - - For example: - SupportedLang = "engfraengfra" - Iso639Language = TRUE - Lang = "eng", the return value is "TRUE", or - Lang = "chs", the return value is "FALSE". - Another example: - SupportedLang = "en;fr;en-US;fr-FR" - Iso639Language = FALSE - Lang = "en", the return value is "TRUE", or - Lang = "zh", the return value is "FALSE". - - @param SupportedLang Platform supported language codes. - @param Lang Configured language. - @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646. - - @retval TRUE lang is in supported language codes. - @retval FALSE lang is not in supported language codes. - -**/ -BOOLEAN -IsLangInSupportedLangCodes( - IN CHAR8 *SupportedLang, - IN CHAR8 *Lang, - IN BOOLEAN Iso639Language - ) -{ - UINTN Index; - UINTN CompareLength; - UINTN LanguageLength; - - if (Iso639Language) { - CompareLength = ISO_639_2_ENTRY_SIZE; - for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) { - if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) { - // - // Successfully find the Lang string in SupportedLang string. - // - return TRUE; - } - } - return FALSE; - } else { - // - // Compare RFC4646 language code - // - for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++); - - for (; *SupportedLang != '\0'; SupportedLang += CompareLength) { - // - // Skip ';' characters in SupportedLang - // - for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++); - // - // Determine the length of the next language code in SupportedLang - // - for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++); - - if ((CompareLength == LanguageLength) && - (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) { - // - // Successfully find the Lang string in SupportedLang string. - // - return TRUE; - } - } - return FALSE; - } -} - -/** - Initialize Lang or PlatformLang variable, if Lang or PlatformLang variable is not found, - or it has been set to an unsupported value(not one of platform supported language codes), - set the default language code to it. - - @param LangName Language name, L"Lang" or L"PlatformLang". - @param SupportedLang Platform supported language codes. - @param DefaultLang Default language code. - @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646, - TRUE for L"Lang" LangName or FALSE for L"PlatformLang" LangName. - -**/ -VOID -InitializeLangVariable ( - IN CHAR16 *LangName, - IN CHAR8 *SupportedLang, - IN CHAR8 *DefaultLang, - IN BOOLEAN Iso639Language - ) -{ - CHAR8 *Lang; - - // - // Find current Lang or PlatformLang from EFI Variable. - // - GetEfiGlobalVariable2 (LangName, (VOID **) &Lang, NULL); - // - // If Lang or PlatformLang variable is not found, - // or it has been set to an unsupported value(not one of the supported language codes), - // set the default language code to it. - // - if ((Lang == NULL) || !IsLangInSupportedLangCodes (SupportedLang, Lang, Iso639Language)) { - // - // The default language code should be one of the supported language codes. - // - ASSERT (IsLangInSupportedLangCodes (SupportedLang, DefaultLang, Iso639Language)); - BdsDxeSetVariableAndReportStatusCodeOnError ( - LangName, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - AsciiStrSize (DefaultLang), - DefaultLang - ); - } - - if (Lang != NULL) { - FreePool (Lang); - } -} - -/** - Determine the current language that will be used - based on language related EFI Variables. - - @param LangCodesSettingRequired - If required to set LangCodes variable - -**/ -VOID -InitializeLanguage ( - BOOLEAN LangCodesSettingRequired - ) -{ - EFI_STATUS Status; - CHAR8 *LangCodes; - CHAR8 *PlatformLangCodes; - - ExportFonts (); - - LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes); - PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes); - if (LangCodesSettingRequired) { - if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) { - // - // UEFI 2.0 depricated this variable so we support turning it off - // - Status = gRT->SetVariable ( - L"LangCodes", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - AsciiStrSize (LangCodes), - LangCodes - ); - // - // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } - - Status = gRT->SetVariable ( - L"PlatformLangCodes", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - AsciiStrSize (PlatformLangCodes), - PlatformLangCodes - ); - // - // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail. - // - ASSERT_EFI_ERROR (Status); - } - - if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) { - // - // UEFI 2.0 depricated this variable so we support turning it off - // - InitializeLangVariable (L"Lang", LangCodes, (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang), TRUE); - } - InitializeLangVariable (L"PlatformLang", PlatformLangCodes, (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang), FALSE); -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h deleted file mode 100644 index 31c65f1824..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h +++ /dev/null @@ -1,51 +0,0 @@ -/** @file - Language setting - -Copyright (c) 2004 - 2008, Intel 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 _LANGUAGE_H_ -#define _LANGUAGE_H_ - -#include "String.h" - -/** - Get next language from language code list (with separator ';'). - - If LangCode is NULL, then ASSERT. - If Lang is NULL, then ASSERT. - - @param LangCode On input: point to first language in the list. On - output: 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 - ); - -/** - Determine the current language that will be used - based on language related EFI Variables. - - @param LangCodesSettingRequired If required to set LangCode variable - -**/ -VOID -InitializeLanguage ( - BOOLEAN LangCodesSettingRequired - ); - -#endif // _LANGUAGE_H_ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c b/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c deleted file mode 100644 index 700e3e6626..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c +++ /dev/null @@ -1,436 +0,0 @@ -/** @file - Perform the platform memory test - -Copyright (c) 2004 - 2015, Intel 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 "Bds.h" -#include "String.h" - -// -// BDS Platform Functions -// -/** - - Show progress bar with title above it. It only works in Graphics mode. - - - @param TitleForeground Foreground color for Title. - @param TitleBackground Background color for Title. - @param Title Title above progress bar. - @param ProgressColor Progress bar color. - @param Progress Progress (0-100) - @param PreviousValue The previous value of the progress. - - @retval EFI_STATUS Success update the progress bar - -**/ -EFI_STATUS -PlatformBdsShowProgress ( - IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, - IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, - IN CHAR16 *Title, - IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, - IN UINTN Progress, - IN UINTN PreviousValue - ) -{ - EFI_STATUS Status; - EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; - EFI_UGA_DRAW_PROTOCOL *UgaDraw; - UINT32 SizeOfX; - UINT32 SizeOfY; - UINT32 ColorDepth; - UINT32 RefreshRate; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; - UINTN BlockHeight; - UINTN BlockWidth; - UINTN BlockNum; - UINTN PosX; - UINTN PosY; - UINTN Index; - - if (Progress > 100) { - return EFI_INVALID_PARAMETER; - } - - UgaDraw = NULL; - Status = gBS->HandleProtocol ( - gST->ConsoleOutHandle, - &gEfiGraphicsOutputProtocolGuid, - (VOID **) &GraphicsOutput - ); - if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { - GraphicsOutput = NULL; - - Status = gBS->HandleProtocol ( - gST->ConsoleOutHandle, - &gEfiUgaDrawProtocolGuid, - (VOID **) &UgaDraw - ); - } - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - SizeOfX = 0; - SizeOfY = 0; - if (GraphicsOutput != NULL) { - SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; - SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; - } else if (UgaDraw != NULL) { - Status = UgaDraw->GetMode ( - UgaDraw, - &SizeOfX, - &SizeOfY, - &ColorDepth, - &RefreshRate - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - } else { - return EFI_UNSUPPORTED; - } - - BlockWidth = SizeOfX / 100; - BlockHeight = SizeOfY / 50; - - BlockNum = Progress; - - PosX = 0; - PosY = SizeOfY * 48 / 50; - - if (BlockNum == 0) { - // - // Clear progress area - // - SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); - - if (GraphicsOutput != NULL) { - Status = GraphicsOutput->Blt ( - GraphicsOutput, - &Color, - EfiBltVideoFill, - 0, - 0, - 0, - PosY - EFI_GLYPH_HEIGHT - 1, - SizeOfX, - SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), - SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) - ); - } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { - Status = UgaDraw->Blt ( - UgaDraw, - (EFI_UGA_PIXEL *) &Color, - EfiUgaVideoFill, - 0, - 0, - 0, - PosY - EFI_GLYPH_HEIGHT - 1, - SizeOfX, - SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), - SizeOfX * sizeof (EFI_UGA_PIXEL) - ); - } else { - return EFI_UNSUPPORTED; - } - } - // - // Show progress by drawing blocks - // - for (Index = PreviousValue; Index < BlockNum; Index++) { - PosX = Index * BlockWidth; - if (GraphicsOutput != NULL) { - Status = GraphicsOutput->Blt ( - GraphicsOutput, - &ProgressColor, - EfiBltVideoFill, - 0, - 0, - PosX, - PosY, - BlockWidth - 1, - BlockHeight, - (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) - ); - } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { - Status = UgaDraw->Blt ( - UgaDraw, - (EFI_UGA_PIXEL *) &ProgressColor, - EfiUgaVideoFill, - 0, - 0, - PosX, - PosY, - BlockWidth - 1, - BlockHeight, - (BlockWidth) * sizeof (EFI_UGA_PIXEL) - ); - } else { - return EFI_UNSUPPORTED; - } - } - - PrintXY ( - (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2, - PosY - EFI_GLYPH_HEIGHT - 1, - &TitleForeground, - &TitleBackground, - Title - ); - - return EFI_SUCCESS; -} - -/** - Perform the memory test base on the memory test intensive level, - and update the memory resource. - - @param Level The memory test intensive level. - - @retval EFI_STATUS Success test all the system memory and update - the memory resource - -**/ -EFI_STATUS -EFIAPI -BdsMemoryTest ( - IN EXTENDMEM_COVERAGE_LEVEL Level - ) -{ - EFI_STATUS Status; - EFI_STATUS KeyStatus; - EFI_STATUS InitStatus; - EFI_STATUS ReturnStatus; - BOOLEAN RequireSoftECCInit; - EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; - UINT64 TestedMemorySize; - UINT64 TotalMemorySize; - UINTN TestPercent; - UINT64 PreviousValue; - BOOLEAN ErrorOut; - BOOLEAN TestAbort; - EFI_INPUT_KEY Key; - CHAR16 StrPercent[80]; - CHAR16 *StrTotalMemory; - CHAR16 *Pos; - CHAR16 *TmpStr; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; - BOOLEAN IsFirstBoot; - UINT32 TempData; - UINTN StrTotalMemorySize; - - ReturnStatus = EFI_SUCCESS; - ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); - - StrTotalMemorySize = 128; - Pos = AllocateZeroPool (StrTotalMemorySize); - - if (Pos == NULL) { - return ReturnStatus; - } - - StrTotalMemory = Pos; - - TestedMemorySize = 0; - TotalMemorySize = 0; - PreviousValue = 0; - ErrorOut = FALSE; - TestAbort = FALSE; - - SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); - SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); - SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); - - RequireSoftECCInit = FALSE; - - Status = gBS->LocateProtocol ( - &gEfiGenericMemTestProtocolGuid, - NULL, - (VOID **) &GenMemoryTest - ); - if (EFI_ERROR (Status)) { - FreePool (Pos); - return EFI_SUCCESS; - } - - InitStatus = GenMemoryTest->MemoryTestInit ( - GenMemoryTest, - Level, - &RequireSoftECCInit - ); - if (InitStatus == EFI_NO_MEDIA) { - // - // The PEI codes also have the relevant memory test code to check the memory, - // it can select to test some range of the memory or all of them. If PEI code - // checks all the memory, this BDS memory test will has no not-test memory to - // do the test, and then the status of EFI_NO_MEDIA will be returned by - // "MemoryTestInit". So it does not need to test memory again, just return. - // - FreePool (Pos); - return EFI_SUCCESS; - } - - if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { - TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST)); - - if (TmpStr != NULL) { - PrintXY (10, 10, NULL, NULL, TmpStr); - FreePool (TmpStr); - } - } else { - DEBUG ((EFI_D_INFO, "Enter memory test.\n")); - } - do { - Status = GenMemoryTest->PerformMemoryTest ( - GenMemoryTest, - &TestedMemorySize, - &TotalMemorySize, - &ErrorOut, - TestAbort - ); - if (ErrorOut && (Status == EFI_DEVICE_ERROR)) { - TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR)); - if (TmpStr != NULL) { - PrintXY (10, 10, NULL, NULL, TmpStr); - FreePool (TmpStr); - } - - ASSERT (0); - } - - if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { - TempData = (UINT32) DivU64x32 (TotalMemorySize, 16); - TestPercent = (UINTN) DivU64x32 ( - DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16), - TempData - ); - if (TestPercent != PreviousValue) { - UnicodeValueToString (StrPercent, 0, TestPercent, 0); - TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT)); - if (TmpStr != NULL) { - // - // TmpStr size is 64, StrPercent is reserved to 16. - // - StrnCatS ( - StrPercent, - sizeof (StrPercent) / sizeof (CHAR16), - TmpStr, - sizeof (StrPercent) / sizeof (CHAR16) - StrLen (StrPercent) - 1 - ); - PrintXY (10, 10, NULL, NULL, StrPercent); - FreePool (TmpStr); - } - - TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); - if (TmpStr != NULL) { - PlatformBdsShowProgress ( - Foreground, - Background, - TmpStr, - Color, - TestPercent, - (UINTN) PreviousValue - ); - FreePool (TmpStr); - } - } - - PreviousValue = TestPercent; - } else { - DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n")); - } - - if (!PcdGetBool (PcdConInConnectOnDemand)) { - KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) { - if (!RequireSoftECCInit) { - if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { - TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); - if (TmpStr != NULL) { - PlatformBdsShowProgress ( - Foreground, - Background, - TmpStr, - Color, - 100, - (UINTN) PreviousValue - ); - FreePool (TmpStr); - } - - PrintXY (10, 10, NULL, NULL, L"100"); - } - Status = GenMemoryTest->Finished (GenMemoryTest); - goto Done; - } - - TestAbort = TRUE; - } - } - } while (Status != EFI_NOT_FOUND); - - Status = GenMemoryTest->Finished (GenMemoryTest); - -Done: - if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { - UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0); - if (StrTotalMemory[0] == L',') { - StrTotalMemory++; - StrTotalMemorySize -= sizeof (CHAR16); - } - - TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED)); - if (TmpStr != NULL) { - StrnCatS ( - StrTotalMemory, - StrTotalMemorySize / sizeof (CHAR16), - TmpStr, - StrTotalMemorySize / sizeof (CHAR16) - StrLen (StrTotalMemory) - 1 - ); - FreePool (TmpStr); - } - - PrintXY (10, 10, NULL, NULL, StrTotalMemory); - PlatformBdsShowProgress ( - Foreground, - Background, - StrTotalMemory, - Color, - 100, - (UINTN) PreviousValue - ); - - } else { - DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize)); - } - - FreePool (Pos); - - - // - // Use a DynamicHii type pcd to save the boot status, which is used to - // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration. - // - IsFirstBoot = PcdGetBool(PcdBootState); - if (IsFirstBoot) { - Status = PcdSetBoolS(PcdBootState, FALSE); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Set PcdBootState to FALSE failed.\n")); - } - } - - return ReturnStatus; -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/String.c b/IntelFrameworkModulePkg/Universal/BdsDxe/String.c deleted file mode 100644 index d02001b4d1..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/String.c +++ /dev/null @@ -1,59 +0,0 @@ -/** @file - String support - -Copyright (c) 2004 - 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 "Bds.h" -#include "Language.h" -#include "FrontPage.h" - -EFI_HII_HANDLE gStringPackHandle; - -EFI_GUID mBdsStringPackGuid = { - 0x7bac95d3, 0xddf, 0x42f3, {0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a} -}; - -/** - Initialize HII global accessor for string support. - -**/ -VOID -InitializeStringSupport ( - VOID - ) -{ - gStringPackHandle = HiiAddPackages ( - &mBdsStringPackGuid, - gImageHandle, - BdsDxeStrings, - NULL - ); - ASSERT (gStringPackHandle != NULL); -} - -/** - Get string by string id from HII Interface - - - @param Id String ID. - - @retval CHAR16 * String from ID. - @retval NULL If error occurs. - -**/ -CHAR16 * -GetStringById ( - IN EFI_STRING_ID Id - ) -{ - return HiiGetString (gStringPackHandle, Id, NULL); -} diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/String.h b/IntelFrameworkModulePkg/Universal/BdsDxe/String.h deleted file mode 100644 index 005b2bdbd2..0000000000 --- a/IntelFrameworkModulePkg/Universal/BdsDxe/String.h +++ /dev/null @@ -1,65 +0,0 @@ -/** @file - String support - -Copyright (c) 2004 - 2009, Intel 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 "Bds.h" - -extern EFI_HII_HANDLE gStringPackHandle; - -// -// This is the VFR compiler generated header file which defines the -// string identifiers. -// - -extern UINT8 BdsDxeStrings[]; - -/** - Get string by string id from HII Interface - - - @param Id String ID. - - @retval CHAR16 * String from ID. - @retval NULL If error occurs. - -**/ -CHAR16 * -GetStringById ( - IN EFI_STRING_ID Id - ); - -/** - Initialize HII global accessor for string support. - -**/ -VOID -InitializeStringSupport ( - VOID - ); - -/** - Call the browser and display the front page - - @return Status code that will be returned by - EFI_FORM_BROWSER2_PROTOCOL.SendForm (). - -**/ -EFI_STATUS -CallFrontPage ( - VOID - ); - -#endif // _STRING_H_ diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni deleted file mode 100644 index 040ed92c36..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/ComponentName.c b/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/ComponentName.c deleted file mode 100644 index d637decb94..0000000000 --- a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/ComponentName.c +++ /dev/null @@ -1,167 +0,0 @@ -/** @file - UEFI Component Name(2) protocol implementation for VGA Class 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 "VgaClass.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gVgaClassComponentName = { - VgaClassComponentNameGetDriverName, - VgaClassComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gVgaClassComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) VgaClassComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) VgaClassComponentNameGetControllerName, - "en" -}; - - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVgaClassDriverNameTable[] = { - { - "eng;en", - L"VGA Class Driver" - }, - { - NULL, - NULL - } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - @param Language 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 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 -VgaClassComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mVgaClassDriverNameTable, - DriverName, - (BOOLEAN)(This == &gVgaClassComponentName) - ); -} - -/** - 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 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - 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 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 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 -VgaClassComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.c b/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.c deleted file mode 100644 index ca13989d5f..0000000000 --- a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.c +++ /dev/null @@ -1,1288 +0,0 @@ -/** @file - VGA Class Driver that managers VGA devices and produces Simple Text Output Protocol. - -Copyright (c) 2006 - 2009, Intel 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 "VgaClass.h" - -// -// EFI Driver Binding Protocol for the VGA Class Driver -// -EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding = { - VgaClassDriverBindingSupported, - VgaClassDriverBindingStart, - VgaClassDriverBindingStop, - 0xa, - NULL, - NULL -}; - -// -// Local variables -// -CHAR16 CrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; - -// -// This list is used to define the valid extend chars. -// It also provides a mapping from Unicode to PCANSI or -// ASCII. The ASCII mapping we just made up. -// -// -UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { - { - BOXDRAW_HORIZONTAL, - 0xc4, - L'-' - }, - { - BOXDRAW_VERTICAL, - 0xb3, - L'|' - }, - { - BOXDRAW_DOWN_RIGHT, - 0xda, - L'/' - }, - { - BOXDRAW_DOWN_LEFT, - 0xbf, - L'\\' - }, - { - BOXDRAW_UP_RIGHT, - 0xc0, - L'\\' - }, - { - BOXDRAW_UP_LEFT, - 0xd9, - L'/' - }, - { - BOXDRAW_VERTICAL_RIGHT, - 0xc3, - L'|' - }, - { - BOXDRAW_VERTICAL_LEFT, - 0xb4, - L'|' - }, - { - BOXDRAW_DOWN_HORIZONTAL, - 0xc2, - L'+' - }, - { - BOXDRAW_UP_HORIZONTAL, - 0xc1, - L'+' - }, - { - BOXDRAW_VERTICAL_HORIZONTAL, - 0xc5, - L'+' - }, - { - BOXDRAW_DOUBLE_HORIZONTAL, - 0xcd, - L'-' - }, - { - BOXDRAW_DOUBLE_VERTICAL, - 0xba, - L'|' - }, - { - BOXDRAW_DOWN_RIGHT_DOUBLE, - 0xd5, - L'/' - }, - { - BOXDRAW_DOWN_DOUBLE_RIGHT, - 0xd6, - L'/' - }, - { - BOXDRAW_DOUBLE_DOWN_RIGHT, - 0xc9, - L'/' - }, - { - BOXDRAW_DOWN_LEFT_DOUBLE, - 0xb8, - L'\\' - }, - { - BOXDRAW_DOWN_DOUBLE_LEFT, - 0xb7, - L'\\' - }, - { - BOXDRAW_DOUBLE_DOWN_LEFT, - 0xbb, - L'\\' - }, - { - BOXDRAW_UP_RIGHT_DOUBLE, - 0xd4, - L'\\' - }, - { - BOXDRAW_UP_DOUBLE_RIGHT, - 0xd3, - L'\\' - }, - { - BOXDRAW_DOUBLE_UP_RIGHT, - 0xc8, - L'\\' - }, - { - BOXDRAW_UP_LEFT_DOUBLE, - 0xbe, - L'/' - }, - { - BOXDRAW_UP_DOUBLE_LEFT, - 0xbd, - L'/' - }, - { - BOXDRAW_DOUBLE_UP_LEFT, - 0xbc, - L'/' - }, - { - BOXDRAW_VERTICAL_RIGHT_DOUBLE, - 0xc6, - L'|' - }, - { - BOXDRAW_VERTICAL_DOUBLE_RIGHT, - 0xc7, - L'|' - }, - { - BOXDRAW_DOUBLE_VERTICAL_RIGHT, - 0xcc, - L'|' - }, - { - BOXDRAW_VERTICAL_LEFT_DOUBLE, - 0xb5, - L'|' - }, - { - BOXDRAW_VERTICAL_DOUBLE_LEFT, - 0xb6, - L'|' - }, - { - BOXDRAW_DOUBLE_VERTICAL_LEFT, - 0xb9, - L'|' - }, - { - BOXDRAW_DOWN_HORIZONTAL_DOUBLE, - 0xd1, - L'+' - }, - { - BOXDRAW_DOWN_DOUBLE_HORIZONTAL, - 0xd2, - L'+' - }, - { - BOXDRAW_DOUBLE_DOWN_HORIZONTAL, - 0xcb, - L'+' - }, - { - BOXDRAW_UP_HORIZONTAL_DOUBLE, - 0xcf, - L'+' - }, - { - BOXDRAW_UP_DOUBLE_HORIZONTAL, - 0xd0, - L'+' - }, - { - BOXDRAW_DOUBLE_UP_HORIZONTAL, - 0xca, - L'+' - }, - { - BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, - 0xd8, - L'+' - }, - { - BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, - 0xd7, - L'+' - }, - { - BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, - 0xce, - L'+' - }, - - { - BLOCKELEMENT_FULL_BLOCK, - 0xdb, - L'*' - }, - { - BLOCKELEMENT_LIGHT_SHADE, - 0xb0, - L'+' - }, - - { - GEOMETRICSHAPE_UP_TRIANGLE, - 0x1e, - L'^' - }, - { - GEOMETRICSHAPE_RIGHT_TRIANGLE, - 0x10, - L'>' - }, - { - GEOMETRICSHAPE_DOWN_TRIANGLE, - 0x1f, - L'v' - }, - { - GEOMETRICSHAPE_LEFT_TRIANGLE, - 0x11, - L'<' - }, - - { - ARROW_LEFT, - 0x3c, - L'<' - }, - - { - ARROW_UP, - 0x18, - L'^' - }, - - { - ARROW_RIGHT, - 0x3e, - L'>' - }, - - { - ARROW_DOWN, - 0x19, - L'v' - }, - - { - 0x0000, - 0x00, - 0x00 - } -}; - -/** - Entrypoint of this VGA Class Driver. - - This function is the entrypoint of this VGA Class Driver. It installs Driver Binding - Protocols together with Component Name Protocols. - - @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. - -**/ -EFI_STATUS -EFIAPI -InitializeVgaClass( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gVgaClassDriverBinding, - ImageHandle, - &gVgaClassComponentName, - &gVgaClassComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - return EFI_SUCCESS; -} - -/** - Internal worker function to program CRTC register via PCI I/O Protocol. - - @param VgaClassDev device instance object - @param Address Address of register to write - @param Data Data to write to register. - -**/ -VOID -WriteCrtc ( - IN VGA_CLASS_DEV *VgaClassDev, - IN UINT16 Address, - IN UINT8 Data - ) -{ - VgaClassDev->PciIo->Io.Write ( - VgaClassDev->PciIo, - EfiPciIoWidthUint8, - VgaClassDev->VgaMiniPort->CrtcAddressRegisterBar, - VgaClassDev->VgaMiniPort->CrtcAddressRegisterOffset, - 1, - &Address - ); - - VgaClassDev->PciIo->Io.Write ( - VgaClassDev->PciIo, - EfiPciIoWidthUint8, - VgaClassDev->VgaMiniPort->CrtcDataRegisterBar, - VgaClassDev->VgaMiniPort->CrtcDataRegisterOffset, - 1, - &Data - ); -} - -/** - Internal worker function to set cursor's position to VgaClass device - - @param VgaClassDev Private data structure for device instance. - @param Column Colomn of position to set cursor to. - @param Row Row of position to set cursor to. - @param MaxColumn Max value of column. - -**/ -VOID -SetVideoCursorPosition ( - IN VGA_CLASS_DEV *VgaClassDev, - IN UINTN Column, - IN UINTN Row, - IN UINTN MaxColumn - ) -{ - Column = Column & 0xff; - Row = Row & 0xff; - MaxColumn = MaxColumn & 0xff; - - WriteCrtc ( - VgaClassDev, - CRTC_CURSOR_LOCATION_HIGH, - (UINT8) ((Row * MaxColumn + Column) >> 8) - ); - WriteCrtc ( - VgaClassDev, - CRTC_CURSOR_LOCATION_LOW, - (UINT8) ((Row * MaxColumn + Column) & 0xff) - ); -} - -/** - Internal worker function to detect if a Unicode char is for Box Drawing text graphics. - - @param Graphic Unicode char to test. - @param PcAnsi Pointer to PCANSI equivalent of Graphic for output. - If NULL, then PCANSI value is not returned. - @param Ascii Pointer to ASCII equivalent of Graphic for output. - If NULL, then ASCII value is not returned. - - @retval TRUE Gpaphic is a supported Unicode Box Drawing character. - @retval FALSE Gpaphic is not a supported Unicode Box Drawing character. - -**/ -BOOLEAN -LibIsValidTextGraphics ( - IN CHAR16 Graphic, - OUT CHAR8 *PcAnsi, OPTIONAL - OUT CHAR8 *Ascii OPTIONAL - ) -{ - UNICODE_TO_CHAR *Table; - - // - // Unicode drawing code charts are all in the 0x25xx range, arrows are 0x21xx. - // So first filter out values not in these 2 ranges. - // - if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { - return FALSE; - } - - // - // Search UnicodeToPcAnsiOrAscii table for matching entry. - // - for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { - if (Graphic == Table->Unicode) { - if (PcAnsi != NULL) { - *PcAnsi = Table->PcAnsi; - } - - if (Ascii != NULL) { - *Ascii = Table->Ascii; - } - - return TRUE; - } - } - - // - // If value is not found in UnicodeToPcAnsiOrAscii table, then return FALSE. - // - return FALSE; -} - -/** - Internal worker function to check whether input value is an ASCII char. - - @param Char Character to check. - - @retval TRUE Input value is an ASCII char. - @retval FALSE Input value is not an ASCII char. - -**/ -BOOLEAN -IsValidAscii ( - IN CHAR16 Char - ) -{ - if ((Char >= 0x20) && (Char <= 0x7f)) { - return TRUE; - } - - return FALSE; -} - -/** - Internal worker function to check whether input value is a unicode control char. - - @param Char Character to check. - - @retval TRUE Input value is a unicode control char. - @retval FALSE Input value is not a unicode control char. - -**/ -BOOLEAN -IsValidEfiCntlChar ( - IN CHAR16 Char - ) -{ - if (Char == CHAR_NULL || Char == CHAR_BACKSPACE || Char == CHAR_LINEFEED || Char == CHAR_CARRIAGE_RETURN) { - return TRUE; - } - - return FALSE; -} - -/** - Tests to see if this driver supports a given controller. - - This function implments EFI_DRIVER_BINDING_PROTOCOL.Supported(). - It Checks if this driver supports the controller specified. Any Controller - with VgaMiniPort Protocol and Pci I/O protocol can be supported. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @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 EFI_ALREADY_STARTED This driver is already running on this device. - @retval EFI_UNSUPPORTED This driver does not support this device. - -**/ -EFI_STATUS -EFIAPI -VgaClassDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - EFI_STATUS Status; - - // - // Checks if Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiVgaMiniPortProtocolGuid, - NULL, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - NULL, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - return Status; -} - -/** - Starts the device controller. - - This function implments EFI_DRIVER_BINDING_PROTOCOL.Start(). - It starts the device specified by Controller with the driver based on PCI I/O Protocol - and VgaMiniPort Protocol. It creates context for device instance and install EFI_SIMPLE_TEXT_OUT_PROTOCOL. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @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 The device was started. - @retval other Fail to start the device. - -**/ -EFI_STATUS -EFIAPI -VgaClassDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; - EFI_PCI_IO_PROTOCOL *PciIo; - VGA_CLASS_DEV *VgaClassPrivate; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - - Status = gBS->HandleProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Report that VGA Class driver is being enabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE, - DevicePath - ); - - // - // Open the PCI I/O Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Open the VGA Mini Port Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiVgaMiniPortProtocolGuid, - (VOID **) &VgaMiniPort, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Allocate the private device structure - // - VgaClassPrivate = AllocateZeroPool (sizeof (VGA_CLASS_DEV)); - ASSERT (VgaClassPrivate != NULL); - - // - // Initialize the private device structure - // - VgaClassPrivate->Signature = VGA_CLASS_DEV_SIGNATURE; - VgaClassPrivate->Handle = Controller; - VgaClassPrivate->VgaMiniPort = VgaMiniPort; - VgaClassPrivate->PciIo = PciIo; - - VgaClassPrivate->SimpleTextOut.Reset = VgaClassReset; - VgaClassPrivate->SimpleTextOut.OutputString = VgaClassOutputString; - VgaClassPrivate->SimpleTextOut.TestString = VgaClassTestString; - VgaClassPrivate->SimpleTextOut.ClearScreen = VgaClassClearScreen; - VgaClassPrivate->SimpleTextOut.SetAttribute = VgaClassSetAttribute; - VgaClassPrivate->SimpleTextOut.SetCursorPosition = VgaClassSetCursorPosition; - VgaClassPrivate->SimpleTextOut.EnableCursor = VgaClassEnableCursor; - VgaClassPrivate->SimpleTextOut.QueryMode = VgaClassQueryMode; - VgaClassPrivate->SimpleTextOut.SetMode = VgaClassSetMode; - - VgaClassPrivate->SimpleTextOut.Mode = &VgaClassPrivate->SimpleTextOutputMode; - VgaClassPrivate->SimpleTextOutputMode.MaxMode = VgaMiniPort->MaxMode; - VgaClassPrivate->DevicePath = DevicePath; - - // - // Initialize the VGA device. - // - Status = VgaClassPrivate->SimpleTextOut.SetAttribute ( - &VgaClassPrivate->SimpleTextOut, - EFI_TEXT_ATTR (EFI_WHITE, EFI_BLACK) - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - Status = VgaClassPrivate->SimpleTextOut.Reset ( - &VgaClassPrivate->SimpleTextOut, - FALSE - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - Status = VgaClassPrivate->SimpleTextOut.EnableCursor ( - &VgaClassPrivate->SimpleTextOut, - TRUE - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiSimpleTextOutProtocolGuid, - &VgaClassPrivate->SimpleTextOut, - NULL - ); - - return Status; - -ErrorExit: - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, - DevicePath - ); - - return Status; - -} - -/** - Starts the device controller. - - This function implments EFI_DRIVER_BINDING_PROTOCOL.Stop(). - It stops this driver on Controller. Support stoping any child handles - created by this driver. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param ControllerHandle A handle to the device being stopped. - @param NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param ChildHandleBuffer An array of child handles to be freed. - - @retval EFI_SUCCESS This driver is removed ControllerHandle - @retval other This driver was not removed from this device - -**/ -EFI_STATUS -EFIAPI -VgaClassDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; - VGA_CLASS_DEV *VgaClassPrivate; - - Status = gBS->OpenProtocol ( - Controller, - &gEfiSimpleTextOutProtocolGuid, - (VOID **) &SimpleTextOut, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (SimpleTextOut); - - // - // Report that VGA Class driver is being disabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE, - VgaClassPrivate->DevicePath - ); - - Status = gBS->UninstallProtocolInterface ( - Controller, - &gEfiSimpleTextOutProtocolGuid, - &VgaClassPrivate->SimpleTextOut - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Release PCI I/O and VGA Mini Port Protocols on the controller handle. - // - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiVgaMiniPortProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - FreePool (VgaClassPrivate); - - return EFI_SUCCESS; -} - -/** - Resets the text output device hardware. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset(). - It resets the text output device hardware. The cursor position is set to (0, 0), - and the screen is cleared to the default background color for the output device. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param ExtendedVerification Indicates that the driver may perform a more exhaustive - verification 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 -VgaClassReset ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - EFI_STATUS Status; - VGA_CLASS_DEV *VgaClassPrivate; - - VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (This); - - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_RESET, - VgaClassPrivate->DevicePath - ); - - This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); - - Status = This->SetMode (This, 0); - if (EFI_ERROR (Status)) { - return Status; - } - - return This->ClearScreen (This); -} - -/** - Writes a Unicode string to the output device. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString(). - It writes a Unicode string to the output device. This is the most basic output mechanism - on an output device. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param String The Null-terminated Unicode string to be displayed on the output device(s). - - @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 -VgaClassOutputString ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN CHAR16 *String - ) -{ - EFI_STATUS Status; - VGA_CLASS_DEV *VgaClassDev; - EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; - UINTN MaxColumn; - UINTN MaxRow; - UINT32 VideoChar; - CHAR8 GraphicChar; - - VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); - Mode = This->Mode; - - Status = This->QueryMode ( - This, - Mode->Mode, - &MaxColumn, - &MaxRow - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Parse each character of the string to output - // - for (; *String != CHAR_NULL; String++) { - - switch (*String) { - case CHAR_BACKSPACE: - if (Mode->CursorColumn > 0) { - Mode->CursorColumn--; - } - break; - - case CHAR_LINEFEED: - if (Mode->CursorRow == (INT32) (MaxRow - 1)) { - // - // Scroll the screen by copying the contents - // of the VGA display up one line - // - VgaClassDev->PciIo->CopyMem ( - VgaClassDev->PciIo, - EfiPciIoWidthUint32, - VgaClassDev->VgaMiniPort->VgaMemoryBar, - VgaClassDev->VgaMiniPort->VgaMemoryOffset, - VgaClassDev->VgaMiniPort->VgaMemoryBar, - VgaClassDev->VgaMiniPort->VgaMemoryOffset + MaxColumn * 2, - ((MaxRow - 1) * MaxColumn) >> 1 - ); - - // - // Print Blank Line of spaces with the current color attributes - // - VideoChar = (Mode->Attribute << 8) | ' '; - VideoChar = (VideoChar << 16) | VideoChar; - VgaClassDev->PciIo->Mem.Write ( - VgaClassDev->PciIo, - EfiPciIoWidthFillUint32, - VgaClassDev->VgaMiniPort->VgaMemoryBar, - VgaClassDev->VgaMiniPort->VgaMemoryOffset + (MaxRow - 1) * MaxColumn * 2, - MaxColumn >> 1, - &VideoChar - ); - } - - if (Mode->CursorRow < (INT32) (MaxRow - 1)) { - Mode->CursorRow++; - } - break; - - case CHAR_CARRIAGE_RETURN: - Mode->CursorColumn = 0; - break; - - default: - if (!LibIsValidTextGraphics (*String, &GraphicChar, NULL)) { - // - // If this character is not ,Box Drawing text graphics, then convert it to ASCII. - // - GraphicChar = (CHAR8) *String; - if (!IsValidAscii (GraphicChar)) { - // - // If not valid ASCII char, convert it to "?" - // - GraphicChar = '?'; - } - } - - VideoChar = (Mode->Attribute << 8) | GraphicChar; - VgaClassDev->PciIo->Mem.Write ( - VgaClassDev->PciIo, - EfiPciIoWidthUint16, - VgaClassDev->VgaMiniPort->VgaMemoryBar, - VgaClassDev->VgaMiniPort->VgaMemoryOffset + ((Mode->CursorRow * MaxColumn + Mode->CursorColumn) * 2), - 1, - &VideoChar - ); - - if (Mode->CursorColumn >= (INT32) (MaxColumn - 1)) { - This->OutputString (This, CrLfString); - } else { - Mode->CursorColumn++; - } - break; - } - } - - SetVideoCursorPosition ( - VgaClassDev, - (UINTN) Mode->CursorColumn, - (UINTN) Mode->CursorRow, - MaxColumn - ); - - return EFI_SUCCESS; -} - -/** - Verifies that all characters in a Unicode string can be output to the target device. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString(). - It verifies that all characters in a Unicode string can be output to the target device. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param String 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 -VgaClassTestString ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN CHAR16 *String - ) -{ - while (*String != CHAR_NULL) { - if (!(IsValidAscii (*String) || IsValidEfiCntlChar (*String) || LibIsValidTextGraphics (*String, NULL, NULL))) { - return EFI_UNSUPPORTED; - } - - String++; - } - - return EFI_SUCCESS; -} - -/** - Clears the output device(s) display to the currently selected background color. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen(). - The ClearScreen() function clears the output device(s) display to the currently - selected background color. The cursor position is set to (0, 0). - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - - @retval EFI_SUCESS 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 -VgaClassClearScreen ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - ) -{ - EFI_STATUS Status; - VGA_CLASS_DEV *VgaClassDev; - UINTN MaxRow; - UINTN MaxColumn; - UINT32 VideoChar; - - VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); - - Status = This->QueryMode ( - This, - This->Mode->Mode, - &MaxColumn, - &MaxRow - ); - if (EFI_ERROR (Status)) { - return Status; - } - - VideoChar = (This->Mode->Attribute << 8) | ' '; - VideoChar = (VideoChar << 16) | VideoChar; - VgaClassDev->PciIo->Mem.Write ( - VgaClassDev->PciIo, - EfiPciIoWidthFillUint32, - VgaClassDev->VgaMiniPort->VgaMemoryBar, - VgaClassDev->VgaMiniPort->VgaMemoryOffset, - (MaxRow * MaxColumn) >> 1, - &VideoChar - ); - - This->SetCursorPosition (This, 0, 0); - - return EFI_SUCCESS; -} - -/** - Sets the background and foreground colors for theOutputString() and ClearScreen() functions. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). - It sets the background and foreground colors for the OutputString() and ClearScreen() functions. - The color mask can be set even when the device is in an invalid text mode. - Devices supporting a different number of text colors are required to emulate the above colors - to the best of the device's capabilities. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param Attribute The attribute to set. - Bits 0..3 are the foreground color, - and bits 4..6 are the background color. - - @retval EFI_SUCCESS The requested attributes were set. - @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. - -**/ -EFI_STATUS -EFIAPI -VgaClassSetAttribute ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN UINTN Attribute - ) -{ - if (Attribute <= EFI_MAX_ATTRIBUTE) { - This->Mode->Attribute = (INT32) Attribute; - return EFI_SUCCESS; - } - - return EFI_UNSUPPORTED; -} - -/** - Sets the current coordinates of the cursor position. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition(). - It sets the current coordinates of the cursor position. - The upper left corner of the screen is defined as coordinate (0, 0). - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param Column Column of position to set the cursor to. - @param Row Row of position to set the cursor to. - - @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 -VgaClassSetCursorPosition ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN UINTN Column, - IN UINTN Row - ) -{ - EFI_STATUS Status; - VGA_CLASS_DEV *VgaClassDev; - UINTN MaxColumn; - UINTN MaxRow; - - VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); - - Status = This->QueryMode ( - This, - This->Mode->Mode, - &MaxColumn, - &MaxRow - ); - if (EFI_ERROR (Status)) { - return Status; - } - - if (Column >= MaxColumn || Row >= MaxRow) { - return EFI_UNSUPPORTED; - } - - SetVideoCursorPosition (VgaClassDev, Column, Row, MaxColumn); - - This->Mode->CursorColumn = (INT32) Column; - This->Mode->CursorRow = (INT32) Row; - - return EFI_SUCCESS; -} - -/** - Makes the cursor visible or invisible. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.EnableCursor(). - It makes the cursor visible or invisible. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param Visible If TRUE, the cursor is set to be visible. - If FALSE, the cursor is set to be invisible. - - @retval EFI_SUCESS 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 does not support visibility control of the cursor. - -**/ -EFI_STATUS -EFIAPI -VgaClassEnableCursor ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN BOOLEAN Visible - ) -{ - VGA_CLASS_DEV *VgaClassDev; - - VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); - if (Visible) { - if (This->Mode->Mode == 1) { - // - // 80 * 50 - // - WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x06); - WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x07); - } else { - // - // 80 * 25 - // - WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x0e); - WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x0f); - } - } else { - WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x20); - } - - This->Mode->CursorVisible = Visible; - return EFI_SUCCESS; -} - -/** - Returns information for an available text mode that the output device(s) supports. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). - It returns information for an available text mode that the output device(s) supports. - It is required that all output devices support at least 80x25 text mode. This mode is defined to be mode 0. - If the output devices support 80x50, that is defined to be mode 1. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param ModeNumber The mode number to return information on. - @param Columns Columen in current mode number - @param Rows Row in current mode number. - - @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 -VgaClassQueryMode ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN UINTN ModeNumber, - OUT UINTN *Columns, - OUT UINTN *Rows - ) -{ - if ((INT32) ModeNumber >= This->Mode->MaxMode) { - *Columns = 0; - *Rows = 0; - return EFI_UNSUPPORTED; - } - - switch (ModeNumber) { - case 0: - *Columns = 80; - *Rows = 25; - break; - - case 1: - *Columns = 80; - *Rows = 50; - break; - - default: - *Columns = 0; - *Rows = 0; - return EFI_UNSUPPORTED; - } - - return EFI_SUCCESS; -} - -/** - Sets the output device(s) to a specified mode. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). - It sets the output device(s) to the requested mode. - On success the device is in the geometry for the requested mode, - and the device has been cleared to the current background color with the cursor at (0,0). - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param ModeNumber The text mode 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 -VgaClassSetMode ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN UINTN ModeNumber - ) -{ - VGA_CLASS_DEV *VgaClassDev; - - VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This); - - if ((INT32) ModeNumber >= This->Mode->MaxMode) { - return EFI_UNSUPPORTED; - } - - This->ClearScreen (This); - - This->Mode->Mode = (INT32) ModeNumber; - - return VgaClassDev->VgaMiniPort->SetMode (VgaClassDev->VgaMiniPort, ModeNumber); -} diff --git a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.h b/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.h deleted file mode 100644 index 5cfa704001..0000000000 --- a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClass.h +++ /dev/null @@ -1,484 +0,0 @@ -/** @file - Internal include file of the VGA Class 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. - -**/ - - -#ifndef _VGA_CLASS_H__ -#define _VGA_CLASS_H__ - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding; -extern EFI_COMPONENT_NAME_PROTOCOL gVgaClassComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gVgaClassComponentName2; - - -// -// Structure for tuple containing mapping among uniocde, PC Ansi and ASCII code. -// -typedef struct { - CHAR16 Unicode; - CHAR8 PcAnsi; - CHAR8 Ascii; -} UNICODE_TO_CHAR; - -// -// VGA specific registers -// -#define CRTC_CURSOR_START 0xA -#define CRTC_CURSOR_END 0xB - -#define CRTC_CURSOR_LOCATION_HIGH 0xE -#define CRTC_CURSOR_LOCATION_LOW 0xF - -#define EFI_MAX_ATTRIBUTE 0x7f - -// -// VGA Class Device Structure -// -#define VGA_CLASS_DEV_SIGNATURE SIGNATURE_32 ('V', 'G', 'A', 'C') - -typedef struct { - UINTN Signature; - EFI_HANDLE Handle; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOut; - EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode; - EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} VGA_CLASS_DEV; - -#define VGA_CLASS_DEV_FROM_THIS(a) CR (a, VGA_CLASS_DEV, SimpleTextOut, VGA_CLASS_DEV_SIGNATURE) - -// -// Driver Binding Protocol functions -// - -/** - Tests to see if this driver supports a given controller. - - This function implments EFI_DRIVER_BINDING_PROTOCOL.Supported(). - It Checks if this driver supports the controller specified. Any Controller - with VgaMiniPort Protocol and Pci I/O protocol can be supported. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @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 EFI_ALREADY_STARTED This driver is already running on this device. - @retval EFI_UNSUPPORTED This driver does not support this device. - -**/ -EFI_STATUS -EFIAPI -VgaClassDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ); - -/** - Starts the device controller. - - This function implments EFI_DRIVER_BINDING_PROTOCOL.Start(). - It starts the device specified by Controller with the driver based on PCI I/O Protocol - and VgaMiniPort Protocol. It creates context for device instance and install EFI_SIMPLE_TEXT_OUT_PROTOCOL. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @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 The device was started. - @retval other Fail to start the device. - -**/ -EFI_STATUS -EFIAPI -VgaClassDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ); - -/** - Starts the device controller. - - This function implments EFI_DRIVER_BINDING_PROTOCOL.Stop(). - It stops this driver on Controller. Support stoping any child handles - created by this driver. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param ControllerHandle A handle to the device being stopped. - @param NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param ChildHandleBuffer An array of child handles to be freed. - - @retval EFI_SUCCESS This driver is removed ControllerHandle - @retval other This driver was not removed from this device - -**/ -EFI_STATUS -EFIAPI -VgaClassDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer OPTIONAL - ); - -// -// EFI Component Name Functions -// - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - @param Language 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 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 -VgaClassComponentNameGetDriverName ( - 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 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - 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 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 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 -VgaClassComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -// -// Simple Text Output Protocol functions -// -/** - Resets the text output device hardware. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset(). - It resets the text output device hardware. The cursor position is set to (0, 0), - and the screen is cleared to the default background color for the output device. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param ExtendedVerification Indicates that the driver may perform a more exhaustive - verification 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 -VgaClassReset ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Writes a Unicode string to the output device. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString(). - It writes a Unicode string to the output device. This is the most basic output mechanism - on an output device. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param String The Null-terminated Unicode string to be displayed on the output device(s). - - @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 -VgaClassOutputString ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN CHAR16 *String - ); - -/** - Verifies that all characters in a Unicode string can be output to the target device. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString(). - It verifies that all characters in a Unicode string can be output to the target device. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param String 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 -VgaClassTestString ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN CHAR16 *String - ); - -/** - Clears the output device(s) display to the currently selected background color. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen(). - The ClearScreen() function clears the output device(s) display to the currently - selected background color. The cursor position is set to (0, 0). - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - - @retval EFI_SUCESS 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 -VgaClassClearScreen ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - ); - -/** - Sets the background and foreground colors for theOutputString() and ClearScreen() functions. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). - It sets the background and foreground colors for the OutputString() and ClearScreen() functions. - The color mask can be set even when the device is in an invalid text mode. - Devices supporting a different number of text colors are required to emulate the above colors - to the best of the device's capabilities. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param Attribute The attribute to set. - Bits 0..3 are the foreground color, - and bits 4..6 are the background color. - - @retval EFI_SUCCESS The requested attributes were set. - @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. - -**/ -EFI_STATUS -EFIAPI -VgaClassSetAttribute ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN UINTN Attribute - ); - -/** - Sets the current coordinates of the cursor position. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition(). - It sets the current coordinates of the cursor position. - The upper left corner of the screen is defined as coordinate (0, 0). - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param Column Column of position to set the cursor to. - @param Row Row of position to set the cursor to. - - @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 -VgaClassSetCursorPosition ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN UINTN Column, - IN UINTN Row - ); - -/** - Makes the cursor visible or invisible. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.EnableCursor(). - It makes the cursor visible or invisible. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param Visible If TRUE, the cursor is set to be visible. - If FALSE, the cursor is set to be invisible. - - @retval EFI_SUCESS 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 does not support visibility control of the cursor. - -**/ -EFI_STATUS -EFIAPI -VgaClassEnableCursor ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN BOOLEAN Visible - ); - -/** - Returns information for an available text mode that the output device(s) supports. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). - It returns information for an available text mode that the output device(s) supports. - It is required that all output devices support at least 80x25 text mode. This mode is defined to be mode 0. - If the output devices support 80x50, that is defined to be mode 1. - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param ModeNumber The mode number to return information on. - @param Columns Columen in current mode number - @param Rows Row in current mode number. - - @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 -VgaClassQueryMode ( - 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. - - This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). - It sets the output device(s) to the requested mode. - On success the device is in the geometry for the requested mode, - and the device has been cleared to the current background color with the cursor at (0,0). - - @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param ModeNumber The text mode 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 -VgaClassSetMode ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN UINTN ModeNumber - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf b/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf deleted file mode 100644 index 2faba9d6f7..0000000000 --- a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf +++ /dev/null @@ -1,64 +0,0 @@ -## @file -# VGA Class Driver that managers VGA devices and produces Simple Text Output 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 -# 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 = VgaClassDxe - MODULE_UNI_FILE = VgaClassDxe.uni - FILE_GUID = BF89F10D-B205-474f-96E3-7A7BB1B4A407 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializeVgaClass - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# -# DRIVER_BINDING = gVgaClassDriverBinding -# COMPONENT_NAME = gVgaClassComponentName -# COMPONENT_NAME2 = gVgaClassComponentName2 -# - -[Sources] - ComponentName.c - VgaClass.h - VgaClass.c - - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - - -[LibraryClasses] - ReportStatusCodeLib - UefiBootServicesTableLib - MemoryAllocationLib - UefiLib - UefiDriverEntryPoint - DebugLib - - -[Protocols] - gEfiSimpleTextOutProtocolGuid ## BY_START - gEfiVgaMiniPortProtocolGuid ## TO_START - gEfiPciIoProtocolGuid ## TO_START - gEfiDevicePathProtocolGuid ## TO_START - -[UserExtensions.TianoCore."ExtraFiles"] - VgaClassDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.uni b/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.uni deleted file mode 100644 index 23bb5c3693..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxeExtra.uni b/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxeExtra.uni deleted file mode 100644 index 4c0cda97c0..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c b/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c deleted file mode 100644 index e48b6382ff..0000000000 --- a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c +++ /dev/null @@ -1,536 +0,0 @@ -/** @file - Uses the services of the I/O Library to produce the CPU I/O Protocol - -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 "CpuIo.h" - -// -// Handle for the CPU I/O Protocol -// -EFI_HANDLE mHandle = NULL; - -// -// CPU I/O Protocol inatance -// -EFI_CPU_IO_PROTOCOL mCpuIo = { - { - CpuMemoryServiceRead, - CpuMemoryServiceWrite - }, - { - CpuIoServiceRead, - CpuIoServiceWrite - } -}; - -// -// Lookup table for increment values based on transfer widths -// -UINT8 mInStride[] = { - 1, // EfiCpuIoWidthUint8 - 2, // EfiCpuIoWidthUint16 - 4, // EfiCpuIoWidthUint32 - 8, // EfiCpuIoWidthUint64 - 0, // EfiCpuIoWidthFifoUint8 - 0, // EfiCpuIoWidthFifoUint16 - 0, // EfiCpuIoWidthFifoUint32 - 0, // EfiCpuIoWidthFifoUint64 - 1, // EfiCpuIoWidthFillUint8 - 2, // EfiCpuIoWidthFillUint16 - 4, // EfiCpuIoWidthFillUint32 - 8 // EfiCpuIoWidthFillUint64 -}; - -// -// Lookup table for increment values based on transfer widths -// -UINT8 mOutStride[] = { - 1, // EfiCpuIoWidthUint8 - 2, // EfiCpuIoWidthUint16 - 4, // EfiCpuIoWidthUint32 - 8, // EfiCpuIoWidthUint64 - 1, // EfiCpuIoWidthFifoUint8 - 2, // EfiCpuIoWidthFifoUint16 - 4, // EfiCpuIoWidthFifoUint32 - 8, // EfiCpuIoWidthFifoUint64 - 0, // EfiCpuIoWidthFillUint8 - 0, // EfiCpuIoWidthFillUint16 - 0, // EfiCpuIoWidthFillUint32 - 0 // EfiCpuIoWidthFillUint64 -}; - -/** - Check parameters to a CPU I/O Protocol service request. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[in] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The parameters for this request pass the checks. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -CpuIoCheckParameter ( - IN BOOLEAN MmioOperation, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN VOID *Buffer - ) -{ - UINT64 MaxCount; - UINT64 Limit; - - // - // Check to see if Buffer is NULL - // - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check to see if Width is in the valid range - // - if ((UINT32)Width >= EfiCpuIoWidthMaximum) { - return EFI_INVALID_PARAMETER; - } - - // - // For FIFO type, the target address won't increase during the access, - // so treat Count as 1 - // - if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) { - Count = 1; - } - - // - // Check to see if Width is in the valid range for I/O Port operations - // - Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); - if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) { - return EFI_INVALID_PARAMETER; - } - - // - // Check to see if Address is aligned - // - if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) { - return EFI_UNSUPPORTED; - } - - // - // Check to see if any address associated with this transfer exceeds the maximum - // allowed address. The maximum address implied by the parameters passed in is - // Address + Size * Count. If the following condition is met, then the transfer - // is not supported. - // - // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1 - // - // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count - // can also be the maximum integer value supported by the CPU, this range - // check must be adjusted to avoid all overflow conditions. - // - // The following form of the range check is equivalent but assumes that - // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1). - // - Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS); - if (Count == 0) { - if (Address > Limit) { - return EFI_UNSUPPORTED; - } - } else { - MaxCount = RShiftU64 (Limit, Width); - if (MaxCount < (Count - 1)) { - return EFI_UNSUPPORTED; - } - if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { - return EFI_UNSUPPORTED; - } - } - - // - // Check to see if Buffer is aligned - // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.) - // - if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) { - return EFI_UNSUPPORTED; - } - - return EFI_SUCCESS; -} - -/** - Reads memory-mapped registers. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[out] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -EFIAPI -CpuMemoryServiceRead ( - IN EFI_CPU_IO_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - OUT VOID *Buffer - ) -{ - EFI_STATUS Status; - UINT8 InStride; - UINT8 OutStride; - EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; - UINT8 *Uint8Buffer; - - Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Select loop based on the width of the transfer - // - InStride = mInStride[Width]; - OutStride = mOutStride[Width]; - OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); - for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { - if (OperationWidth == EfiCpuIoWidthUint8) { - *Uint8Buffer = MmioRead8 ((UINTN)Address); - } else if (OperationWidth == EfiCpuIoWidthUint16) { - *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); - } else if (OperationWidth == EfiCpuIoWidthUint32) { - *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); - } else if (OperationWidth == EfiCpuIoWidthUint64) { - *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address); - } - } - return EFI_SUCCESS; -} - -/** - Writes memory-mapped registers. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[in] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -EFIAPI -CpuMemoryServiceWrite ( - IN EFI_CPU_IO_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN VOID *Buffer - ) -{ - EFI_STATUS Status; - UINT8 InStride; - UINT8 OutStride; - EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; - UINT8 *Uint8Buffer; - - Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Select loop based on the width of the transfer - // - InStride = mInStride[Width]; - OutStride = mOutStride[Width]; - OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); - for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { - if (OperationWidth == EfiCpuIoWidthUint8) { - MmioWrite8 ((UINTN)Address, *Uint8Buffer); - } else if (OperationWidth == EfiCpuIoWidthUint16) { - MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); - } else if (OperationWidth == EfiCpuIoWidthUint32) { - MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); - } else if (OperationWidth == EfiCpuIoWidthUint64) { - MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); - } - } - return EFI_SUCCESS; -} - -/** - Reads I/O registers. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[out] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -EFIAPI -CpuIoServiceRead ( - IN EFI_CPU_IO_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - OUT VOID *Buffer - ) -{ - EFI_STATUS Status; - UINT8 InStride; - UINT8 OutStride; - EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; - UINT8 *Uint8Buffer; - - Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Select loop based on the width of the transfer - // - InStride = mInStride[Width]; - OutStride = mOutStride[Width]; - OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); - for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { - if (OperationWidth == EfiCpuIoWidthUint8) { - *Uint8Buffer = IoRead8 ((UINTN)Address); - } else if (OperationWidth == EfiCpuIoWidthUint16) { - *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address); - } else if (OperationWidth == EfiCpuIoWidthUint32) { - *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address); - } - } - - return EFI_SUCCESS; -} - -/** - Write I/O registers. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[in] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -EFIAPI -CpuIoServiceWrite ( - IN EFI_CPU_IO_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN VOID *Buffer - ) -{ - EFI_STATUS Status; - UINT8 InStride; - UINT8 OutStride; - EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; - UINT8 *Uint8Buffer; - - // - // Make sure the parameters are valid - // - Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Select loop based on the width of the transfer - // - InStride = mInStride[Width]; - OutStride = mOutStride[Width]; - OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); - for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { - if (OperationWidth == EfiCpuIoWidthUint8) { - IoWrite8 ((UINTN)Address, *Uint8Buffer); - } else if (OperationWidth == EfiCpuIoWidthUint16) { - IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); - } else if (OperationWidth == EfiCpuIoWidthUint32) { - IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); - } - } - - return EFI_SUCCESS; -} - -/** - The user Entry Point for module CpuIo. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -CpuIoInitialize ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIoProtocolGuid); - Status = gBS->InstallMultipleProtocolInterfaces ( - &mHandle, - &gEfiCpuIoProtocolGuid, &mCpuIo, - NULL - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h b/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h deleted file mode 100644 index 6eba9c09e7..0000000000 --- a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.h +++ /dev/null @@ -1,226 +0,0 @@ -/** @file - Internal include file of CPU I/O DXE Driver. - - Copyright (c) 2004 - 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 __CPU_IO_DXE_H__ -#define __CPU_IO_DXE_H__ - - -#include - -#include - -#include -#include -#include -#include - -#define MAX_IO_PORT_ADDRESS 0xFFFF - -/** - Reads memory-mapped registers. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[out] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -EFIAPI -CpuMemoryServiceRead ( - IN EFI_CPU_IO_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - OUT VOID *Buffer - ); - -/** - Writes memory-mapped registers. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[in] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -EFIAPI -CpuMemoryServiceWrite ( - IN EFI_CPU_IO_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN VOID *Buffer - ); - -/** - Reads I/O registers. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[out] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -EFIAPI -CpuIoServiceRead ( - IN EFI_CPU_IO_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - OUT VOID *Buffer - ); - -/** - Write I/O registers. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number of - bytes moved is Width size * Count, starting at Address. - @param[in] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -EFI_STATUS -EFIAPI -CpuIoServiceWrite ( - IN EFI_CPU_IO_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN VOID *Buffer - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf b/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf deleted file mode 100644 index 368fa75bbb..0000000000 --- a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf +++ /dev/null @@ -1,51 +0,0 @@ -## @file -# Module that produces the Framework CPU I/O Protocol using the services of the I/O Library -# -# 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 -# 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 = CpuIoDxe - MODULE_UNI_FILE = CpuIoDxe.uni - FILE_GUID = BAE7599F-3C6B-43b7-BDF0-9CE07AA91AA6 - MODULE_TYPE = DXE_RUNTIME_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = CpuIoInitialize - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 -# - -[Sources] - CpuIo.c - CpuIo.h - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - -[LibraryClasses] - UefiDriverEntryPoint - BaseLib - DebugLib - IoLib - UefiBootServicesTableLib - -[Protocols] - gEfiCpuIoProtocolGuid ## PRODUCES - -[Depex] - TRUE - -[UserExtensions.TianoCore."ExtraFiles"] - CpuIoDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.uni b/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.uni deleted file mode 100644 index 68fa4ec31a..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxeExtra.uni b/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxeExtra.uni deleted file mode 100644 index 6bc7525414..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c b/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c deleted file mode 100644 index 91f7c7ecf9..0000000000 --- a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c +++ /dev/null @@ -1,587 +0,0 @@ -/** @file - This code produces the Data Hub protocol. It preloads the data hub - with status information copied in from PEI HOBs. - -Copyright (c) 2006 - 2015, Intel 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 "DataHub.h" - -// -// Since this driver will only ever produce one instance of the Logging Hub -// protocol you are not required to dynamically allocate the PrivateData. -// -DATA_HUB_INSTANCE mPrivateData; - -/** - Log data record into the data logging hub - - @param This Protocol instance structure - @param DataRecordGuid GUID that defines record contents - @param ProducerName GUID that defines the name of the producer of the data - @param DataRecordClass Class that defines generic record type - @param RawData Data Log record as defined by DataRecordGuid - @param RawDataSize Size of Data Log data in bytes - - @retval EFI_SUCCESS If data was logged - @retval EFI_OUT_OF_RESOURCES If data was not logged due to lack of system - resources. -**/ -EFI_STATUS -EFIAPI -DataHubLogData ( - IN EFI_DATA_HUB_PROTOCOL *This, - IN EFI_GUID *DataRecordGuid, - IN EFI_GUID *ProducerName, - IN UINT64 DataRecordClass, - IN VOID *RawData, - IN UINT32 RawDataSize - ) -{ - EFI_STATUS Status; - DATA_HUB_INSTANCE *Private; - EFI_DATA_ENTRY *LogEntry; - UINT32 TotalSize; - UINT32 RecordSize; - EFI_DATA_RECORD_HEADER *Record; - VOID *Raw; - DATA_HUB_FILTER_DRIVER *FilterEntry; - LIST_ENTRY *Link; - LIST_ENTRY *Head; - EFI_TIME LogTime; - - Private = DATA_HUB_INSTANCE_FROM_THIS (This); - - // - // Combine the storage for the internal structs and a copy of the log record. - // Record follows PrivateLogEntry. The consumer will be returned a pointer - // to Record so we don't what it to be the thing that was allocated from - // pool, so the consumer can't free an data record by mistake. - // - RecordSize = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize; - TotalSize = sizeof (EFI_DATA_ENTRY) + RecordSize; - - // - // First try to get log time at TPL level <= TPL_CALLBACK. - // - ZeroMem (&LogTime, sizeof (LogTime)); - if (EfiGetCurrentTpl() <= TPL_CALLBACK) { - gRT->GetTime (&LogTime, NULL); - } - - // - // The Logging action is the critical section, so it is locked. - // The MTC asignment & update and logging must be an - // atomic operation, so use the lock. - // - Status = EfiAcquireLockOrFail (&Private->DataLock); - if (EFI_ERROR (Status)) { - // - // Reentrancy detected so exit! - // - return Status; - } - - LogEntry = AllocatePool (TotalSize); - - if (LogEntry == NULL) { - EfiReleaseLock (&Private->DataLock); - return EFI_OUT_OF_RESOURCES; - } - - ZeroMem (LogEntry, TotalSize); - - Record = (EFI_DATA_RECORD_HEADER *) (LogEntry + 1); - Raw = (VOID *) (Record + 1); - - // - // Build Standard Log Header - // - Record->Version = EFI_DATA_RECORD_HEADER_VERSION; - Record->HeaderSize = (UINT16) sizeof (EFI_DATA_RECORD_HEADER); - Record->RecordSize = RecordSize; - CopyMem (&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID)); - CopyMem (&Record->ProducerName, ProducerName, sizeof (EFI_GUID)); - Record->DataRecordClass = DataRecordClass; - - // - // Ensure LogMonotonicCount is not zero - // - Record->LogMonotonicCount = ++Private->GlobalMonotonicCount; - - CopyMem (&Record->LogTime, &LogTime, sizeof (LogTime)); - - // - // Insert log into the internal linked list. - // - LogEntry->Signature = EFI_DATA_ENTRY_SIGNATURE; - LogEntry->Record = Record; - LogEntry->RecordSize = sizeof (EFI_DATA_ENTRY) + RawDataSize; - InsertTailList (&Private->DataListHead, &LogEntry->Link); - - CopyMem (Raw, RawData, RawDataSize); - - EfiReleaseLock (&Private->DataLock); - - // - // Send Signal to all the filter drivers which are interested - // in the record's class and guid. - // - Head = &Private->FilterDriverListHead; - for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) { - FilterEntry = FILTER_ENTRY_FROM_LINK (Link); - if (((FilterEntry->ClassFilter & DataRecordClass) != 0) && - (CompareGuid (&FilterEntry->FilterDataRecordGuid, &gZeroGuid) || - CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid))) { - gBS->SignalEvent (FilterEntry->Event); - } - } - - return EFI_SUCCESS; -} - -/** - Search the Head doubly linked list for the passed in MTC. Return the - matching element in Head and the MTC on the next entry. - - @param Head Head of Data Log linked list. - @param ClassFilter Only match the MTC if it is in the same Class as the - ClassFilter. - @param PtrCurrentMTC On IN contians MTC to search for. On OUT contians next - MTC in the data log list or zero if at end of the list. - - @retval EFI_DATA_LOG_ENTRY Return pointer to data log data from Head list. - @retval NULL If no data record exists. - -**/ -EFI_DATA_RECORD_HEADER * -GetNextDataRecord ( - IN LIST_ENTRY *Head, - IN UINT64 ClassFilter, - IN OUT UINT64 *PtrCurrentMTC - ) - -{ - EFI_DATA_ENTRY *LogEntry; - LIST_ENTRY *Link; - BOOLEAN ReturnFirstEntry; - EFI_DATA_RECORD_HEADER *Record; - EFI_DATA_ENTRY *NextLogEntry; - - // - // If MonotonicCount == 0 just return the first one - // - ReturnFirstEntry = (BOOLEAN) (*PtrCurrentMTC == 0); - - Record = NULL; - for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) { - LogEntry = DATA_ENTRY_FROM_LINK (Link); - if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) { - // - // Skip any entry that does not have the correct ClassFilter - // - continue; - } - - if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) { - // - // Return record to the user - // - Record = LogEntry->Record; - - // - // Calculate the next MTC value. If there is no next entry set - // MTC to zero. - // - *PtrCurrentMTC = 0; - for (Link = GetNextNode(Head, Link); Link != Head; Link = GetNextNode(Head, Link)) { - NextLogEntry = DATA_ENTRY_FROM_LINK (Link); - if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) { - // - // Return the MTC of the next thing to search for if found - // - *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount; - break; - } - } - // - // Record found exit loop and return - // - break; - } - } - - return Record; -} - -/** - Search the Head list for a EFI_DATA_HUB_FILTER_DRIVER member that - represents Event and return it. - - @param Head Pointer to head of dual linked list of EFI_DATA_HUB_FILTER_DRIVER structures. - @param Event Event to be search for in the Head list. - - @retval EFI_DATA_HUB_FILTER_DRIVER Returned if Event stored in the Head doubly linked list. - @retval NULL If Event is not in the list - -**/ -DATA_HUB_FILTER_DRIVER * -FindFilterDriverByEvent ( - IN LIST_ENTRY *Head, - IN EFI_EVENT Event - ) -{ - DATA_HUB_FILTER_DRIVER *FilterEntry; - LIST_ENTRY *Link; - - for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) { - FilterEntry = FILTER_ENTRY_FROM_LINK (Link); - if (FilterEntry->Event == Event) { - return FilterEntry; - } - } - - return NULL; -} - -/** - - Get a previously logged data record and the MonotonicCount for the next - availible Record. This allows all records or all records later - than a give MonotonicCount to be returned. If an optional FilterDriverEvent - is passed in with a MonotonicCout of zero return the first record - not yet read by the filter driver. If FilterDriverEvent is NULL and - MonotonicCount is zero return the first data record. - - @param This Pointer to the EFI_DATA_HUB_PROTOCOL instance. - @param MonotonicCount Specifies the Record to return. On input, zero means - return the first record. On output, contains the next - record to availible. Zero indicates no more records. - @param FilterDriverEvent If FilterDriverEvent is not passed in a MonotonicCount - of zero, it means to return the first data record. - If FilterDriverEvent is passed in, then a MonotonicCount - of zero means to return the first data not yet read by - FilterDriverEvent. - @param Record Returns a dynamically allocated memory buffer with a data - record that matches MonotonicCount. - - @retval EFI_SUCCESS Data was returned in Record. - @retval EFI_INVALID_PARAMETER FilterDriverEvent was passed in but does not exist. - @retval EFI_NOT_FOUND MonotonicCount does not match any data record in the - system. If a MonotonicCount of zero was passed in, then - no data records exist in the system. - @retval EFI_OUT_OF_RESOURCES Record was not returned due to lack of system resources. - -**/ -EFI_STATUS -EFIAPI -DataHubGetNextRecord ( - IN EFI_DATA_HUB_PROTOCOL *This, - IN OUT UINT64 *MonotonicCount, - IN EFI_EVENT *FilterDriverEvent, OPTIONAL - OUT EFI_DATA_RECORD_HEADER **Record - ) -{ - DATA_HUB_INSTANCE *Private; - DATA_HUB_FILTER_DRIVER *FilterDriver; - UINT64 ClassFilter; - - Private = DATA_HUB_INSTANCE_FROM_THIS (This); - - FilterDriver = NULL; - ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG | - EFI_DATA_RECORD_CLASS_ERROR | - EFI_DATA_RECORD_CLASS_DATA | - EFI_DATA_RECORD_CLASS_PROGRESS_CODE; - - // - // If FilterDriverEvent is NULL, then return the next record - // - if (FilterDriverEvent == NULL) { - *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); - if (*Record == NULL) { - return EFI_NOT_FOUND; - } - return EFI_SUCCESS; - } - - // - // For events the beginning is the last unread record. This info is - // stored in the instance structure, so we must look up the event - // to get the data. - // - FilterDriver = FindFilterDriverByEvent ( - &Private->FilterDriverListHead, - *FilterDriverEvent - ); - if (FilterDriver == NULL) { - return EFI_INVALID_PARAMETER; - } - // - // Use the Class filter the event was created with. - // - ClassFilter = FilterDriver->ClassFilter; - - // - // Retrieve the next record or the first record. - // - if (*MonotonicCount != 0 || FilterDriver->GetNextMonotonicCount == 0) { - *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); - if (*Record == NULL) { - return EFI_NOT_FOUND; - } - - if (*MonotonicCount != 0) { - // - // If this was not the last record then update the count associated with the filter - // - FilterDriver->GetNextMonotonicCount = *MonotonicCount; - } else { - // - // Save the MonotonicCount of the last record which has been read - // - FilterDriver->GetNextMonotonicCount = (*Record)->LogMonotonicCount; - } - return EFI_SUCCESS; - } - - // - // This is a request to read the first record that has not been read yet. - // Set MonotoicCount to the last record successfuly read - // - *MonotonicCount = FilterDriver->GetNextMonotonicCount; - - // - // Retrieve the last record successfuly read again, but do not return it since - // it has already been returned before. - // - *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); - if (*Record == NULL) { - return EFI_NOT_FOUND; - } - - if (*MonotonicCount != 0) { - // - // Update the count associated with the filter - // - FilterDriver->GetNextMonotonicCount = *MonotonicCount; - - // - // Retrieve the record after the last record successfuly read - // - *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); - if (*Record == NULL) { - return EFI_NOT_FOUND; - } - } - - return EFI_SUCCESS; -} - -/** - This function registers the data hub filter driver that is represented - by FilterEvent. Only one instance of each FilterEvent can be registered. - After the FilterEvent is registered, it will be signaled so it can sync - with data records that have been recorded prior to the FilterEvent being - registered. - - @param This Pointer to The EFI_DATA_HUB_PROTOCOL instance. - @param FilterEvent The EFI_EVENT to signal whenever data that matches - FilterClass is logged in the system. - @param FilterTpl The maximum EFI_TPL at which FilterEvent can be - signaled. It is strongly recommended that you use the - lowest EFI_TPL possible. - @param FilterClass FilterEvent will be signaled whenever a bit in - EFI_DATA_RECORD_HEADER.DataRecordClass is also set in - FilterClass. If FilterClass is zero, no class-based - filtering will be performed. - @param FilterDataRecordGuid FilterEvent will be signaled whenever FilterDataRecordGuid - matches EFI_DATA_RECORD_HEADER.DataRecordGuid. If - FilterDataRecordGuid is NULL, then no GUID-based filtering - will be performed. - - @retval EFI_SUCCESS The filter driver event was registered. - @retval EFI_ALREADY_STARTED FilterEvent was previously registered and cannot be - registered again. - @retval EFI_OUT_OF_RESOURCES The filter driver event was not registered due to lack of - system resources. - -**/ -EFI_STATUS -EFIAPI -DataHubRegisterFilterDriver ( - IN EFI_DATA_HUB_PROTOCOL * This, - IN EFI_EVENT FilterEvent, - IN EFI_TPL FilterTpl, - IN UINT64 FilterClass, - IN EFI_GUID * FilterDataRecordGuid OPTIONAL - ) - -{ - DATA_HUB_INSTANCE *Private; - DATA_HUB_FILTER_DRIVER *FilterDriver; - - Private = DATA_HUB_INSTANCE_FROM_THIS (This); - - FilterDriver = (DATA_HUB_FILTER_DRIVER *) AllocateZeroPool (sizeof (DATA_HUB_FILTER_DRIVER)); - if (FilterDriver == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // Initialize filter driver info - // - FilterDriver->Signature = EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE; - FilterDriver->Event = FilterEvent; - FilterDriver->Tpl = FilterTpl; - FilterDriver->GetNextMonotonicCount = 0; - if (FilterClass == 0) { - FilterDriver->ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG | - EFI_DATA_RECORD_CLASS_ERROR | - EFI_DATA_RECORD_CLASS_DATA | - EFI_DATA_RECORD_CLASS_PROGRESS_CODE; - } else { - FilterDriver->ClassFilter = FilterClass; - } - - if (FilterDataRecordGuid != NULL) { - CopyMem (&FilterDriver->FilterDataRecordGuid, FilterDataRecordGuid, sizeof (EFI_GUID)); - } - // - // Search for duplicate entries - // - if (FindFilterDriverByEvent (&Private->FilterDriverListHead, FilterEvent) != NULL) { - FreePool (FilterDriver); - return EFI_ALREADY_STARTED; - } - // - // Make insertion an atomic operation with the lock. - // - EfiAcquireLock (&Private->DataLock); - InsertTailList (&Private->FilterDriverListHead, &FilterDriver->Link); - EfiReleaseLock (&Private->DataLock); - - // - // Signal the Filter driver we just loaded so they will recieve all the - // previous history. If we did not signal here we would have to wait until - // the next data was logged to get the history. In a case where no next - // data was logged we would never get synced up. - // - gBS->SignalEvent (FilterEvent); - - return EFI_SUCCESS; -} - -/** - Remove a Filter Driver, so it no longer gets called when data - information is logged. - - @param This Protocol instance structure - - @param FilterEvent Event that represents a filter driver that is to be - Unregistered. - - @retval EFI_SUCCESS If FilterEvent was unregistered - @retval EFI_NOT_FOUND If FilterEvent does not exist -**/ -EFI_STATUS -EFIAPI -DataHubUnregisterFilterDriver ( - IN EFI_DATA_HUB_PROTOCOL *This, - IN EFI_EVENT FilterEvent - ) -{ - DATA_HUB_INSTANCE *Private; - DATA_HUB_FILTER_DRIVER *FilterDriver; - - Private = DATA_HUB_INSTANCE_FROM_THIS (This); - - // - // Search for duplicate entries - // - FilterDriver = FindFilterDriverByEvent ( - &Private->FilterDriverListHead, - FilterEvent - ); - if (FilterDriver == NULL) { - return EFI_NOT_FOUND; - } - // - // Make removal an atomic operation with the lock - // - EfiAcquireLock (&Private->DataLock); - RemoveEntryList (&FilterDriver->Link); - EfiReleaseLock (&Private->DataLock); - - return EFI_SUCCESS; -} - - - -/** - Driver's Entry point routine that install Driver to produce Data Hub protocol. - - @param ImageHandle Module's image handle - @param SystemTable Pointer of EFI_SYSTEM_TABLE - - @retval EFI_SUCCESS Logging Hub protocol installed - @retval Other No protocol installed, unload driver. - -**/ -EFI_STATUS -EFIAPI -DataHubInstall ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - UINT32 HighMontonicCount; - - mPrivateData.Signature = DATA_HUB_INSTANCE_SIGNATURE; - mPrivateData.DataHub.LogData = DataHubLogData; - mPrivateData.DataHub.GetNextRecord = DataHubGetNextRecord; - mPrivateData.DataHub.RegisterFilterDriver = DataHubRegisterFilterDriver; - mPrivateData.DataHub.UnregisterFilterDriver = DataHubUnregisterFilterDriver; - - // - // Initialize Private Data in CORE_LOGGING_HUB_INSTANCE that is - // required by this protocol - // - InitializeListHead (&mPrivateData.DataListHead); - InitializeListHead (&mPrivateData.FilterDriverListHead); - - EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY); - - // - // Make sure we get a bigger MTC number on every boot! - // - Status = gRT->GetNextHighMonotonicCount (&HighMontonicCount); - if (EFI_ERROR (Status)) { - // - // if system service fails pick a sane value. - // - mPrivateData.GlobalMonotonicCount = 0; - } else { - mPrivateData.GlobalMonotonicCount = LShiftU64 ((UINT64) HighMontonicCount, 32); - } - // - // Make a new handle and install the protocol - // - mPrivateData.Handle = NULL; - Status = gBS->InstallProtocolInterface ( - &mPrivateData.Handle, - &gEfiDataHubProtocolGuid, - EFI_NATIVE_INTERFACE, - &mPrivateData.DataHub - ); - return Status; -} - diff --git a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.h b/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.h deleted file mode 100644 index de2e3f34ff..0000000000 --- a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.h +++ /dev/null @@ -1,131 +0,0 @@ -/** @file - This code supports a the private implementation - of the Data Hub protocol - -Copyright (c) 2006 - 2015, Intel 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 _DATA_HUB_H_ -#define _DATA_HUB_H_ - - -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DATA_HUB_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', 'u', 'b') -typedef struct { - UINT32 Signature; - - EFI_HANDLE Handle; - - // - // Produced protocol(s) - // - EFI_DATA_HUB_PROTOCOL DataHub; - - // - // Private Data - // - // - // Updates to GlobalMonotonicCount, LogListHead, and FilterDriverListHead - // must be locked. - // - EFI_LOCK DataLock; - - // - // Runing Monotonic Count to use for each error record. - // Increment AFTER use in an error record. - // - UINT64 GlobalMonotonicCount; - - // - // List of EFI_DATA_ENTRY structures. This is the data log! The list - // must be in assending order of LogMonotonicCount. - // - LIST_ENTRY DataListHead; - - // - // List of EFI_DATA_HUB_FILTER_DRIVER structures. Represents all - // the registered filter drivers. - // - LIST_ENTRY FilterDriverListHead; - -} DATA_HUB_INSTANCE; - -#define DATA_HUB_INSTANCE_FROM_THIS(this) CR (this, DATA_HUB_INSTANCE, DataHub, DATA_HUB_INSTANCE_SIGNATURE) - -// -// Private data structure to contain the data log. One record per -// structure. Head pointer to the list is the Log member of -// EFI_DATA_ENTRY. Record is a copy of the data passed in. -// -#define EFI_DATA_ENTRY_SIGNATURE SIGNATURE_32 ('D', 'r', 'e', 'c') -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - - EFI_DATA_RECORD_HEADER *Record; - - UINTN RecordSize; - -} EFI_DATA_ENTRY; - -#define DATA_ENTRY_FROM_LINK(link) CR (link, EFI_DATA_ENTRY, Link, EFI_DATA_ENTRY_SIGNATURE) - -// -// Private data to contain the filter driver Event and it's -// associated EFI_TPL. -// -#define EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE SIGNATURE_32 ('D', 'h', 'F', 'd') - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - - // - // Store Filter Driver Event and Tpl level it can be Signaled at. - // - EFI_EVENT Event; - EFI_TPL Tpl; - - // - // Monotonic count on the get next operation for Event. - // Zero indicates get next has not been called for this event yet. - // - UINT64 GetNextMonotonicCount; - - // - // Filter driver will register what class filter should be used. - // - UINT64 ClassFilter; - - // - // Filter driver will register what record guid filter should be used. - // - EFI_GUID FilterDataRecordGuid; - -} DATA_HUB_FILTER_DRIVER; - -#define FILTER_ENTRY_FROM_LINK(link) CR (link, DATA_HUB_FILTER_DRIVER, Link, EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE) - -#endif diff --git a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf b/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf deleted file mode 100644 index 834c3b3148..0000000000 --- a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf +++ /dev/null @@ -1,85 +0,0 @@ -## @file -# This driver initializes and installs the Data Hub protocol. -# -# The data hub is a volatile database that is intended as the major focus for the accumulation of -# manageability data.T he hub is fed by "producers" with chunks of data in a defined format. -# Consumers may then extract the data in temporal "log" order.As an example, progress codes might -# be recorded in the data hub for future processing.Ot her data contributed to the data hub might -# include, for example, statistics on enumerated items such as memory, add-in buses, and add-in -# cards and data on errors encountered during boot (for example, the system did not boot off the -# network because the cable was not plugged in). -# Some classes of data have defined formats.For example, the amount of memory in the system is -# reported in a standard format so that consumers can be written to extract the data.O ther data is -# system specific.For example, additional detail on errors might be specific to the driver that -# discovered the error.The consumer might be a driver that tabularizes data from the data hub, -# providing a mechanism for the raw data to be made available to the OS for post-processing by -# OS-based applications. -# The intent of the data hub is for drivers that enumerate and configure parts of the system to report -# their discoveries to the data hub.This data can then be extracted by other drivers that report those -# discoveries using standard manageability interfaces such as SMBIOS and Intelligent Platform -# Management Interface (IPMI).The alternative to a data-hub-like architecture is to require all -# drivers to be aware of all reporting formats. -# For more information, please ref http://www.intel.com/technology/framework/ -# -# Copyright (c) 2006 - 2015, Intel 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 = DataHubDxe - MODULE_UNI_FILE = DataHubDxe.uni - FILE_GUID = 53BCC14F-C24F-434C-B294-8ED2D4CC1860 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = DataHubInstall - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - DataHub.h - DataHub.c - - -[Packages] - IntelFrameworkPkg/IntelFrameworkPkg.dec - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - - -[LibraryClasses] - UefiRuntimeServicesTableLib - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - BaseLib - UefiLib - UefiDriverEntryPoint - DebugLib - - -[Guids] - gZeroGuid ## SOMETIMES_CONSUMES ## GUID - - -[Protocols] - gEfiDataHubProtocolGuid ## PRODUCES - - -[Depex] - TRUE - -[UserExtensions.TianoCore."ExtraFiles"] - DataHubDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.uni b/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.uni deleted file mode 100644 index 2e62686103..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxeExtra.uni b/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxeExtra.uni deleted file mode 100644 index 27b2ae3bdc..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErr.c b/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErr.c deleted file mode 100644 index 48522c01af..0000000000 --- a/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErr.c +++ /dev/null @@ -1,151 +0,0 @@ -/** @file - Data Hub filter driver that takes DEBUG () info from Data Hub and writes it - to StdErr if it exists. - -Copyright (c) 2006 - 2009, Intel 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 - -EFI_DATA_HUB_PROTOCOL *mDataHub = NULL; - -EFI_EVENT mDataHubStdErrEvent; - -/** - Event handler registered with the Data Hub to parse EFI_DEBUG_CODE. This - handler reads the Data Hub and sends any DEBUG info to StdErr. - - @param Event The event that occured, not used - @param Context DataHub Protocol Pointer -**/ -VOID -EFIAPI -DataHubStdErrEventHandler ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - EFI_DATA_HUB_PROTOCOL *DataHub; - EFI_DATA_RECORD_HEADER *Record; - DATA_HUB_STATUS_CODE_DATA_RECORD *DataRecord; - UINT64 Mtc; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto; - INT32 OldAttribute; - - DataHub = (EFI_DATA_HUB_PROTOCOL *) Context; - - // - // If StdErr is not yet initialized just return a DEBUG print in the BDS - // after consoles are connect will make sure data gets flushed properly - // when StdErr is availible. - // - if (gST == NULL) { - return ; - } - - if (gST->StdErr == NULL) { - return ; - } - - // - // Mtc of zero means return the next record that has not been read by the - // event handler. - // - Mtc = 0; - do { - Status = DataHub->GetNextRecord (DataHub, &Mtc, &mDataHubStdErrEvent, &Record); - if (!EFI_ERROR (Status)) { - if (CompareGuid (&Record->DataRecordGuid, &gEfiDataHubStatusCodeRecordGuid)) { - DataRecord = (DATA_HUB_STATUS_CODE_DATA_RECORD *) (((CHAR8 *) Record) + Record->HeaderSize); - - if (DataRecord->Data.HeaderSize > 0) { - if (CompareGuid (&DataRecord->Data.Type, &gEfiStatusCodeDataTypeDebugGuid)) { - // - // If the Data record is from a DEBUG () then send it to Standard Error - // - Sto = gST->StdErr; - OldAttribute = Sto->Mode->Attribute; - Sto->SetAttribute (Sto, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK)); - Sto->OutputString (Sto, (CHAR16 *) (DataRecord + 1)); - Sto->SetAttribute (Sto, OldAttribute); - } - } - } - } - } while ((Mtc != 0) && !EFI_ERROR (Status)); -} - -/** - Register an event handler with the Data Hub to parse EFI_DEBUG_CODE. This - handler reads the Data Hub and sends any DEBUG info to StdErr. - - @param ImageHandle Image handle of this driver. - @param SystemTable Pointer to EFI system table. - - @retval EFI_SUCCESS The event handler was registered. - @retval EFI_OUT_OF_RESOURCES The event hadler was not registered due to lack of system resources. -**/ -EFI_STATUS -EFIAPI -DataHubStdErrInitialize ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - UINT64 DataClass; - - gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **) &mDataHub); - // - // Should never fail due to Depex grammer. - // - ASSERT (mDataHub != NULL); - - // - // Create an event and register it with the filter driver - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - DataHubStdErrEventHandler, - mDataHub, - &mDataHubStdErrEvent - ); - if (EFI_ERROR (Status)) { - return Status; - } - - DataClass = EFI_DATA_RECORD_CLASS_DEBUG | EFI_DATA_RECORD_CLASS_ERROR; - Status = mDataHub->RegisterFilterDriver ( - mDataHub, - mDataHubStdErrEvent, - TPL_CALLBACK, - DataClass, - NULL - ); - if (EFI_ERROR (Status)) { - gBS->CloseEvent (mDataHubStdErrEvent); - } - - return Status; -} - diff --git a/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf b/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf deleted file mode 100644 index f9dede864c..0000000000 --- a/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf +++ /dev/null @@ -1,57 +0,0 @@ -## @file -# This driver takes DEBUG info from Data Hub and writes it to StdErr if it exists. -# -# 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 -# 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 = DataHubStdErrDxe - MODULE_UNI_FILE = DataHubStdErrDxe.uni - FILE_GUID = CA515306-00CE-4032-874E-11B755FF6866 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = DataHubStdErrInitialize - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - DataHubStdErr.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - UefiBootServicesTableLib - BaseMemoryLib - UefiDriverEntryPoint - DebugLib - -[Guids] - gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## UNDEFINED # DataRecord Date Type - gEfiDataHubStatusCodeRecordGuid ## SOMETIMES_CONSUMES ## UNDEFINED # DataRecordGuid - - -[Protocols] - gEfiDataHubProtocolGuid ## CONSUMES - -[Depex] - gEfiDataHubProtocolGuid - -[UserExtensions.TianoCore."ExtraFiles"] - DataHubStdErrDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.uni b/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.uni deleted file mode 100644 index 88aac304ad..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxeExtra.uni b/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxeExtra.uni deleted file mode 100644 index 9ef673b8a8..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c deleted file mode 100644 index 12508b4335..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c +++ /dev/null @@ -1,608 +0,0 @@ -/** @file - FFS file access utilities. - - 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 "FwVolDriver.h" - -#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address)) - -/** - Set File State in the FfsHeader. - - @param State File state to be set into FFS header. - @param FfsHeader Points to the FFS file header - -**/ -VOID -SetFileState ( - IN UINT8 State, - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - // - // Set File State in the FfsHeader - // - FfsHeader->State = (EFI_FFS_FILE_STATE) (FfsHeader->State ^ State); - return ; -} - -/** - Get the FFS file state by checking the highest bit set in the header's state field. - - @param ErasePolarity Erase polarity attribute of the firmware volume - @param FfsHeader Points to the FFS file header - - @return FFS File state - -**/ -EFI_FFS_FILE_STATE -GetFileState ( - IN UINT8 ErasePolarity, - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - EFI_FFS_FILE_STATE FileState; - UINT8 HighestBit; - - FileState = FfsHeader->State; - - if (ErasePolarity != 0) { - FileState = (EFI_FFS_FILE_STATE)~FileState; - } - - HighestBit = 0x80; - while (HighestBit != 0 && ((HighestBit & FileState) == 0)) { - HighestBit >>= 1; - } - - return (EFI_FFS_FILE_STATE) HighestBit; -} - -/** - Convert the Buffer Address to LBA Entry Address. - - @param FvDevice Cached FvDevice - @param BufferAddress Address of Buffer - @param LbaListEntry Pointer to the got LBA entry that contains the address. - - @retval EFI_NOT_FOUND Buffer address is out of FvDevice. - @retval EFI_SUCCESS LBA entry is found for Buffer address. - -**/ -EFI_STATUS -Buffer2LbaEntry ( - IN FV_DEVICE *FvDevice, - IN EFI_PHYSICAL_ADDRESS BufferAddress, - OUT LBA_ENTRY **LbaListEntry - ) -{ - LBA_ENTRY *LbaEntry; - LIST_ENTRY *Link; - - Link = FvDevice->LbaHeader.ForwardLink; - LbaEntry = (LBA_ENTRY *) Link; - - // - // Locate LBA which contains the address - // - while (&LbaEntry->Link != &FvDevice->LbaHeader) { - if ((EFI_PHYSICAL_ADDRESS) (UINTN) (LbaEntry->StartingAddress) > BufferAddress) { - break; - } - - Link = LbaEntry->Link.ForwardLink; - LbaEntry = (LBA_ENTRY *) Link; - } - - if (&LbaEntry->Link == &FvDevice->LbaHeader) { - return EFI_NOT_FOUND; - } - - Link = LbaEntry->Link.BackLink; - LbaEntry = (LBA_ENTRY *) Link; - - if (&LbaEntry->Link == &FvDevice->LbaHeader) { - return EFI_NOT_FOUND; - } - - *LbaListEntry = LbaEntry; - - return EFI_SUCCESS; -} - -/** - Convert the Buffer Address to LBA Address & Offset. - - @param FvDevice Cached FvDevice - @param BufferAddress Address of Buffer - @param Lba Pointer to the gob Lba value - @param Offset Pointer to the got Offset - - @retval EFI_NOT_FOUND Buffer address is out of FvDevice. - @retval EFI_SUCCESS LBA and Offset is found for Buffer address. - -**/ -EFI_STATUS -Buffer2Lba ( - IN FV_DEVICE *FvDevice, - IN EFI_PHYSICAL_ADDRESS BufferAddress, - OUT EFI_LBA *Lba, - OUT UINTN *Offset - ) -{ - LBA_ENTRY *LbaEntry; - EFI_STATUS Status; - - LbaEntry = NULL; - - Status = Buffer2LbaEntry ( - FvDevice, - BufferAddress, - &LbaEntry - ); - if (EFI_ERROR (Status)) { - return Status; - } - - *Lba = LbaEntry->LbaIndex; - *Offset = (UINTN) BufferAddress - (UINTN) LbaEntry->StartingAddress; - - return EFI_SUCCESS; -} - -/** - Check if a block of buffer is erased. - - @param ErasePolarity Erase polarity attribute of the firmware volume - @param Buffer The buffer to be checked - @param BufferSize Size of the buffer in bytes - - @retval TRUE The block of buffer is erased - @retval FALSE The block of buffer is not erased - -**/ -BOOLEAN -IsBufferErased ( - IN UINT8 ErasePolarity, - IN UINT8 *Buffer, - IN UINTN BufferSize - ) -{ - UINTN Count; - UINT8 EraseByte; - - if (ErasePolarity == 1) { - EraseByte = 0xFF; - } else { - EraseByte = 0; - } - - for (Count = 0; Count < BufferSize; Count++) { - if (Buffer[Count] != EraseByte) { - return FALSE; - } - } - - return TRUE; -} - -/** - Verify checksum of the firmware volume header. - - @param FvHeader Points to the firmware volume header to be checked - - @retval TRUE Checksum verification passed - @retval FALSE Checksum verification failed - -**/ -BOOLEAN -VerifyFvHeaderChecksum ( - IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader - ) -{ - UINT16 Checksum; - - Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength); - - if (Checksum == 0) { - return TRUE; - } else { - return FALSE; - } -} - -/** - Verify checksum of the FFS file header. - - @param FfsHeader Points to the FFS file header to be checked - - @retval TRUE Checksum verification passed - @retval FALSE Checksum verification failed - -**/ -BOOLEAN -VerifyHeaderChecksum ( - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - UINT8 HeaderChecksum; - - if (IS_FFS_FILE2 (FfsHeader)) { - HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER2)); - } else { - HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER)); - } - HeaderChecksum = (UINT8) (HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File); - - if (HeaderChecksum == 0) { - return TRUE; - } else { - return FALSE; - } -} - -/** - Verify checksum of the FFS file data. - - @param FfsHeader Points to the FFS file header to be checked - - @retval TRUE Checksum verification passed - @retval FALSE Checksum verification failed - -**/ -BOOLEAN -VerifyFileChecksum ( - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - UINT8 FileChecksum; - EFI_FV_FILE_ATTRIBUTES Attributes; - - Attributes = FfsHeader->Attributes; - - if ((Attributes & FFS_ATTRIB_CHECKSUM) != 0) { - - // - // Check checksum of FFS data - // - if (IS_FFS_FILE2 (FfsHeader)) { - FileChecksum = CalculateSum8 ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER2)); - } else { - FileChecksum = CalculateSum8 ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER)); - } - FileChecksum = (UINT8) (FileChecksum + FfsHeader->IntegrityCheck.Checksum.File); - - if (FileChecksum == 0) { - return TRUE; - } else { - return FALSE; - } - - } else { - - if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { - return FALSE; - } else { - return TRUE; - } - } - -} - -/** - Check if it's a valid FFS file header. - - @param ErasePolarity Erase polarity attribute of the firmware volume - @param FfsHeader Points to the FFS file header to be checked - - @retval TRUE Valid FFS file header - @retval FALSE Invalid FFS file header - -**/ -BOOLEAN -IsValidFFSHeader ( - IN UINT8 ErasePolarity, - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - EFI_FFS_FILE_STATE FileState; - - // - // Check if it is a free space - // - if (IsBufferErased ( - ErasePolarity, - (UINT8 *) FfsHeader, - sizeof (EFI_FFS_FILE_HEADER) - )) { - return FALSE; - } - - FileState = GetFileState (ErasePolarity, FfsHeader); - - switch (FileState) { - case EFI_FILE_HEADER_CONSTRUCTION: - // - // fall through - // - case EFI_FILE_HEADER_INVALID: - return FALSE; - - case EFI_FILE_HEADER_VALID: - // - // fall through - // - case EFI_FILE_DATA_VALID: - // - // fall through - // - case EFI_FILE_MARKED_FOR_UPDATE: - // - // fall through - // - case EFI_FILE_DELETED: - // - // Here we need to verify header checksum - // - if (!VerifyHeaderChecksum (FfsHeader)) { - return FALSE; - } - break; - - default: - // - // return - // - return FALSE; - } - - return TRUE; -} - -/** - Get next possible of Firmware File System Header. - - @param ErasePolarity Erase polarity attribute of the firmware volume - @param FfsHeader Points to the FFS file header to be skipped. - - @return Pointer to next FFS header. - -**/ -EFI_PHYSICAL_ADDRESS -GetNextPossibleFileHeader ( - IN UINT8 ErasePolarity, - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - UINT32 FileLength; - UINT32 SkipLength; - - if (!IsValidFFSHeader (ErasePolarity, FfsHeader)) { - // - // Skip this header - // - if (IS_FFS_FILE2 (FfsHeader)) { - return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2); - } else { - return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + sizeof (EFI_FFS_FILE_HEADER); - } - } - - if (IS_FFS_FILE2 (FfsHeader)) { - FileLength = FFS_FILE2_SIZE (FfsHeader); - } else { - FileLength = FFS_FILE_SIZE (FfsHeader); - } - - // - // Since FileLength is not multiple of 8, we need skip some bytes - // to get next possible header - // - SkipLength = FileLength; - while ((SkipLength & 0x07) != 0) { - SkipLength++; - } - - return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + SkipLength; -} - -/** - Search FFS file with the same FFS name in FV Cache. - - @param FvDevice Cached FV image. - @param FfsHeader Points to the FFS file header to be skipped. - @param StateBit FFS file state bit to be checked. - - @return Pointer to next found FFS header. NULL will return if no found. - -**/ -EFI_FFS_FILE_HEADER * -DuplicateFileExist ( - IN FV_DEVICE *FvDevice, - IN EFI_FFS_FILE_HEADER *FfsHeader, - IN EFI_FFS_FILE_STATE StateBit - ) -{ - UINT8 *Ptr; - EFI_FFS_FILE_HEADER *NextFfsFile; - - // - // Search duplicate file, not from the beginning of FV, - // just search the next ocurrence of this file - // - NextFfsFile = FfsHeader; - - do { - Ptr = (UINT8 *) PHYSICAL_ADDRESS_TO_POINTER ( - GetNextPossibleFileHeader (FvDevice->ErasePolarity, - NextFfsFile) - ); - NextFfsFile = (EFI_FFS_FILE_HEADER *) Ptr; - - if ((UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (FvDevice->CachedFv) + FvDevice->FwVolHeader->FvLength - Ptr < - sizeof (EFI_FFS_FILE_HEADER) - ) { - break; - } - - if (!IsValidFFSHeader (FvDevice->ErasePolarity, NextFfsFile)) { - continue; - } - - if (!VerifyFileChecksum (NextFfsFile)) { - continue; - } - - if (CompareGuid (&NextFfsFile->Name, &FfsHeader->Name)) { - if (GetFileState (FvDevice->ErasePolarity, NextFfsFile) == StateBit) { - return NextFfsFile; - } - } - } while (Ptr < (UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (FvDevice->CachedFv) + FvDevice->FwVolHeader->FvLength); - - return NULL; -} - -/** - Change FFS file header state and write to FV. - - @param FvDevice Cached FV image. - @param FfsHeader Points to the FFS file header to be updated. - @param State FFS file state to be set. - - @retval EFI_SUCCESS File state is writen into FV. - @retval others File state can't be writen into FV. - -**/ -EFI_STATUS -UpdateHeaderBit ( - IN FV_DEVICE *FvDevice, - IN EFI_FFS_FILE_HEADER *FfsHeader, - IN EFI_FFS_FILE_STATE State - ) -{ - EFI_STATUS Status; - EFI_LBA Lba; - UINTN Offset; - UINTN NumBytesWritten; - - Lba = 0; - Offset = 0; - - SetFileState (State, FfsHeader); - - Buffer2Lba ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) (&FfsHeader->State), - &Lba, - &Offset - ); - // - // Write the state byte into FV - // - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvDevice->Fvb->Write ( - FvDevice->Fvb, - Lba, - Offset, - &NumBytesWritten, - &FfsHeader->State - ); - return Status; -} - -/** - Check if it's a valid FFS file. - Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first. - - @param FvDevice Cached FV image. - @param FfsHeader Points to the FFS file to be checked - - @retval TRUE Valid FFS file - @retval FALSE Invalid FFS file - -**/ -BOOLEAN -IsValidFFSFile ( - IN FV_DEVICE *FvDevice, - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - EFI_FFS_FILE_STATE FileState; - UINT8 ErasePolarity; - - ErasePolarity = FvDevice->ErasePolarity; - - FileState = GetFileState (ErasePolarity, FfsHeader); - - switch (FileState) { - case EFI_FILE_DATA_VALID: - if (!VerifyFileChecksum (FfsHeader)) { - return FALSE; - } - - if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { - break; - } - // - // Check if there is another duplicated file with the EFI_FILE_DATA_VALID - // - if (DuplicateFileExist (FvDevice, FfsHeader, EFI_FILE_DATA_VALID) != NULL) { - return FALSE; - } - - break; - - case EFI_FILE_MARKED_FOR_UPDATE: - if (!VerifyFileChecksum (FfsHeader)) { - return FALSE; - } - - if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { - // - // since its data area is not unperturbed, it cannot be reclaimed, - // marked it as deleted - // - UpdateHeaderBit (FvDevice, FfsHeader, EFI_FILE_DELETED); - return TRUE; - - } else if (DuplicateFileExist (FvDevice, FfsHeader, EFI_FILE_DATA_VALID) != NULL) { - // - // Here the found file is more recent than this file, - // mark it as deleted - // - UpdateHeaderBit (FvDevice, FfsHeader, EFI_FILE_DELETED); - return TRUE; - - } else { - return TRUE; - } - - break; - - case EFI_FILE_DELETED: - if (!VerifyFileChecksum (FfsHeader)) { - return FALSE; - } - - break; - - default: - return FALSE; - } - - return TRUE; -} - diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwPadFile.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwPadFile.c deleted file mode 100644 index 8d53d879bd..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwPadFile.c +++ /dev/null @@ -1,1228 +0,0 @@ -/** @file - Implements functions to pad firmware file. - - 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 "FwVolDriver.h" - -/** - Calculate the checksum for a PAD file. - - @param PadFileHeader The Pad File to be caculeted the checksum. - -**/ -VOID -SetPadFileChecksum ( - IN EFI_FFS_FILE_HEADER *PadFileHeader - ) -{ - if ((PadFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) { - - if (IS_FFS_FILE2 (PadFileHeader)) { - // - // Calculate checksum of Pad File Data - // - PadFileHeader->IntegrityCheck.Checksum.File = - CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2)); - - } else { - // - // Calculate checksum of Pad File Data - // - PadFileHeader->IntegrityCheck.Checksum.File = - CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER)); - } - - } else { - - PadFileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; - - } - - return ; -} - -/** - Create a PAD File in the Free Space. - - @param FvDevice Firmware Volume Device. - @param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted. - @param Size Pad file Size, not include the header. - @param PadFileEntry The Ffs File Entry that points to this Pad File. - - @retval EFI_SUCCESS Successfully create a PAD file. - @retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file. - @retval EFI_INVALID_PARAMETER Size is not 8 byte alignment. - @retval EFI_DEVICE_ERROR Free space is not erased. -**/ -EFI_STATUS -FvCreatePadFileInFreeSpace ( - IN FV_DEVICE *FvDevice, - IN FREE_SPACE_ENTRY *FreeSpaceEntry, - IN UINTN Size, - OUT FFS_FILE_LIST_ENTRY **PadFileEntry - ) -{ - EFI_STATUS Status; - EFI_FFS_FILE_HEADER *PadFileHeader; - UINTN Offset; - UINTN NumBytesWritten; - UINTN StateOffset; - UINT8 *StartPos; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - UINTN HeaderSize; - UINTN FileSize; - - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - FileSize = Size + HeaderSize; - if (FileSize > 0x00FFFFFF) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - FileSize = Size + HeaderSize; - } - - if (FreeSpaceEntry->Length < FileSize) { - return EFI_OUT_OF_RESOURCES; - } - - if ((Size & 0x07) != 0) { - return EFI_INVALID_PARAMETER; - } - - StartPos = FreeSpaceEntry->StartingAddress; - - // - // First double check the space - // - if (!IsBufferErased ( - FvDevice->ErasePolarity, - StartPos, - FileSize - )) { - return EFI_DEVICE_ERROR; - } - - PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos; - - // - // Create File Step 1 - // - SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader); - - Offset = (UINTN) (StartPos - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &PadFileHeader->State - ); - if (EFI_ERROR (Status)) { - SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader); - return Status; - } - // - // Update Free Space Entry, since header is allocated - // - FreeSpaceEntry->Length -= HeaderSize; - FreeSpaceEntry->StartingAddress += HeaderSize; - - // - // Fill File Name Guid, here we assign a NULL-GUID to Pad files - // - ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID)); - - // - // Fill File Type, checksum(0), Attributes(0), Size - // - PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD; - PadFileHeader->Attributes = 0; - if ((FileSize) > 0x00FFFFFF) { - ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) FileSize; - *(UINT32 *) PadFileHeader->Size &= 0xFF000000; - PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; - } else { - *(UINT32 *) PadFileHeader->Size &= 0xFF000000; - *(UINT32 *) PadFileHeader->Size |= FileSize; - } - - SetHeaderChecksum (PadFileHeader); - SetPadFileChecksum (PadFileHeader); - - Offset = (UINTN) (StartPos - FvDevice->CachedFv); - - NumBytesWritten = HeaderSize; - Status = FvcWrite ( - FvDevice, - Offset, - &NumBytesWritten, - (UINT8 *) PadFileHeader - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Step 2, then Mark header valid, since no data write, - // mark the data valid at the same time. - // - SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader); - SetFileState (EFI_FILE_DATA_VALID, PadFileHeader); - - Offset = (UINTN) (StartPos - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &PadFileHeader->State - ); - if (EFI_ERROR (Status)) { - SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader); - SetFileState (EFI_FILE_DATA_VALID, PadFileHeader); - return Status; - } - // - // Update Free Space Entry, since header is allocated - // - FreeSpaceEntry->Length -= Size; - FreeSpaceEntry->StartingAddress += Size; - - // - // If successfully, insert an FfsFileEntry at the end of ffs file list - // - FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); - ASSERT (FfsFileEntry != NULL); - - FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) StartPos; - InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); - - *PadFileEntry = FfsFileEntry; - FvDevice->CurrentFfsFile = FfsFileEntry; - - return EFI_SUCCESS; -} - -/** - Fill pad file header within firmware cache. - - @param PadFileHeader The start of the Pad File Buffer. - @param PadFileLength The length of the pad file including the header. - -**/ -VOID -FvFillPadFile ( - IN EFI_FFS_FILE_HEADER *PadFileHeader, - IN UINTN PadFileLength - ) -{ - // - // Fill File Name Guid, here we assign a NULL-GUID to Pad files - // - ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID)); - - // - // Fill File Type, checksum(0), Attributes(0), Size - // - PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD; - PadFileHeader->Attributes = 0; - if (PadFileLength > 0x00FFFFFF) { - ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) PadFileLength; - *(UINT32 *) PadFileHeader->Size &= 0xFF000000; - PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; - } else { - *(UINT32 *) PadFileHeader->Size &= 0xFF000000; - *(UINT32 *) PadFileHeader->Size |= PadFileLength; - } - - SetHeaderChecksum (PadFileHeader); - SetPadFileChecksum (PadFileHeader); - - // - // Set File State to 0x00000111 - // - SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader); - SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader); - SetFileState (EFI_FILE_DATA_VALID, PadFileHeader); - - return ; -} - -/** - Create entire FFS file. - - @param FileHeader Starting Address of a Buffer that hold the FFS File image. - @param FfsFileBuffer The source buffer that contains the File Data. - @param BufferSize The length of FfsFileBuffer. - @param ActualFileSize Size of FFS file. - @param FileName The Guid of Ffs File. - @param FileType The type of the written Ffs File. - @param FileAttributes The attributes of the written Ffs File. - - @retval EFI_INVALID_PARAMETER File type is not valid. - @retval EFI_SUCCESS FFS file is successfully created. - -**/ -EFI_STATUS -FvFillFfsFile ( - OUT EFI_FFS_FILE_HEADER *FileHeader, - IN UINT8 *FfsFileBuffer, - IN UINTN BufferSize, - IN UINTN ActualFileSize, - IN EFI_GUID *FileName, - IN EFI_FV_FILETYPE FileType, - IN EFI_FV_FILE_ATTRIBUTES FileAttributes - ) -{ - EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute; - EFI_FFS_FILE_HEADER *TmpFileHeader; - - // - // File Type value 0x0E~0xE0 are reserved - // - if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) { - return EFI_INVALID_PARAMETER; - } - - TmpFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer; - // - // First fill all fields ready in FfsFileBuffer - // - CopyGuid (&TmpFileHeader->Name, FileName); - TmpFileHeader->Type = FileType; - - // - // Convert the FileAttributes to FFSFileAttributes - // - FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute); - - TmpFileHeader->Attributes = TmpFileAttribute; - - if (ActualFileSize > 0x00FFFFFF) { - ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize; - *(UINT32 *) FileHeader->Size &= 0xFF000000; - FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; - } else { - *(UINT32 *) FileHeader->Size &= 0xFF000000; - *(UINT32 *) FileHeader->Size |= ActualFileSize; - } - - SetHeaderChecksum (TmpFileHeader); - SetFileChecksum (TmpFileHeader, ActualFileSize); - - SetFileState (EFI_FILE_HEADER_CONSTRUCTION, TmpFileHeader); - SetFileState (EFI_FILE_HEADER_VALID, TmpFileHeader); - SetFileState (EFI_FILE_DATA_VALID, TmpFileHeader); - - // - // Copy data from FfsFileBuffer to FileHeader(cache) - // - CopyMem (FileHeader, FfsFileBuffer, BufferSize); - - return EFI_SUCCESS; -} - -/** - Fill some other extra space using 0xFF(Erase Value). - - @param ErasePolarity Fv erase value. - @param FileHeader Point to the start of FFS File. - @param ExtraLength The pading length. - -**/ -VOID -FvAdjustFfsFile ( - IN UINT8 ErasePolarity, - IN EFI_FFS_FILE_HEADER *FileHeader, - IN UINTN ExtraLength - ) -{ - UINT8 *Ptr; - UINT8 PadingByte; - - if (IS_FFS_FILE2 (FileHeader)) { - Ptr = (UINT8 *) FileHeader + FFS_FILE2_SIZE (FileHeader); - } else { - Ptr = (UINT8 *) FileHeader + FFS_FILE_SIZE (FileHeader); - } - - if (ErasePolarity == 0) { - PadingByte = 0; - } else { - PadingByte = 0xFF; - } - // - // Fill the non-used space with Padding Byte - // - SetMem (Ptr, ExtraLength, PadingByte); - - return ; -} - -/** - Free File List entry pointed by FileListHead. - - @param FileListHeader FileListEntry Header. - -**/ -VOID -FreeFileList ( - IN LIST_ENTRY *FileListHead - ) -{ - FFS_FILE_LIST_ENTRY *FfsFileEntry; - LIST_ENTRY *NextEntry; - - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) (FileListHead->ForwardLink); - - // - // Loop the whole list entry to free resources - // - while (&FfsFileEntry->Link != FileListHead) { - NextEntry = (&FfsFileEntry->Link)->ForwardLink; - FreePool (FfsFileEntry); - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry; - } - - return ; -} - -/** - Create a new file within a PAD file area. - - @param FvDevice Firmware Volume Device. - @param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state). - @param BufferSize The size of FfsFileBuffer. - @param ActualFileSize The actual file length, it may not be multiples of 8. - @param FileName The FFS File Name. - @param FileType The FFS File Type. - @param FileAttributes The Attributes of the FFS File to be created. - - @retval EFI_SUCCESS Successfully create a new file within the found PAD file area. - @retval EFI_OUT_OF_RESOURCES No suitable PAD file is found. - @retval other errors New file is created failed. - -**/ -EFI_STATUS -FvCreateNewFileInsidePadFile ( - IN FV_DEVICE *FvDevice, - IN UINT8 *FfsFileBuffer, - IN UINTN BufferSize, - IN UINTN ActualFileSize, - IN EFI_GUID *FileName, - IN EFI_FV_FILETYPE FileType, - IN EFI_FV_FILE_ATTRIBUTES FileAttributes - ) -{ - UINTN RequiredAlignment; - FFS_FILE_LIST_ENTRY *PadFileEntry; - EFI_STATUS Status; - UINTN PadAreaLength; - UINTN PadSize; - EFI_FFS_FILE_HEADER *FileHeader; - EFI_FFS_FILE_HEADER *OldPadFileHeader; - EFI_FFS_FILE_HEADER *PadFileHeader; - EFI_FFS_FILE_HEADER *TailPadFileHeader; - UINTN StateOffset; - UINTN Offset; - UINTN NumBytesWritten; - UINT8 *StartPos; - LIST_ENTRY NewFileList; - FFS_FILE_LIST_ENTRY *NewFileListEntry; - FFS_FILE_LIST_ENTRY *FfsEntry; - FFS_FILE_LIST_ENTRY *NextFfsEntry; - - // - // First get the required alignment from the File Attributes - // - RequiredAlignment = GetRequiredAlignment (FileAttributes); - - // - // Find a suitable PAD File - // - Status = FvLocatePadFile ( - FvDevice, - BufferSize, - RequiredAlignment, - &PadSize, - &PadFileEntry - ); - - if (EFI_ERROR (Status)) { - return EFI_OUT_OF_RESOURCES; - } - - OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader; - - // - // Step 1: Update Pad File Header - // - SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldPadFileHeader); - - StartPos = PadFileEntry->FfsHeader; - - Offset = (UINTN) (StartPos - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &OldPadFileHeader->State - ); - if (EFI_ERROR (Status)) { - SetFileState (EFI_FILE_HEADER_CONSTRUCTION, OldPadFileHeader); - return Status; - } - - // - // Step 2: Update Pad area - // - InitializeListHead (&NewFileList); - - if (IS_FFS_FILE2 (OldPadFileHeader)) { - PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER); - PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2)); - } else { - PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER); - PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER)); - } - - if (PadSize != 0) { - // - // Insert a PAD file before to achieve required alignment - // - FvFillPadFile (PadFileHeader, PadSize); - NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); - ASSERT (NewFileListEntry != NULL); - NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader; - InsertTailList (&NewFileList, &NewFileListEntry->Link); - } - - FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize); - - Status = FvFillFfsFile ( - FileHeader, - FfsFileBuffer, - BufferSize, - ActualFileSize, - FileName, - FileType, - FileAttributes - ); - if (EFI_ERROR (Status)) { - FreeFileList (&NewFileList); - return Status; - } - - NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); - ASSERT (NewFileListEntry != NULL); - - NewFileListEntry->FfsHeader = (UINT8 *) FileHeader; - InsertTailList (&NewFileList, &NewFileListEntry->Link); - - FvDevice->CurrentFfsFile = NewFileListEntry; - - if (PadAreaLength > (BufferSize + PadSize)) { - if ((PadAreaLength - BufferSize - PadSize) >= sizeof (EFI_FFS_FILE_HEADER)) { - // - // we can insert another PAD file - // - TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize); - FvFillPadFile (TailPadFileHeader, PadAreaLength - BufferSize - PadSize); - - NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); - ASSERT (NewFileListEntry != NULL); - - NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader; - InsertTailList (&NewFileList, &NewFileListEntry->Link); - } else { - // - // because left size cannot hold another PAD file header, - // adjust the writing file size (just in cache) - // - FvAdjustFfsFile ( - FvDevice->ErasePolarity, - FileHeader, - PadAreaLength - BufferSize - PadSize - ); - } - } - // - // Start writing to FV - // - if (IS_FFS_FILE2 (OldPadFileHeader)) { - StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2); - } else { - StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER); - } - - Offset = (UINTN) (StartPos - FvDevice->CachedFv); - - NumBytesWritten = PadAreaLength; - Status = FvcWrite ( - FvDevice, - Offset, - &NumBytesWritten, - StartPos - ); - if (EFI_ERROR (Status)) { - FreeFileList (&NewFileList); - FvDevice->CurrentFfsFile = NULL; - return Status; - } - - // - // Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID - // - SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader); - - StartPos = PadFileEntry->FfsHeader; - - Offset = (UINTN) (StartPos - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &OldPadFileHeader->State - ); - if (EFI_ERROR (Status)) { - SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader); - FreeFileList (&NewFileList); - FvDevice->CurrentFfsFile = NULL; - return Status; - } - - // - // If all successfully, update FFS_FILE_LIST - // - - // - // Delete old pad file entry - // - FfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink; - NextFfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink; - - FreePool (PadFileEntry); - - FfsEntry->Link.ForwardLink = NewFileList.ForwardLink; - (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link; - NextFfsEntry->Link.BackLink = NewFileList.BackLink; - (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link; - - return EFI_SUCCESS; -} - -/** - Free all FfsBuffer. - - @param NumOfFiles Number of FfsBuffer. - @param FfsBuffer An array of pointer to an FFS File Buffer - -**/ -VOID -FreeFfsBuffer ( - IN UINTN NumOfFiles, - IN UINT8 **FfsBuffer - ) -{ - UINTN Index; - for (Index = 0; Index < NumOfFiles; Index++) { - if (FfsBuffer[Index] != NULL) { - FreePool (FfsBuffer[Index]); - } - } -} - -/** - Create multiple files within a PAD File area. - - @param FvDevice Firmware Volume Device. - @param PadFileEntry The pad file entry to be written in. - @param NumOfFiles Total File number to be written. - @param BufferSize The array of buffer size of each FfsBuffer. - @param ActualFileSize The array of actual file size. - @param PadSize The array of leading pad file size for each FFS File - @param FfsBuffer The array of Ffs Buffer pointer. - @param FileData The array of EFI_FV_WRITE_FILE_DATA structure, - used to get name, attributes, type, etc. - - @retval EFI_SUCCESS Add the input multiple files into PAD file area. - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval other error Files can't be added into PAD file area. - -**/ -EFI_STATUS -FvCreateMultipleFilesInsidePadFile ( - IN FV_DEVICE *FvDevice, - IN FFS_FILE_LIST_ENTRY *PadFileEntry, - IN UINTN NumOfFiles, - IN UINTN *BufferSize, - IN UINTN *ActualFileSize, - IN UINTN *PadSize, - IN UINT8 **FfsBuffer, - IN EFI_FV_WRITE_FILE_DATA *FileData - ) -{ - EFI_STATUS Status; - EFI_FFS_FILE_HEADER *OldPadFileHeader; - UINTN Index; - EFI_FFS_FILE_HEADER *PadFileHeader; - EFI_FFS_FILE_HEADER *FileHeader; - EFI_FFS_FILE_HEADER *TailPadFileHeader; - UINTN TotalSize; - UINTN PadAreaLength; - LIST_ENTRY NewFileList; - FFS_FILE_LIST_ENTRY *NewFileListEntry; - UINTN Offset; - UINTN NumBytesWritten; - UINT8 *StartPos; - FFS_FILE_LIST_ENTRY *FfsEntry; - FFS_FILE_LIST_ENTRY *NextFfsEntry; - - InitializeListHead (&NewFileList); - - NewFileListEntry = NULL; - - OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader; - if (IS_FFS_FILE2 (OldPadFileHeader)) { - PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2); - } else { - PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER); - } - - Status = UpdateHeaderBit ( - FvDevice, - OldPadFileHeader, - EFI_FILE_MARKED_FOR_UPDATE - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Update PAD area - // - TotalSize = 0; - if (IS_FFS_FILE2 (OldPadFileHeader)) { - PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2)); - } else { - PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER)); - } - FileHeader = PadFileHeader; - - for (Index = 0; Index < NumOfFiles; Index++) { - if (PadSize[Index] != 0) { - FvFillPadFile (PadFileHeader, PadSize[Index]); - NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); - if (NewFileListEntry == NULL) { - FreeFileList (&NewFileList); - return EFI_OUT_OF_RESOURCES; - } - - NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader; - InsertTailList (&NewFileList, &NewFileListEntry->Link); - } - - FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]); - Status = FvFillFfsFile ( - FileHeader, - FfsBuffer[Index], - BufferSize[Index], - ActualFileSize[Index], - FileData[Index].NameGuid, - FileData[Index].Type, - FileData[Index].FileAttributes - ); - if (EFI_ERROR (Status)) { - FreeFileList (&NewFileList); - return Status; - } - - NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); - if (NewFileListEntry == NULL) { - FreeFileList (&NewFileList); - return EFI_OUT_OF_RESOURCES; - } - - NewFileListEntry->FfsHeader = (UINT8 *) FileHeader; - InsertTailList (&NewFileList, &NewFileListEntry->Link); - - PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]); - TotalSize += PadSize[Index]; - TotalSize += BufferSize[Index]; - } - - FvDevice->CurrentFfsFile = NewFileListEntry; - // - // Maybe we need a tail pad file - // - if (PadAreaLength > TotalSize) { - if ((PadAreaLength - TotalSize) >= sizeof (EFI_FFS_FILE_HEADER)) { - // - // we can insert another PAD file - // - TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[NumOfFiles - 1]); - FvFillPadFile (TailPadFileHeader, PadAreaLength - TotalSize); - - NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); - if (NewFileListEntry == NULL) { - FreeFileList (&NewFileList); - FvDevice->CurrentFfsFile = NULL; - return EFI_OUT_OF_RESOURCES; - } - - NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader; - InsertTailList (&NewFileList, &NewFileListEntry->Link); - } else { - // - // because left size cannot hold another PAD file header, - // adjust the writing file size (just in cache) - // - FvAdjustFfsFile ( - FvDevice->ErasePolarity, - FileHeader, - PadAreaLength - TotalSize - ); - } - } - // - // Start writing to FV - // - if (IS_FFS_FILE2 (OldPadFileHeader)) { - StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2); - } else { - StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER); - } - - Offset = (UINTN) (StartPos - FvDevice->CachedFv); - - NumBytesWritten = PadAreaLength; - Status = FvcWrite ( - FvDevice, - Offset, - &NumBytesWritten, - StartPos - ); - if (EFI_ERROR (Status)) { - FreeFileList (&NewFileList); - FvDevice->CurrentFfsFile = NULL; - return Status; - } - - Status = UpdateHeaderBit ( - FvDevice, - OldPadFileHeader, - EFI_FILE_HEADER_INVALID - ); - if (EFI_ERROR (Status)) { - FreeFileList (&NewFileList); - FvDevice->CurrentFfsFile = NULL; - return Status; - } - - // - // Update File List Link - // - - // - // First delete old pad file entry - // - FfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink; - NextFfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink; - - FreePool (PadFileEntry); - - FfsEntry->Link.ForwardLink = NewFileList.ForwardLink; - (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link; - NextFfsEntry->Link.BackLink = NewFileList.BackLink; - (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link; - - return EFI_SUCCESS; -} - -/** - Create multiple files within the Free Space. - - @param FvDevice Firmware Volume Device. - @param FreeSpaceEntry Indicating in which Free Space(Cache) the multiple files will be inserted. - @param NumOfFiles Total File number to be written. - @param BufferSize The array of buffer size of each FfsBuffer. - @param ActualFileSize The array of actual file size. - @param PadSize The array of leading pad file size for each FFS File - @param FfsBuffer The array of Ffs Buffer pointer. - @param FileData The array of EFI_FV_WRITE_FILE_DATA structure, - used to get name, attributes, type, etc. - - @retval EFI_SUCCESS Add the input multiple files into PAD file area. - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval other error Files can't be added into PAD file area. - -**/ -EFI_STATUS -FvCreateMultipleFilesInsideFreeSpace ( - IN FV_DEVICE *FvDevice, - IN FREE_SPACE_ENTRY *FreeSpaceEntry, - IN UINTN NumOfFiles, - IN UINTN *BufferSize, - IN UINTN *ActualFileSize, - IN UINTN *PadSize, - IN UINT8 **FfsBuffer, - IN EFI_FV_WRITE_FILE_DATA *FileData - ) -{ - EFI_STATUS Status; - UINTN Index; - EFI_FFS_FILE_HEADER *PadFileHeader; - EFI_FFS_FILE_HEADER *FileHeader; - UINTN TotalSize; - LIST_ENTRY NewFileList; - FFS_FILE_LIST_ENTRY *NewFileListEntry; - UINTN Offset; - UINTN NumBytesWritten; - UINT8 *StartPos; - - InitializeListHead (&NewFileList); - - NewFileListEntry = NULL; - - TotalSize = 0; - StartPos = FreeSpaceEntry->StartingAddress; - PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos; - FileHeader = PadFileHeader; - - for (Index = 0; Index < NumOfFiles; Index++) { - if (PadSize[Index] != 0) { - FvFillPadFile (PadFileHeader, PadSize[Index]); - NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); - if (NewFileListEntry == NULL) { - FreeFileList (&NewFileList); - return EFI_OUT_OF_RESOURCES; - } - - NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader; - InsertTailList (&NewFileList, &NewFileListEntry->Link); - } - - FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]); - Status = FvFillFfsFile ( - FileHeader, - FfsBuffer[Index], - BufferSize[Index], - ActualFileSize[Index], - FileData[Index].NameGuid, - FileData[Index].Type, - FileData[Index].FileAttributes - ); - if (EFI_ERROR (Status)) { - FreeFileList (&NewFileList); - return Status; - } - - NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY)); - if (NewFileListEntry == NULL) { - FreeFileList (&NewFileList); - return EFI_OUT_OF_RESOURCES; - } - - NewFileListEntry->FfsHeader = (UINT8 *) FileHeader; - InsertTailList (&NewFileList, &NewFileListEntry->Link); - - PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]); - TotalSize += PadSize[Index]; - TotalSize += BufferSize[Index]; - } - - if (FreeSpaceEntry->Length < TotalSize) { - FreeFileList (&NewFileList); - return EFI_OUT_OF_RESOURCES; - } - - FvDevice->CurrentFfsFile = NewFileListEntry; - - // - // Start writing to FV - // - Offset = (UINTN) (StartPos - FvDevice->CachedFv); - - NumBytesWritten = TotalSize; - Status = FvcWrite ( - FvDevice, - Offset, - &NumBytesWritten, - StartPos - ); - if (EFI_ERROR (Status)) { - FreeFileList (&NewFileList); - FvDevice->CurrentFfsFile = NULL; - return Status; - } - - FreeSpaceEntry->Length -= TotalSize; - FreeSpaceEntry->StartingAddress += TotalSize; - - NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileList.ForwardLink); - - while (NewFileListEntry != (FFS_FILE_LIST_ENTRY *) &NewFileList) { - InsertTailList (&FvDevice->FfsFileListHeader, &NewFileListEntry->Link); - NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileListEntry->Link.ForwardLink); - } - - return EFI_SUCCESS; -} - -/** - Write multiple files into FV in reliable method. - - @param FvDevice Firmware Volume Device. - @param NumOfFiles Total File number to be written. - @param FileData The array of EFI_FV_WRITE_FILE_DATA structure, - used to get name, attributes, type, etc - @param FileOperation The array of operation for each file. - - @retval EFI_SUCCESS Files are added into FV. - @retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files. - @retval EFI_INVALID_PARAMETER File number is less than or equal to 1. - @retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files. - -**/ -EFI_STATUS -FvCreateMultipleFiles ( - IN FV_DEVICE *FvDevice, - IN UINTN NumOfFiles, - IN EFI_FV_WRITE_FILE_DATA *FileData, - IN BOOLEAN *FileOperation - ) -{ - EFI_STATUS Status; - UINT8 *FfsBuffer[MAX_FILES]; - UINTN Index1; - UINTN Index2; - UINTN BufferSize[MAX_FILES]; - UINTN ActualFileSize[MAX_FILES]; - UINTN RequiredAlignment[MAX_FILES]; - UINTN PadSize[MAX_FILES]; - FFS_FILE_LIST_ENTRY *PadFileEntry; - UINTN TotalSizeNeeded; - FREE_SPACE_ENTRY *FreeSpaceEntry; - EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; - UINTN Key; - EFI_GUID FileNameGuid; - EFI_FV_FILETYPE OldFileType; - EFI_FV_FILE_ATTRIBUTES OldFileAttributes; - UINTN OldFileSize; - FFS_FILE_LIST_ENTRY *OldFfsFileEntry[MAX_FILES]; - EFI_FFS_FILE_HEADER *OldFileHeader[MAX_FILES]; - BOOLEAN IsCreateFile; - UINTN HeaderSize; - - // - // To use this function, we must ensure that the NumOfFiles is great - // than 1 - // - if (NumOfFiles <= 1) { - return EFI_INVALID_PARAMETER; - } - - if (NumOfFiles > MAX_FILES) { - return EFI_UNSUPPORTED; - } - - Fv = &FvDevice->Fv; - - SetMem (FfsBuffer, NumOfFiles, 0); - SetMem (RequiredAlignment, NumOfFiles, 8); - SetMem (PadSize, NumOfFiles, 0); - ZeroMem (OldFfsFileEntry, sizeof (OldFfsFileEntry)); - ZeroMem (OldFileHeader, sizeof (OldFileHeader)); - - // - // Adjust file size - // - for (Index1 = 0; Index1 < NumOfFiles; Index1++) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize; - if (ActualFileSize[Index1] > 0x00FFFFFF) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize; - } - BufferSize[Index1] = ActualFileSize[Index1]; - - if (BufferSize[Index1] == HeaderSize) { - // - // clear file attributes, zero-length file does not have any attributes - // - FileData[Index1].FileAttributes = 0; - } - - while ((BufferSize[Index1] & 0x07) != 0) { - BufferSize[Index1]++; - } - - FfsBuffer[Index1] = AllocateZeroPool (BufferSize[Index1]); - - // - // Copy File Data into FileBuffer - // - CopyMem ( - FfsBuffer[Index1] + HeaderSize, - FileData[Index1].Buffer, - FileData[Index1].BufferSize - ); - - if (FvDevice->ErasePolarity == 1) { - for (Index2 = 0; Index2 < HeaderSize; Index2++) { - FfsBuffer[Index1][Index2] = (UINT8)~FfsBuffer[Index1][Index2]; - } - } - - if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) { - RequiredAlignment[Index1] = GetRequiredAlignment (FileData[Index1].FileAttributes); - } - // - // If update file, mark the original file header to - // EFI_FILE_MARKED_FOR_UPDATE - // - IsCreateFile = FileOperation[Index1]; - if (!IsCreateFile) { - - Key = 0; - do { - OldFileType = 0; - Status = Fv->GetNextFile ( - Fv, - &Key, - &OldFileType, - &FileNameGuid, - &OldFileAttributes, - &OldFileSize - ); - if (EFI_ERROR (Status)) { - FreeFfsBuffer (NumOfFiles, FfsBuffer); - return Status; - } - } while (!CompareGuid (&FileNameGuid, FileData[Index1].NameGuid)); - - // - // Get FfsFileEntry from the search key - // - OldFfsFileEntry[Index1] = (FFS_FILE_LIST_ENTRY *) Key; - OldFileHeader[Index1] = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry[Index1]->FfsHeader; - Status = UpdateHeaderBit ( - FvDevice, - OldFileHeader[Index1], - EFI_FILE_MARKED_FOR_UPDATE - ); - if (EFI_ERROR (Status)) { - FreeFfsBuffer (NumOfFiles, FfsBuffer); - return Status; - } - } - } - // - // First to search a suitable pad file that can hold so - // many files - // - Status = FvSearchSuitablePadFile ( - FvDevice, - NumOfFiles, - BufferSize, - RequiredAlignment, - PadSize, - &TotalSizeNeeded, - &PadFileEntry - ); - - if (Status == EFI_NOT_FOUND) { - // - // Try to find a free space that can hold these files - // - Status = FvSearchSuitableFreeSpace ( - FvDevice, - NumOfFiles, - BufferSize, - RequiredAlignment, - PadSize, - &TotalSizeNeeded, - &FreeSpaceEntry - ); - if (EFI_ERROR (Status)) { - FreeFfsBuffer (NumOfFiles, FfsBuffer); - return EFI_OUT_OF_RESOURCES; - } - Status = FvCreateMultipleFilesInsideFreeSpace ( - FvDevice, - FreeSpaceEntry, - NumOfFiles, - BufferSize, - ActualFileSize, - PadSize, - FfsBuffer, - FileData - ); - - } else { - // - // Create multiple files inside such a pad file - // to achieve lock-step update - // - Status = FvCreateMultipleFilesInsidePadFile ( - FvDevice, - PadFileEntry, - NumOfFiles, - BufferSize, - ActualFileSize, - PadSize, - FfsBuffer, - FileData - ); - } - - FreeFfsBuffer (NumOfFiles, FfsBuffer); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Delete those updated files - // - for (Index1 = 0; Index1 < NumOfFiles; Index1++) { - IsCreateFile = FileOperation[Index1]; - if (!IsCreateFile && OldFfsFileEntry[Index1] != NULL) { - (OldFfsFileEntry[Index1]->Link.BackLink)->ForwardLink = OldFfsFileEntry[Index1]->Link.ForwardLink; - (OldFfsFileEntry[Index1]->Link.ForwardLink)->BackLink = OldFfsFileEntry[Index1]->Link.BackLink; - FreePool (OldFfsFileEntry[Index1]); - } - } - // - // Set those files' state to EFI_FILE_DELETED - // - for (Index1 = 0; Index1 < NumOfFiles; Index1++) { - IsCreateFile = FileOperation[Index1]; - if (!IsCreateFile && OldFileHeader[Index1] != NULL) { - Status = UpdateHeaderBit (FvDevice, OldFileHeader[Index1], EFI_FILE_DELETED); - if (EFI_ERROR (Status)) { - return Status; - } - } - } - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c deleted file mode 100644 index 2ba09c49b5..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c +++ /dev/null @@ -1,798 +0,0 @@ -/** @file - - Firmware File System driver that produce full Firmware Volume2 protocol. - Layers on top of Firmware Block protocol to produce a file abstraction - of FV based files. - - 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 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 "FwVolDriver.h" - -#define KEYSIZE sizeof (UINTN) - -/** - Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and - copy the real length volume header into it. - - @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to - read the volume header - @param FwVolHeader Pointer to pointer to allocated buffer in which - the volume header is returned. - - @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. - @retval EFI_SUCCESS Successfully read volume header to the allocated - buffer. - @retval EFI_ACCESS_DENIED Read status of FV is not enabled. - @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or - the file system could not be understood. -**/ -EFI_STATUS -GetFwVolHeader ( - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, - OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_HEADER TempFvh; - EFI_FVB_ATTRIBUTES_2 FvbAttributes; - UINTN FvhLength; - EFI_PHYSICAL_ADDRESS BaseAddress; - - // - // Determine the real length of FV header - // - Status = Fvb->GetAttributes ( - Fvb, - &FvbAttributes - ); - if (EFI_ERROR (Status)) { - return Status; - } - - if ((FvbAttributes & EFI_FVB2_READ_STATUS) == 0) { - return EFI_ACCESS_DENIED; - } - - // - // Just avoid compiling warning - // - BaseAddress = 0; - FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER); - - // - // memory-mapped FV and non memory-mapped has different ways to read - // - if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { - Status = Fvb->GetPhysicalAddress ( - Fvb, - &BaseAddress - ); - if (EFI_ERROR (Status)) { - return Status; - } - CopyMem (&TempFvh, (VOID *) (UINTN) BaseAddress, FvhLength); - } else { - Status = Fvb->Read ( - Fvb, - 0, - 0, - &FvhLength, - (UINT8 *) &TempFvh - ); - } - - // - // Validate FV Header signature, if not as expected, continue. - // - if (TempFvh.Signature != EFI_FVH_SIGNATURE) { - return EFI_INVALID_PARAMETER; - } - - // - // Check to see that the file system is indeed formatted in a way we can - // understand it... - // - if ((!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) && - (!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) { - return EFI_INVALID_PARAMETER; - } - - *FwVolHeader = AllocatePool (TempFvh.HeaderLength); - if (*FwVolHeader == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // Read the whole header - // - if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { - CopyMem (*FwVolHeader, (VOID *) (UINTN) BaseAddress, TempFvh.HeaderLength); - } else { - // - // Assumed the first block is bigger than the length of Fv headder - // - FvhLength = TempFvh.HeaderLength; - Status = Fvb->Read ( - Fvb, - 0, - 0, - &FvhLength, - (UINT8 *) *FwVolHeader - ); - // - // Check whether Read successes. - // - if (EFI_ERROR (Status)) { - FreePool (*FwVolHeader); - *FwVolHeader = NULL; - return Status; - } - } - - return EFI_SUCCESS; -} - -/** - Free FvDevice resource when error happens. - - @param FvDevice Pointer to the FvDevice to be freed. -**/ -VOID -FreeFvDeviceResource ( - IN FV_DEVICE *FvDevice - ) -{ - LBA_ENTRY *LbaEntry; - FREE_SPACE_ENTRY *FreeSpaceEntry; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - LIST_ENTRY *NextEntry; - - // - // Free LAB Entry - // - LbaEntry = (LBA_ENTRY *) FvDevice->LbaHeader.ForwardLink; - while (&LbaEntry->Link != &FvDevice->LbaHeader) { - NextEntry = (&LbaEntry->Link)->ForwardLink; - FreePool (LbaEntry); - LbaEntry = (LBA_ENTRY *) NextEntry; - } - // - // Free File List Entry - // - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink; - while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) { - NextEntry = (&FfsFileEntry->Link)->ForwardLink; - FreePool (FfsFileEntry); - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry; - } - // - // Free Space Entry - // - FreeSpaceEntry = (FREE_SPACE_ENTRY *) FvDevice->FreeSpaceHeader.ForwardLink; - while (&FreeSpaceEntry->Link != &FvDevice->FreeSpaceHeader) { - NextEntry = (&FreeSpaceEntry->Link)->ForwardLink; - FreePool (FreeSpaceEntry); - FreeSpaceEntry = (FREE_SPACE_ENTRY *) NextEntry; - } - // - // Free the cache - // - FreePool ((UINT8 *) (UINTN) FvDevice->CachedFv); - - return ; -} - -/** - - Firmware volume inherits authentication status from the FV image file and section(in another firmware volume) - where it came from. - - @param FvDevice A pointer to the FvDevice. - -**/ -VOID -FwVolInheritAuthenticationStatus ( - IN FV_DEVICE *FvDevice - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_HEADER *CachedFvHeader; - EFI_FIRMWARE_VOLUME_EXT_HEADER *CachedFvExtHeader; - EFI_FIRMWARE_VOLUME2_PROTOCOL *ParentFvProtocol; - UINTN Key; - EFI_GUID FileNameGuid; - EFI_FV_FILETYPE FileType; - EFI_FV_FILE_ATTRIBUTES FileAttributes; - UINTN FileSize; - EFI_SECTION_TYPE SectionType; - UINT32 AuthenticationStatus; - EFI_FIRMWARE_VOLUME_HEADER *FvHeader; - EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; - UINTN BufferSize; - - CachedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvDevice->CachedFv; - - if (FvDevice->Fv.ParentHandle != NULL) { - // - // By Parent Handle, find out the FV image file and section(in another firmware volume) where the firmware volume came from - // - Status = gBS->HandleProtocol (FvDevice->Fv.ParentHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &ParentFvProtocol); - if (!EFI_ERROR (Status) && (ParentFvProtocol != NULL)) { - Key = 0; - do { - FileType = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE; - Status = ParentFvProtocol->GetNextFile ( - ParentFvProtocol, - &Key, - &FileType, - &FileNameGuid, - &FileAttributes, - &FileSize - ); - if (EFI_ERROR (Status)) { - return; - } - - SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; - FvHeader = NULL; - BufferSize = 0; - Status = ParentFvProtocol->ReadSection ( - ParentFvProtocol, - &FileNameGuid, - SectionType, - 0, - (VOID **) &FvHeader, - &BufferSize, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - if ((FvHeader->FvLength == CachedFvHeader->FvLength) && - (FvHeader->ExtHeaderOffset == CachedFvHeader->ExtHeaderOffset)) { - if (FvHeader->ExtHeaderOffset !=0) { - // - // Both FVs contain extension header, then compare their FV Name GUID - // - FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) FvHeader + FvHeader->ExtHeaderOffset); - CachedFvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) CachedFvHeader + CachedFvHeader->ExtHeaderOffset); - if (CompareGuid (&FvExtHeader->FvName, &CachedFvExtHeader->FvName)) { - // - // Found the FV image section where the firmware volume came from, - // and then inherit authentication status from it. - // - FvDevice->AuthenticationStatus = AuthenticationStatus; - FreePool ((VOID *) FvHeader); - return; - } - } else { - // - // Both FVs don't contain extension header, then compare their whole FV Image. - // - if (CompareMem ((VOID *) FvHeader, (VOID *) CachedFvHeader, (UINTN) FvHeader->FvLength) == 0) { - // - // Found the FV image section where the firmware volume came from - // and then inherit authentication status from it. - // - FvDevice->AuthenticationStatus = AuthenticationStatus; - FreePool ((VOID *) FvHeader); - return; - } - } - } - FreePool ((VOID *) FvHeader); - } - } while (TRUE); - } - } -} - -/** - Check if an FV is consistent and allocate cache for it. - - @param FvDevice A pointer to the FvDevice to be checked. - - @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. - @retval EFI_VOLUME_CORRUPTED File system is corrupted. - @retval EFI_SUCCESS FV is consistent and cache is allocated. - -**/ -EFI_STATUS -FvCheck ( - IN FV_DEVICE *FvDevice - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - EFI_FVB_ATTRIBUTES_2 FvbAttributes; - EFI_FV_BLOCK_MAP_ENTRY *BlockMap; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; - UINT8 *FwCache; - LBA_ENTRY *LbaEntry; - FREE_SPACE_ENTRY *FreeSpaceEntry; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - UINT8 *LbaStart; - UINTN Index; - EFI_LBA LbaIndex; - UINT8 *Ptr; - UINTN Size; - UINT8 *FreeStart; - UINTN FreeSize; - UINT8 ErasePolarity; - EFI_FFS_FILE_STATE FileState; - UINT8 *TopFvAddress; - UINTN TestLength; - EFI_PHYSICAL_ADDRESS BaseAddress; - - Fvb = FvDevice->Fvb; - - Status = Fvb->GetAttributes (Fvb, &FvbAttributes); - if (EFI_ERROR (Status)) { - return Status; - } - - InitializeListHead (&FvDevice->LbaHeader); - InitializeListHead (&FvDevice->FreeSpaceHeader); - InitializeListHead (&FvDevice->FfsFileListHeader); - - FwVolHeader = NULL; - Status = GetFwVolHeader (Fvb, &FwVolHeader); - if (EFI_ERROR (Status)) { - return Status; - } - ASSERT (FwVolHeader != NULL); - - FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); - - // - // Double Check firmware volume header here - // - if (!VerifyFvHeaderChecksum (FwVolHeader)) { - FreePool (FwVolHeader); - return EFI_VOLUME_CORRUPTED; - } - - BlockMap = FwVolHeader->BlockMap; - - // - // FwVolHeader->FvLength is the whole FV length including FV header - // - FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength); - if (FwCache == NULL) { - FreePool (FwVolHeader); - return EFI_OUT_OF_RESOURCES; - } - - FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache; - - // - // Copy to memory - // - LbaStart = FwCache; - LbaIndex = 0; - Ptr = NULL; - - if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { - // - // Get volume base address - // - Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress); - if (EFI_ERROR (Status)) { - FreePool (FwVolHeader); - return Status; - } - - Ptr = (UINT8 *) ((UINTN) BaseAddress); - - DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress)); - } - // - // Copy whole FV into the memory - // - while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { - - for (Index = 0; Index < BlockMap->NumBlocks; Index++) { - LbaEntry = AllocatePool (sizeof (LBA_ENTRY)); - if (LbaEntry == NULL) { - FreePool (FwVolHeader); - FreeFvDeviceResource (FvDevice); - return EFI_OUT_OF_RESOURCES; - } - - LbaEntry->LbaIndex = LbaIndex; - LbaEntry->StartingAddress = LbaStart; - LbaEntry->BlockLength = BlockMap->Length; - - // - // Copy each LBA into memory - // - if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { - - CopyMem (LbaStart, Ptr, BlockMap->Length); - Ptr += BlockMap->Length; - - } else { - - Size = BlockMap->Length; - Status = Fvb->Read ( - Fvb, - LbaIndex, - 0, - &Size, - LbaStart - ); - // - // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length - // - if (EFI_ERROR (Status)) { - FreePool (FwVolHeader); - FreeFvDeviceResource (FvDevice); - return Status; - } - - } - - LbaIndex++; - LbaStart += BlockMap->Length; - - InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link); - } - - BlockMap++; - } - - FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache; - - // - // it is not used any more, so free FwVolHeader - // - FreePool (FwVolHeader); - - // - // Scan to check the free space & File list - // - if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) { - ErasePolarity = 1; - } else { - ErasePolarity = 0; - } - - FvDevice->ErasePolarity = ErasePolarity; - - // - // go through the whole FV cache, check the consistence of the FV - // - if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) { - // - // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. - // - FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset); - Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize; - Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8); - } else { - Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength); - } - TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength); - - // - // Build FFS list & Free Space List here - // - while (Ptr < TopFvAddress) { - TestLength = TopFvAddress - Ptr; - - if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { - TestLength = sizeof (EFI_FFS_FILE_HEADER); - } - - if (IsBufferErased (ErasePolarity, Ptr, TestLength)) { - // - // We found free space - // - FreeStart = Ptr; - FreeSize = 0; - - do { - TestLength = TopFvAddress - Ptr; - - if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { - TestLength = sizeof (EFI_FFS_FILE_HEADER); - } - - if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) { - break; - } - - FreeSize += TestLength; - Ptr += TestLength; - } while (Ptr < TopFvAddress); - - FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY)); - if (FreeSpaceEntry == NULL) { - FreeFvDeviceResource (FvDevice); - return EFI_OUT_OF_RESOURCES; - } - // - // Create a Free space entry - // - FreeSpaceEntry->StartingAddress = FreeStart; - FreeSpaceEntry->Length = FreeSize; - InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link); - continue; - } - // - // double check boundry - // - if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) { - break; - } - - if (!IsValidFFSHeader ( - FvDevice->ErasePolarity, - (EFI_FFS_FILE_HEADER *) Ptr - )) { - FileState = GetFileState ( - FvDevice->ErasePolarity, - (EFI_FFS_FILE_HEADER *) Ptr - ); - if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { - if (IS_FFS_FILE2 (Ptr)) { - if (!FvDevice->IsFfs3Fv) { - DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name)); - } - Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2); - } else { - Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER); - } - - continue; - - } else { - // - // File system is corrputed, return - // - FreeFvDeviceResource (FvDevice); - return EFI_VOLUME_CORRUPTED; - } - } - - if (IS_FFS_FILE2 (Ptr)) { - ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF); - if (!FvDevice->IsFfs3Fv) { - DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name)); - Ptr = Ptr + FFS_FILE2_SIZE (Ptr); - // - // Adjust Ptr to the next 8-byte aligned boundry. - // - while (((UINTN) Ptr & 0x07) != 0) { - Ptr++; - } - continue; - } - } - - if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) { - FileState = GetFileState ( - FvDevice->ErasePolarity, - (EFI_FFS_FILE_HEADER *) Ptr - ); - - // - // check for non-deleted file - // - if (FileState != EFI_FILE_DELETED) { - // - // Create a FFS list entry for each non-deleted file - // - FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); - if (FfsFileEntry == NULL) { - FreeFvDeviceResource (FvDevice); - return EFI_OUT_OF_RESOURCES; - } - - FfsFileEntry->FfsHeader = Ptr; - InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); - } - - if (IS_FFS_FILE2 (Ptr)) { - Ptr = Ptr + FFS_FILE2_SIZE (Ptr); - } else { - Ptr = Ptr + FFS_FILE_SIZE (Ptr); - } - - // - // Adjust Ptr to the next 8-byte aligned boundry. - // - while (((UINTN) Ptr & 0x07) != 0) { - Ptr++; - } - } else { - // - // File system is corrupted, return - // - FreeFvDeviceResource (FvDevice); - return EFI_VOLUME_CORRUPTED; - } - } - - FvDevice->CurrentFfsFile = NULL; - - return EFI_SUCCESS; -} - -/** - Entry point function does install/reinstall FV2 protocol with full functionality. - - @param ImageHandle A handle for the image that is initializing this driver - @param SystemTable A pointer to the EFI system table - - @retval EFI_SUCCESS At least one Fv protocol install/reinstall successfully. - @retval EFI_NOT_FOUND No FV protocol install/reinstall successfully. -**/ -EFI_STATUS -EFIAPI -FwVolDriverInit ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_HANDLE *HandleBuffer; - UINTN HandleCount; - UINTN Index; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; - FV_DEVICE *FvDevice; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - BOOLEAN Reinstall; - BOOLEAN InstallFlag; - - DEBUG ((EFI_D_INFO, "=========FwVol writable driver installed\n")); - InstallFlag = FALSE; - // - // Locate all handles of Fvb protocol - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiFirmwareVolumeBlockProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - - for (Index = 0; Index < HandleCount; Index += 1) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiFirmwareVolumeBlockProtocolGuid, - (VOID **) &Fvb - ); - if (EFI_ERROR (Status)) { - continue; - } - - FwVolHeader = NULL; - Status = GetFwVolHeader (Fvb, &FwVolHeader); - if (EFI_ERROR (Status)) { - continue; - } - ASSERT (FwVolHeader != NULL); - FreePool (FwVolHeader); - - Reinstall = FALSE; - // - // Check if there is an FV protocol already installed in that handle - // - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiFirmwareVolume2ProtocolGuid, - (VOID **) &Fv - ); - if (!EFI_ERROR (Status)) { - Reinstall = TRUE; - } - // - // FwVol protocol on the handle so create a new one - // - FvDevice = AllocateZeroPool (sizeof (FV_DEVICE)); - if (FvDevice == NULL) { - goto Done; - } - - FvDevice->Signature = FV_DEVICE_SIGNATURE; - FvDevice->Fvb = Fvb; - - // - // Firmware Volume Protocol interface - // - FvDevice->Fv.GetVolumeAttributes = FvGetVolumeAttributes; - FvDevice->Fv.SetVolumeAttributes = FvSetVolumeAttributes; - FvDevice->Fv.ReadFile = FvReadFile; - FvDevice->Fv.ReadSection = FvReadFileSection; - FvDevice->Fv.WriteFile = FvWriteFile; - FvDevice->Fv.GetNextFile = FvGetNextFile; - FvDevice->Fv.KeySize = KEYSIZE; - FvDevice->Fv.GetInfo = FvGetVolumeInfo; - FvDevice->Fv.SetInfo = FvSetVolumeInfo; - FvDevice->Fv.ParentHandle = Fvb->ParentHandle; - - Status = FvCheck (FvDevice); - if (EFI_ERROR (Status)) { - // - // The file system is not consistence - // - FreePool (FvDevice); - continue; - } - - FwVolInheritAuthenticationStatus (FvDevice); - - if (Reinstall) { - // - // Reinstall an New FV protocol - // - // FvDevice = FV_DEVICE_FROM_THIS (Fv); - // FvDevice->Fvb = Fvb; - // FreeFvDeviceResource (FvDevice); - // - Status = gBS->ReinstallProtocolInterface ( - HandleBuffer[Index], - &gEfiFirmwareVolume2ProtocolGuid, - Fv, - &FvDevice->Fv - ); - if (!EFI_ERROR (Status)) { - InstallFlag = TRUE; - } else { - FreePool (FvDevice); - } - - DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status)); - ASSERT_EFI_ERROR (Status); - } else { - // - // Install an New FV protocol - // - Status = gBS->InstallProtocolInterface ( - &FvDevice->Handle, - &gEfiFirmwareVolume2ProtocolGuid, - EFI_NATIVE_INTERFACE, - &FvDevice->Fv - ); - if (!EFI_ERROR (Status)) { - InstallFlag = TRUE; - } else { - FreePool (FvDevice); - } - - DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status)); - ASSERT_EFI_ERROR (Status); - } - } - -Done: - // - // As long as one Fv protocol install/reinstall successfully, - // success should return to ensure this image will be not unloaded. - // Otherwise, new Fv protocols are corrupted by other loaded driver. - // - if (InstallFlag) { - return EFI_SUCCESS; - } - - // - // No FV protocol install/reinstall successfully. - // EFI_NOT_FOUND should return to ensure this image will be unloaded. - // - return EFI_NOT_FOUND; -} diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolAttrib.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolAttrib.c deleted file mode 100644 index 0e4ddf8bea..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolAttrib.c +++ /dev/null @@ -1,220 +0,0 @@ -/** @file - - Implements get/set firmware volume attributes. - - Copyright (c) 2006 - 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 "FwVolDriver.h" - -/** - Retrieves attributes, insures positive polarity of attribute bits, returns - resulting attributes in output parameter. - - @param This Calling context - @param Attributes output buffer which contains attributes - - @retval EFI_SUCCESS Successfully got volume attributes - -**/ -EFI_STATUS -EFIAPI -FvGetVolumeAttributes ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - OUT EFI_FV_ATTRIBUTES *Attributes - ) -{ - EFI_STATUS Status; - FV_DEVICE *FvDevice; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - EFI_FVB_ATTRIBUTES_2 FvbAttributes; - - FvDevice = FV_DEVICE_FROM_THIS (This); - Fvb = FvDevice->Fvb; - - // - // First get the Firmware Volume Block Attributes - // - Status = Fvb->GetAttributes (Fvb, &FvbAttributes); - FvbAttributes &= 0xfffff0ff; - - *Attributes = FvbAttributes; - *Attributes |= EFI_FV2_WRITE_POLICY_RELIABLE; - return Status; -} - -/** - Sets current attributes for volume. - - @param This Calling context - @param Attributes On input, FvAttributes is a pointer to - an EFI_FV_ATTRIBUTES containing the - desired firmware volume settings. On - successful return, it contains the new - settings of the firmware volume. On - unsuccessful return, FvAttributes is not - modified and the firmware volume - settings are not changed. - - @retval EFI_SUCCESS The requested firmware volume attributes - were set and the resulting - EFI_FV_ATTRIBUTES is returned in - FvAttributes. - @retval EFI_ACCESS_DENIED Atrribute is locked down. - @retval EFI_INVALID_PARAMETER Atrribute is not valid. - -**/ -EFI_STATUS -EFIAPI -FvSetVolumeAttributes ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN OUT EFI_FV_ATTRIBUTES *Attributes - ) -{ - EFI_STATUS Status; - FV_DEVICE *FvDevice; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - EFI_FVB_ATTRIBUTES_2 OldFvbAttributes; - EFI_FVB_ATTRIBUTES_2 NewFvbAttributes; - UINT64 NewStatus; - UINT32 Capabilities; - - FvDevice = FV_DEVICE_FROM_THIS (This); - Fvb = FvDevice->Fvb; - - // - // First get the current Volume Attributes - // - Status = Fvb->GetAttributes ( - Fvb, - &OldFvbAttributes - ); - - if ((OldFvbAttributes & EFI_FVB2_LOCK_STATUS) != 0) { - return EFI_ACCESS_DENIED; - } - // - // Only status attributes can be updated. - // - Capabilities = OldFvbAttributes & EFI_FVB2_CAPABILITIES; - NewStatus = (*Attributes) & EFI_FVB2_STATUS; - - // - // 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) != 0) { - 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) != 0) { - return EFI_INVALID_PARAMETER; - } - } - // - // Test lock - // - if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { - if ((NewStatus & EFI_FVB2_LOCK_STATUS) != 0) { - return EFI_INVALID_PARAMETER; - } - } - - NewFvbAttributes = OldFvbAttributes & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); - NewFvbAttributes |= NewStatus; - Status = Fvb->SetAttributes ( - Fvb, - &NewFvbAttributes - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - *Attributes = 0; - - This->GetVolumeAttributes ( - This, - Attributes - ); - - return EFI_SUCCESS; -} - -/** - Return information of type InformationType for the requested firmware - volume. - - @param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL. - @param InformationType InformationType for requested. - @param BufferSize On input, size of Buffer.On output, the amount of - data returned in Buffer. - @param Buffer A poniter to the data buffer to return. - - @return EFI_UNSUPPORTED Could not get. - -**/ -EFI_STATUS -EFIAPI -FvGetVolumeInfo ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN CONST EFI_GUID *InformationType, - IN OUT UINTN *BufferSize, - OUT VOID *Buffer - ) -{ - return EFI_UNSUPPORTED; -} - -/** - Set information with InformationType into the requested firmware volume. - - @param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL. - @param InformationType InformationType for requested. - @param BufferSize Size of Buffer data. - @param Buffer A poniter to the data buffer to be set. - - @retval EFI_UNSUPPORTED Could not set. - -**/ -EFI_STATUS -EFIAPI -FvSetVolumeInfo ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN CONST EFI_GUID *InformationType, - IN UINTN BufferSize, - IN CONST VOID *Buffer - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDriver.h b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDriver.h deleted file mode 100644 index b1646dd39e..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDriver.h +++ /dev/null @@ -1,761 +0,0 @@ -/** @file - Common defines and definitions for a FwVolDxe driver. - - Copyright (c) 2006 - 2015, Intel 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 _FWVOL_DRIVER_H_ -#define _FWVOL_DRIVER_H_ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define FV_DEVICE_SIGNATURE SIGNATURE_32 ('_', 'F', 'V', '_') - -// -// 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) - -#define MAX_FILES 32 - -// -// Used to calculate from address -> Lba -// -typedef struct { - LIST_ENTRY Link; - EFI_LBA LbaIndex; - UINT8 *StartingAddress; - UINTN BlockLength; -} LBA_ENTRY; - -// -// Used to track free space in the Fv -// -typedef struct { - LIST_ENTRY Link; - UINT8 *StartingAddress; - UINTN Length; -} FREE_SPACE_ENTRY; - -// -// Used to track all non-deleted files -// -typedef struct { - LIST_ENTRY Link; - UINT8 *FfsHeader; -} FFS_FILE_LIST_ENTRY; - -typedef struct { - UINTN Signature; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - EFI_FIRMWARE_VOLUME2_PROTOCOL Fv; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - UINT8 *Key; - EFI_HANDLE Handle; - - UINT8 ErasePolarity; - EFI_PHYSICAL_ADDRESS CachedFv; - LIST_ENTRY LbaHeader; - LIST_ENTRY FreeSpaceHeader; - LIST_ENTRY FfsFileListHeader; - - FFS_FILE_LIST_ENTRY *CurrentFfsFile; - BOOLEAN IsFfs3Fv; - UINT32 AuthenticationStatus; -} FV_DEVICE; - -#define FV_DEVICE_FROM_THIS(a) CR (a, FV_DEVICE, Fv, FV_DEVICE_SIGNATURE) - -/** - Retrieves attributes, insures positive polarity of attribute bits, returns - resulting attributes in output parameter. - - @param This Calling context - @param Attributes output buffer which contains attributes - - @retval EFI_SUCCESS Successfully got volume attributes - -**/ -EFI_STATUS -EFIAPI -FvGetVolumeAttributes ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - OUT EFI_FV_ATTRIBUTES *Attributes - ); - -/** - Sets current attributes for volume. - - @param This Calling context - @param Attributes On input, FvAttributes is a pointer to - an EFI_FV_ATTRIBUTES containing the - desired firmware volume settings. On - successful return, it contains the new - settings of the firmware volume. On - unsuccessful return, FvAttributes is not - modified and the firmware volume - settings are not changed. - - @retval EFI_SUCCESS The requested firmware volume attributes - were set and the resulting - EFI_FV_ATTRIBUTES is returned in - FvAttributes. - @retval EFI_ACCESS_DENIED Atrribute is locked down. - @retval EFI_INVALID_PARAMETER Atrribute is not valid. - -**/ -EFI_STATUS -EFIAPI -FvSetVolumeAttributes ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN OUT EFI_FV_ATTRIBUTES *Attributes - ); - -/** - Given the input key, search for the next matching file in the volume. - - @param This Indicates the calling context. - @param Key Key is a pointer to a caller allocated - buffer that contains implementation specific - data that is used to track where to begin - the search for the next file. The size of - the buffer must be at least This->KeySize - bytes long. To reinitialize the search and - begin from the beginning of the firmware - volume, the entire buffer must be cleared to - zero. Other than clearing the buffer to - initiate a new search, the caller must not - modify the data in the buffer between calls - to GetNextFile(). - @param FileType FileType is a pointer to a caller allocated - EFI_FV_FILETYPE. The GetNextFile() API can - filter it's search for files based on the - value of *FileType input. A *FileType input - of 0 causes GetNextFile() to search for - files of all types. If a file is found, the - file's type is returned in *FileType. - *FileType is not modified if no file is - found. - @param NameGuid NameGuid is a pointer to a caller allocated - EFI_GUID. If a file is found, the file's - name is returned in *NameGuid. *NameGuid is - not modified if no file is found. - @param Attributes Attributes is a pointer to a caller - allocated EFI_FV_FILE_ATTRIBUTES. If a file - is found, the file's attributes are returned - in *Attributes. *Attributes is not modified - if no file is found. - @param Size Size is a pointer to a caller allocated - UINTN. If a file is found, the file's size - is returned in *Size. *Size is not modified - if no file is found. - - @retval EFI_SUCCESS Successfully find the file. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_ACCESS_DENIED Fv could not read. - @retval EFI_NOT_FOUND No matching file found. - @retval EFI_INVALID_PARAMETER Invalid parameter - -**/ -EFI_STATUS -EFIAPI -FvGetNextFile ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN OUT VOID *Key, - IN OUT EFI_FV_FILETYPE *FileType, - OUT EFI_GUID *NameGuid, - OUT EFI_FV_FILE_ATTRIBUTES *Attributes, - OUT UINTN *Size - ); - -/** - Locates a file in the firmware volume and - copies it to the supplied buffer. - - @param This Indicates the calling context. - @param NameGuid Pointer to an EFI_GUID, which is the - filename. - @param Buffer Buffer is a pointer to pointer to a buffer - in which the file or section contents or are - returned. - @param BufferSize BufferSize is a pointer to caller allocated - UINTN. On input *BufferSize indicates the - size in bytes of the memory region pointed - to by Buffer. On output, *BufferSize - contains the number of bytes required to - read the file. - @param FoundType FoundType is a pointer to a caller allocated - EFI_FV_FILETYPE that on successful return - from Read() contains the type of file read. - This output reflects the file type - irrespective of the value of the SectionType - input. - @param FileAttributes FileAttributes is a pointer to a caller - allocated EFI_FV_FILE_ATTRIBUTES. On - successful return from Read(), - *FileAttributes contains the attributes of - the file read. - @param AuthenticationStatus AuthenticationStatus is a pointer to a - caller allocated UINTN in which the - authentication status is returned. - - @retval EFI_SUCCESS Successfully read to memory buffer. - @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small. - @retval EFI_NOT_FOUND Not found. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_ACCESS_DENIED Could not read. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. - -**/ -EFI_STATUS -EFIAPI -FvReadFile ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN CONST EFI_GUID *NameGuid, - IN OUT VOID **Buffer, - IN OUT UINTN *BufferSize, - OUT EFI_FV_FILETYPE *FoundType, - OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, - OUT UINT32 *AuthenticationStatus - ); - -/** - Locates a section in a given FFS File and - copies it to the supplied buffer (not including section header). - - @param This Indicates the calling context. - @param NameGuid Pointer to an EFI_GUID, which is the - filename. - @param SectionType Indicates the section type to return. - @param SectionInstance Indicates which instance of sections with a - type of SectionType to return. - @param Buffer Buffer is a pointer to pointer to a buffer - in which the file or section contents or are - returned. - @param BufferSize BufferSize is a pointer to caller allocated - UINTN. - @param AuthenticationStatus AuthenticationStatus is a pointer to a - caller allocated UINT32 in which the - authentication status is returned. - - @retval EFI_SUCCESS Successfully read the file section into - buffer. - @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small. - @retval EFI_NOT_FOUND Section not found. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_ACCESS_DENIED Could not read. - @retval EFI_INVALID_PARAMETER Invalid parameter. - -**/ -EFI_STATUS -EFIAPI -FvReadFileSection ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN CONST EFI_GUID *NameGuid, - IN EFI_SECTION_TYPE SectionType, - IN UINTN SectionInstance, - IN OUT VOID **Buffer, - IN OUT UINTN *BufferSize, - OUT UINT32 *AuthenticationStatus - ); - -/** - Writes one or more files to the firmware volume. - - @param This Indicates the calling context. - @param NumberOfFiles Number of files. - @param WritePolicy WritePolicy indicates the level of reliability - for the write in the event of a power failure or - other system failure during the write operation. - @param FileData FileData is an pointer to an array of - EFI_FV_WRITE_DATA. Each element of array - FileData represents a file to be written. - - @retval EFI_SUCCESS Files successfully written to firmware volume - @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_WRITE_PROTECTED Write protected. - @retval EFI_NOT_FOUND Not found. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_UNSUPPORTED This function not supported. - -**/ -EFI_STATUS -EFIAPI -FvWriteFile ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN UINT32 NumberOfFiles, - IN EFI_FV_WRITE_POLICY WritePolicy, - IN EFI_FV_WRITE_FILE_DATA *FileData - ); - -/** - Return information of type InformationType for the requested firmware - volume. - - @param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL. - @param InformationType InformationType for requested. - @param BufferSize On input, size of Buffer.On output, the amount of - data returned in Buffer. - @param Buffer A poniter to the data buffer to return. - - @return EFI_UNSUPPORTED Could not get. - -**/ -EFI_STATUS -EFIAPI -FvGetVolumeInfo ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN CONST EFI_GUID *InformationType, - IN OUT UINTN *BufferSize, - OUT VOID *Buffer - ); - - -/** - Set information with InformationType into the requested firmware volume. - - @param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL. - @param InformationType InformationType for requested. - @param BufferSize Size of Buffer data. - @param Buffer A poniter to the data buffer to be set. - - @retval EFI_UNSUPPORTED Could not set. - -**/ -EFI_STATUS -EFIAPI -FvSetVolumeInfo ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN CONST EFI_GUID *InformationType, - IN UINTN BufferSize, - IN CONST VOID *Buffer - ); - -/** - Writes data beginning at Lba:Offset from FV. The write terminates either - when *NumBytes of data have been written, or when the firmware end is - reached. *NumBytes is updated to reflect the actual number of bytes - written. - - @param FvDevice Cached Firmware Volume - @param Offset Offset in the block at which to begin write - @param NumBytes At input, indicates the requested write size. - At output, indicates the actual number of bytes written. - @param Buffer Buffer containing source data for the write. - - @retval EFI_SUCCESS Data is successfully written into FV. - @return error Data is failed written. - -**/ -EFI_STATUS -FvcWrite ( - IN FV_DEVICE *FvDevice, - IN UINTN Offset, - IN OUT UINTN *NumBytes, - IN UINT8 *Buffer - ); - - -/** - Check if a block of buffer is erased. - - @param ErasePolarity Erase polarity attribute of the firmware volume - @param Buffer The buffer to be checked - @param BufferSize Size of the buffer in bytes - - @retval TRUE The block of buffer is erased - @retval FALSE The block of buffer is not erased - -**/ -BOOLEAN -IsBufferErased ( - IN UINT8 ErasePolarity, - IN UINT8 *Buffer, - IN UINTN BufferSize - ); - -/** - Get the FFS file state by checking the highest bit set in the header's state field. - - @param ErasePolarity Erase polarity attribute of the firmware volume - @param FfsHeader Points to the FFS file header - - @return FFS File state - -**/ -EFI_FFS_FILE_STATE -GetFileState ( - IN UINT8 ErasePolarity, - IN EFI_FFS_FILE_HEADER *FfsHeader - ); - -/** - Verify checksum of the firmware volume header. - - @param FvHeader Points to the firmware volume header to be checked - - @retval TRUE Checksum verification passed - @retval FALSE Checksum verification failed - -**/ -BOOLEAN -VerifyFvHeaderChecksum ( - IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader - ); - -/** - Check if it's a valid FFS file header. - - @param ErasePolarity Erase polarity attribute of the firmware volume - @param FfsHeader Points to the FFS file header to be checked - - @retval TRUE Valid FFS file header - @retval FALSE Invalid FFS file header - -**/ -BOOLEAN -IsValidFFSHeader ( - IN UINT8 ErasePolarity, - IN EFI_FFS_FILE_HEADER *FfsHeader - ); - -/** - Check if it's a valid FFS file. - Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first. - - @param FvDevice Cached FV image. - @param FfsHeader Points to the FFS file to be checked - - @retval TRUE Valid FFS file - @retval FALSE Invalid FFS file - -**/ -BOOLEAN -IsValidFFSFile ( - IN FV_DEVICE *FvDevice, - IN EFI_FFS_FILE_HEADER *FfsHeader - ); - -/** - Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and - copy the real length volume header into it. - - @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to - read the volume header - @param FwVolHeader Pointer to pointer to allocated buffer in which - the volume header is returned. - - @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. - @retval EFI_SUCCESS Successfully read volume header to the allocated - buffer. - @retval EFI_ACCESS_DENIED Read status of FV is not enabled. - @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or - the file system could not be understood. -**/ -EFI_STATUS -GetFwVolHeader ( - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, - OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader - ); - -/** - Convert the Buffer Address to LBA Entry Address. - - @param FvDevice Cached FvDevice - @param BufferAddress Address of Buffer - @param LbaListEntry Pointer to the got LBA entry that contains the address. - - @retval EFI_NOT_FOUND Buffer address is out of FvDevice. - @retval EFI_SUCCESS LBA entry is found for Buffer address. - -**/ -EFI_STATUS -Buffer2LbaEntry ( - IN FV_DEVICE *FvDevice, - IN EFI_PHYSICAL_ADDRESS BufferAddress, - OUT LBA_ENTRY **LbaListEntry - ); - -/** - Convert the Buffer Address to LBA Address & Offset. - - @param FvDevice Cached FvDevice - @param BufferAddress Address of Buffer - @param Lba Pointer to the gob Lba value - @param Offset Pointer to the got Offset - - @retval EFI_NOT_FOUND Buffer address is out of FvDevice. - @retval EFI_SUCCESS LBA and Offset is found for Buffer address. - -**/ -EFI_STATUS -Buffer2Lba ( - IN FV_DEVICE *FvDevice, - IN EFI_PHYSICAL_ADDRESS BufferAddress, - OUT EFI_LBA *Lba, - OUT UINTN *Offset - ); - -/** - Set File State in the FfsHeader. - - @param State File state to be set into FFS header. - @param FfsHeader Points to the FFS file header - -**/ -VOID -SetFileState ( - IN UINT8 State, - IN EFI_FFS_FILE_HEADER *FfsHeader - ); - -/** - Create a PAD File in the Free Space. - - @param FvDevice Firmware Volume Device. - @param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted. - @param Size Pad file Size, not include the header. - @param PadFileEntry The Ffs File Entry that points to this Pad File. - - @retval EFI_SUCCESS Successfully create a PAD file. - @retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file. - @retval EFI_INVALID_PARAMETER Size is not 8 byte alignment. - @retval EFI_DEVICE_ERROR Free space is not erased. -**/ -EFI_STATUS -FvCreatePadFileInFreeSpace ( - IN FV_DEVICE *FvDevice, - IN FREE_SPACE_ENTRY *FreeSpaceEntry, - IN UINTN Size, - OUT FFS_FILE_LIST_ENTRY **PadFileEntry - ); - -/** - Create a new file within a PAD file area. - - @param FvDevice Firmware Volume Device. - @param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state). - @param BufferSize The size of FfsFileBuffer. - @param ActualFileSize The actual file length, it may not be multiples of 8. - @param FileName The FFS File Name. - @param FileType The FFS File Type. - @param FileAttributes The Attributes of the FFS File to be created. - - @retval EFI_SUCCESS Successfully create a new file within the found PAD file area. - @retval EFI_OUT_OF_RESOURCES No suitable PAD file is found. - @retval other errors New file is created failed. - -**/ -EFI_STATUS -FvCreateNewFileInsidePadFile ( - IN FV_DEVICE *FvDevice, - IN UINT8 *FfsFileBuffer, - IN UINTN BufferSize, - IN UINTN ActualFileSize, - IN EFI_GUID *FileName, - IN EFI_FV_FILETYPE FileType, - IN EFI_FV_FILE_ATTRIBUTES FileAttributes - ); - -/** - Write multiple files into FV in reliable method. - - @param FvDevice Firmware Volume Device. - @param NumOfFiles Total File number to be written. - @param FileData The array of EFI_FV_WRITE_FILE_DATA structure, - used to get name, attributes, type, etc - @param FileOperation The array of operation for each file. - - @retval EFI_SUCCESS Files are added into FV. - @retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files. - @retval EFI_INVALID_PARAMETER File number is less than or equal to 1. - @retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files. - -**/ -EFI_STATUS -FvCreateMultipleFiles ( - IN FV_DEVICE *FvDevice, - IN UINTN NumOfFiles, - IN EFI_FV_WRITE_FILE_DATA *FileData, - IN BOOLEAN *FileOperation - ); - -/** - Calculate the checksum for the FFS header. - - @param FfsHeader FFS File Header which needs to calculate the checksum - -**/ -VOID -SetHeaderChecksum ( - IN EFI_FFS_FILE_HEADER *FfsHeader - ); - -/** - Calculate the checksum for the FFS File. - - @param FfsHeader FFS File Header which needs to calculate the checksum - @param ActualFileSize The whole Ffs File Length. - -**/ -VOID -SetFileChecksum ( - IN EFI_FFS_FILE_HEADER *FfsHeader, - IN UINTN ActualFileSize - ); - -/** - Get the alignment value from File Attributes. - - @param FfsAttributes FFS attribute - - @return Alignment value. - -**/ -UINTN -GetRequiredAlignment ( - IN EFI_FV_FILE_ATTRIBUTES FfsAttributes - ); - -/** - Locate Pad File for writing, this is got from FV Cache. - - @param FvDevice Cached Firmware Volume. - @param Size The required FFS file size. - @param RequiredAlignment FFS File Data alignment requirement. - @param PadSize Pointer to the size of leading Pad File. - @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. - - @retval EFI_SUCCESS The required pad file is found. - @retval EFI_NOT_FOUND The required pad file can't be found. - -**/ -EFI_STATUS -FvLocatePadFile ( - IN FV_DEVICE *FvDevice, - IN UINTN Size, - IN UINTN RequiredAlignment, - OUT UINTN *PadSize, - OUT FFS_FILE_LIST_ENTRY **PadFileEntry - ); - -/** - Locate a suitable pad file for multiple file writing. - - @param FvDevice Cached Firmware Volume. - @param NumOfFiles The number of Files that needed updating - @param BufferSize The array of each file size. - @param RequiredAlignment The array of of FFS File Data alignment requirement. - @param PadSize The array of size of each leading Pad File. - @param TotalSizeNeeded The totalsize that can hold these files. - @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. - - @retval EFI_SUCCESS The required pad file is found. - @retval EFI_NOT_FOUND The required pad file can't be found. - -**/ -EFI_STATUS -FvSearchSuitablePadFile ( - IN FV_DEVICE *FvDevice, - IN UINTN NumOfFiles, - IN UINTN *BufferSize, - IN UINTN *RequiredAlignment, - OUT UINTN *PadSize, - OUT UINTN *TotalSizeNeeded, - OUT FFS_FILE_LIST_ENTRY **PadFileEntry - ); - -/** - Locate a Free Space entry which can hold these files, including - meeting the alignment requirements. - - @param FvDevice Cached Firmware Volume. - @param NumOfFiles The number of Files that needed updating - @param BufferSize The array of each file size. - @param RequiredAlignment The array of of FFS File Data alignment requirement. - @param PadSize The array of size of each leading Pad File. - @param TotalSizeNeeded The got total size that can hold these files. - @param FreeSpaceEntry The Free Space Entry that can hold these files. - - @retval EFI_SUCCESS The free space entry is found. - @retval EFI_NOT_FOUND The free space entry can't be found. - -**/ -EFI_STATUS -FvSearchSuitableFreeSpace ( - IN FV_DEVICE *FvDevice, - IN UINTN NumOfFiles, - IN UINTN *BufferSize, - IN UINTN *RequiredAlignment, - OUT UINTN *PadSize, - OUT UINTN *TotalSizeNeeded, - OUT FREE_SPACE_ENTRY **FreeSpaceEntry - ); - -/** - Change FFS file header state and write to FV. - - @param FvDevice Cached FV image. - @param FfsHeader Points to the FFS file header to be updated. - @param State FFS file state to be set. - - @retval EFI_SUCCESS File state is writen into FV. - @retval others File state can't be writen into FV. - -**/ -EFI_STATUS -UpdateHeaderBit ( - IN FV_DEVICE *FvDevice, - IN EFI_FFS_FILE_HEADER *FfsHeader, - IN EFI_FFS_FILE_STATE State - ); - -/** - Convert EFI_FV_FILE_ATTRIBUTES to FFS_FILE_ATTRIBUTES. - - @param FvFileAttrib The value of EFI_FV_FILE_ATTRIBUTES - @param FfsFileAttrib Pointer to the got FFS_FILE_ATTRIBUTES value. - -**/ -VOID -FvFileAttrib2FfsFileAttrib ( - IN EFI_FV_FILE_ATTRIBUTES FvFileAttrib, - OUT UINT8 *FfsFileAttrib - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf deleted file mode 100644 index 057266bb2b..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf +++ /dev/null @@ -1,74 +0,0 @@ -## @file -# FwVolDxe Driver. -# -# This driver produces Firmware Volume2 protocol with full services -# (read/write, get/set) based on Firmware Volume Block 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 -# 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 = FwVolDxe - MODULE_UNI_FILE = FwVolDxe.uni - FILE_GUID = 233C2592-1CEC-494a-A097-15DC96379777 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - - ENTRY_POINT = FwVolDriverInit - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - FwVolDriver.h - FwPadFile.c - Ffs.c - FwVolWrite.c - FwVolRead.c - FwVolAttrib.c - FwVol.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - - -[LibraryClasses] - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - BaseLib - UefiLib - UefiDriverEntryPoint - DebugLib - - -[Guids] - gEfiFirmwareVolumeTopFileGuid ## CONSUMES ## File # VTF file - gEfiFirmwareFileSystem2Guid ## CONSUMES ## GUID # File System Guid - gEfiFirmwareFileSystem3Guid ## CONSUMES ## GUID # File System Guid - -[Protocols] - gEfiSectionExtractionProtocolGuid ## CONSUMES - gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES - gEfiFirmwareVolume2ProtocolGuid ## PRODUCES - -[Depex] - gEfiFirmwareVolumeBlockProtocolGuid AND gEfiSectionExtractionProtocolGuid - -[UserExtensions.TianoCore."ExtraFiles"] - FwVolDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni deleted file mode 100644 index 89e44a4471..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni deleted file mode 100644 index b008de7a93..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolRead.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolRead.c deleted file mode 100644 index 8e2706bb8a..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolRead.c +++ /dev/null @@ -1,629 +0,0 @@ -/** @file - Implements functions to read firmware file. - - 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 "FwVolDriver.h" - -/** -Required Alignment Alignment Value in FFS Alignment Value in -(bytes) Attributes Field Firmware Volume Interfaces -1 0 0 -16 1 4 -128 2 7 -512 3 9 -1 KB 4 10 -4 KB 5 12 -32 KB 6 15 -64 KB 7 16 -**/ -UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16}; - -/** - Convert the FFS File Attributes to FV File Attributes. - - @param FfsAttributes The attributes of UINT8 type. - - @return The attributes of EFI_FV_FILE_ATTRIBUTES - -**/ -EFI_FV_FILE_ATTRIBUTES -FfsAttributes2FvFileAttributes ( - IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes - ) -{ - UINT8 DataAlignment; - EFI_FV_FILE_ATTRIBUTES FileAttribute; - - DataAlignment = (UINT8) ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3); - ASSERT (DataAlignment < 8); - - FileAttribute = (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[DataAlignment]; - - if ((FfsAttributes & FFS_ATTRIB_FIXED) == FFS_ATTRIB_FIXED) { - FileAttribute |= EFI_FV_FILE_ATTRIB_FIXED; - } - - return FileAttribute; -} - -/** - Given the input key, search for the next matching file in the volume. - - @param This Indicates the calling context. - @param Key Key is a pointer to a caller allocated - buffer that contains implementation specific - data that is used to track where to begin - the search for the next file. The size of - the buffer must be at least This->KeySize - bytes long. To reinitialize the search and - begin from the beginning of the firmware - volume, the entire buffer must be cleared to - zero. Other than clearing the buffer to - initiate a new search, the caller must not - modify the data in the buffer between calls - to GetNextFile(). - @param FileType FileType is a pointer to a caller allocated - EFI_FV_FILETYPE. The GetNextFile() API can - filter it's search for files based on the - value of *FileType input. A *FileType input - of 0 causes GetNextFile() to search for - files of all types. If a file is found, the - file's type is returned in *FileType. - *FileType is not modified if no file is - found. - @param NameGuid NameGuid is a pointer to a caller allocated - EFI_GUID. If a file is found, the file's - name is returned in *NameGuid. *NameGuid is - not modified if no file is found. - @param Attributes Attributes is a pointer to a caller - allocated EFI_FV_FILE_ATTRIBUTES. If a file - is found, the file's attributes are returned - in *Attributes. *Attributes is not modified - if no file is found. - @param Size Size is a pointer to a caller allocated - UINTN. If a file is found, the file's size - is returned in *Size. *Size is not modified - if no file is found. - - @retval EFI_SUCCESS Successfully find the file. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_ACCESS_DENIED Fv could not read. - @retval EFI_NOT_FOUND No matching file found. - @retval EFI_INVALID_PARAMETER Invalid parameter - -**/ -EFI_STATUS -EFIAPI -FvGetNextFile ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN OUT VOID *Key, - IN OUT EFI_FV_FILETYPE *FileType, - OUT EFI_GUID *NameGuid, - OUT EFI_FV_FILE_ATTRIBUTES *Attributes, - OUT UINTN *Size - ) -{ - EFI_STATUS Status; - FV_DEVICE *FvDevice; - EFI_FV_ATTRIBUTES FvAttributes; - EFI_FFS_FILE_HEADER *FfsFileHeader; - UINTN *KeyValue; - LIST_ENTRY *Link; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - - FvDevice = FV_DEVICE_FROM_THIS (This); - - Status = This->GetVolumeAttributes (This, &FvAttributes); - if (EFI_ERROR (Status)) { - return Status; - } - - KeyValue = (UINTN *) Key; - FfsFileHeader = NULL; - - // - // Check if read operation is enabled - // - if ((FvAttributes & EFI_FV2_READ_STATUS) == 0) { - return EFI_ACCESS_DENIED; - } - - if (*FileType > EFI_FV_FILETYPE_SMM_CORE) { - // - // File type needs to be in 0 - 0x0D - // - return EFI_NOT_FOUND; - } - - do { - if (*KeyValue == 0) { - // - // Search for 1st matching file - // - Link = &FvDevice->FfsFileListHeader; - if (Link->ForwardLink == &FvDevice->FfsFileListHeader) { - return EFI_NOT_FOUND; - } - - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Link->ForwardLink; - FfsFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; - - // - // remember the key - // - *KeyValue = (UINTN) FfsFileEntry; - - // - // we ignore pad files - // - if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { - continue; - } - - if (*FileType == 0) { - break; - } - - if (*FileType == FfsFileHeader->Type) { - break; - } - - } else { - // - // Getting link from last Ffs - // - Link = (LIST_ENTRY *) (*KeyValue); - if (Link->ForwardLink == &FvDevice->FfsFileListHeader) { - return EFI_NOT_FOUND; - } - - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Link->ForwardLink; - FfsFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; - - // - // remember the key - // - *KeyValue = (UINTN) FfsFileEntry; - - // - // we ignore pad files - // - if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { - continue; - } - - if (*FileType == EFI_FV_FILETYPE_ALL) { - break; - } - - if (*FileType == FfsFileHeader->Type) { - break; - } - } - } while (Link->ForwardLink != &FvDevice->FfsFileListHeader); - - // - // Cache this file entry - // - FvDevice->CurrentFfsFile = FfsFileEntry; - - *FileType = FfsFileHeader->Type; - CopyGuid (NameGuid, &FfsFileHeader->Name); - *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes); - if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) { - *Attributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED; - } - - // - // we need to substract the header size - // - if (IS_FFS_FILE2 (FfsFileHeader)) { - *Size = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2); - } else { - *Size = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER); - } - - if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid, NameGuid)) { - // - // specially deal with VTF file - // - UINT8 *SrcPtr; - UINT32 Tmp; - - if (IS_FFS_FILE2 (FfsFileHeader)) { - SrcPtr = ((UINT8 *) FfsFileHeader) + sizeof (EFI_FFS_FILE_HEADER2); - } else { - SrcPtr = ((UINT8 *) FfsFileHeader) + sizeof (EFI_FFS_FILE_HEADER); - } - - while (*Size >= 4) { - Tmp = *(UINT32 *) SrcPtr; - if (Tmp == 0) { - SrcPtr += 4; - (*Size) -= 4; - } else { - break; - } - } - } - - return EFI_SUCCESS; -} - -/** - Locates a file in the firmware volume and - copies it to the supplied buffer. - - @param This Indicates the calling context. - @param NameGuid Pointer to an EFI_GUID, which is the - filename. - @param Buffer Buffer is a pointer to pointer to a buffer - in which the file or section contents or are - returned. - @param BufferSize BufferSize is a pointer to caller allocated - UINTN. On input *BufferSize indicates the - size in bytes of the memory region pointed - to by Buffer. On output, *BufferSize - contains the number of bytes required to - read the file. - @param FoundType FoundType is a pointer to a caller allocated - EFI_FV_FILETYPE that on successful return - from Read() contains the type of file read. - This output reflects the file type - irrespective of the value of the SectionType - input. - @param FileAttributes FileAttributes is a pointer to a caller - allocated EFI_FV_FILE_ATTRIBUTES. On - successful return from Read(), - *FileAttributes contains the attributes of - the file read. - @param AuthenticationStatus AuthenticationStatus is a pointer to a - caller allocated UINTN in which the - authentication status is returned. - - @retval EFI_SUCCESS Successfully read to memory buffer. - @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small. - @retval EFI_NOT_FOUND Not found. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_ACCESS_DENIED Could not read. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. - -**/ -EFI_STATUS -EFIAPI -FvReadFile ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN CONST EFI_GUID *NameGuid, - IN OUT VOID **Buffer, - IN OUT UINTN *BufferSize, - OUT EFI_FV_FILETYPE *FoundType, - OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, - OUT UINT32 *AuthenticationStatus - ) -{ - EFI_STATUS Status; - FV_DEVICE *FvDevice; - UINTN Key; - EFI_GUID SearchNameGuid; - EFI_FV_ATTRIBUTES FvAttributes; - EFI_FV_FILETYPE LocalFoundType; - EFI_FV_FILE_ATTRIBUTES LocalAttributes; - UINTN FileSize; - UINT8 *SrcPtr; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - EFI_FFS_FILE_HEADER *FfsHeader; - UINT8 *FileBuffer; - - if (NULL == This || NULL == NameGuid) { - return EFI_INVALID_PARAMETER; - } - - FvDevice = FV_DEVICE_FROM_THIS (This); - - Status = This->GetVolumeAttributes (This, &FvAttributes); - if (EFI_ERROR (Status)) { - return Status; - } - // - // First check to see that FV is enabled for reads... - // - if (0 == (FvAttributes & EFI_FV2_READ_STATUS)) { - return EFI_ACCESS_DENIED; - } - - FfsHeader = NULL; - - // - // Check if the file was read last time. - // - FfsFileEntry = FvDevice->CurrentFfsFile; - - if (FfsFileEntry != NULL) { - FfsHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; - } - - if ((FfsFileEntry == NULL) || (!CompareGuid (&FfsHeader->Name, NameGuid))) { - // - // If not match or no file cached, search this file - // - Key = 0; - do { - LocalFoundType = 0; - Status = This->GetNextFile ( - This, - &Key, - &LocalFoundType, - &SearchNameGuid, - &LocalAttributes, - &FileSize - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - } while (!CompareGuid (&SearchNameGuid, NameGuid)); - - // - // Get file entry - // - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key; - - // - // Update the cache - // - FvDevice->CurrentFfsFile = FfsFileEntry; - - FfsHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; - - } else { - // - // Get File Size of the cached file - // - if (IS_FFS_FILE2 (FfsHeader)) { - FileSize = FFS_FILE2_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER2); - } else { - FileSize = FFS_FILE_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER); - } - } - // - // Get file info - // - *FoundType = FfsHeader->Type; - *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes); - if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) { - *FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED; - } - *AuthenticationStatus = 0; - - // - // If Buffer is NULL, we only want to get some information - // - if (Buffer == NULL) { - *BufferSize = FileSize; - return EFI_SUCCESS; - } - - if (IS_FFS_FILE2 (FfsHeader)) { - SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2); - } else { - SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER); - } - - if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid, NameGuid)) { - // - // specially deal with VTF file - // - UINT32 Tmp; - - while (FileSize >= 4) { - Tmp = *(UINT32 *) SrcPtr; - if (Tmp == 0) { - SrcPtr += 4; - FileSize -= 4; - } else { - break; - } - } - } - // - // If we drop out of the above loop, we've found the correct file header... - // - if (*Buffer == NULL) { - FileBuffer = AllocateCopyPool (FileSize, SrcPtr); - if (FileBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - *BufferSize = FileSize; - *Buffer = FileBuffer; - - return EFI_SUCCESS; - } - // - // If the user's buffer is smaller than the file size, then copy as much - // as we can and return an appropriate status. - // - if (FileSize > *BufferSize) { - CopyMem (*Buffer, SrcPtr, *BufferSize); - *BufferSize = FileSize; - return EFI_WARN_BUFFER_TOO_SMALL; - } - // - // User's buffer size is ok, so copy the entire file to their buffer. - // - *BufferSize = FileSize; - CopyMem (*Buffer, SrcPtr, *BufferSize); - - return EFI_SUCCESS; -} - -/** - Locates a section in a given FFS File and - copies it to the supplied buffer (not including section header). - - @param This Indicates the calling context. - @param NameGuid Pointer to an EFI_GUID, which is the - filename. - @param SectionType Indicates the section type to return. - @param SectionInstance Indicates which instance of sections with a - type of SectionType to return. - @param Buffer Buffer is a pointer to pointer to a buffer - in which the file or section contents or are - returned. - @param BufferSize BufferSize is a pointer to caller allocated - UINTN. - @param AuthenticationStatus AuthenticationStatus is a pointer to a - caller allocated UINT32 in which the - authentication status is returned. - - @retval EFI_SUCCESS Successfully read the file section into - buffer. - @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small. - @retval EFI_NOT_FOUND Section not found. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_ACCESS_DENIED Could not read. - @retval EFI_INVALID_PARAMETER Invalid parameter. - -**/ -EFI_STATUS -EFIAPI -FvReadFileSection ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN CONST EFI_GUID *NameGuid, - IN EFI_SECTION_TYPE SectionType, - IN UINTN SectionInstance, - IN OUT VOID **Buffer, - IN OUT UINTN *BufferSize, - OUT UINT32 *AuthenticationStatus - ) -{ - EFI_STATUS Status; - FV_DEVICE *FvDevice; - EFI_FV_ATTRIBUTES FvAttributes; - EFI_FV_FILETYPE FileType; - EFI_FV_FILE_ATTRIBUTES FileAttributes; - UINTN FileSize; - UINT8 *FileBuffer; - EFI_SECTION_EXTRACTION_PROTOCOL *Sep; - UINTN StreamHandle; - - if (NULL == This || NULL == NameGuid || Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - FvDevice = FV_DEVICE_FROM_THIS (This); - - Status = This->GetVolumeAttributes (This, &FvAttributes); - if (EFI_ERROR (Status)) { - return Status; - } - // - // First check to see that FV is enabled for reads... - // - if (0 == (FvAttributes & EFI_FV2_READ_STATUS)) { - return EFI_ACCESS_DENIED; - } - // - // Read the whole file into buffer - // - FileBuffer = NULL; - Status = This->ReadFile ( - This, - NameGuid, - (VOID **) &FileBuffer, - &FileSize, - &FileType, - &FileAttributes, - AuthenticationStatus - ); - - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check to see that the file actually HAS sections before we go any further. - // - if (FileType == EFI_FV_FILETYPE_RAW) { - FreePool (FileBuffer); - return EFI_NOT_FOUND; - } - // - // Located the protocol - // - Status = gBS->LocateProtocol ( - &gEfiSectionExtractionProtocolGuid, - NULL, - (VOID **) &Sep - ); - if (EFI_ERROR (Status)) { - FreePool (FileBuffer); - return Status; - } - - Status = Sep->OpenSectionStream ( - Sep, - FileSize, - FileBuffer, - &StreamHandle - ); - - if (EFI_ERROR (Status)) { - FreePool (FileBuffer); - return Status; - } - - if (SectionType == 0) { - // - // We need the whole section stream - // - Status = Sep->GetSection ( - Sep, - StreamHandle, - NULL, - NULL, - 0, - Buffer, - BufferSize, - AuthenticationStatus - ); - } else { - Status = Sep->GetSection ( - Sep, - StreamHandle, - &SectionType, - NULL, - SectionInstance, - Buffer, - BufferSize, - AuthenticationStatus - ); - } - - if (!EFI_ERROR (Status)) { - // - // Inherit the authentication status. - // - *AuthenticationStatus |= FvDevice->AuthenticationStatus; - } - - // - // Handle AuthenticationStatus if necessary - // - Sep->CloseSectionStream (Sep, StreamHandle); - - FreePool (FileBuffer); - - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c deleted file mode 100644 index 7f23b51d83..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c +++ /dev/null @@ -1,1586 +0,0 @@ -/** @file - Implements write firmware file. - - Copyright (c) 2006 - 2015, Intel 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 "FwVolDriver.h" - -/** - Calculate the checksum for the FFS header. - - @param FfsHeader FFS File Header which needs to calculate the checksum - -**/ -VOID -SetHeaderChecksum ( - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - EFI_FFS_FILE_STATE State; - UINT8 FileChecksum; - - // - // The state and the File checksum are not included - // - State = FfsHeader->State; - FfsHeader->State = 0; - - FileChecksum = FfsHeader->IntegrityCheck.Checksum.File; - FfsHeader->IntegrityCheck.Checksum.File = 0; - - FfsHeader->IntegrityCheck.Checksum.Header = 0; - - if (IS_FFS_FILE2 (FfsHeader)) { - FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 ( - (UINT8 *) FfsHeader, - sizeof (EFI_FFS_FILE_HEADER2) - ); - } else { - FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 ( - (UINT8 *) FfsHeader, - sizeof (EFI_FFS_FILE_HEADER) - ); - } - - FfsHeader->State = State; - FfsHeader->IntegrityCheck.Checksum.File = FileChecksum; - - return ; -} - -/** - Calculate the checksum for the FFS File. - - @param FfsHeader FFS File Header which needs to calculate the checksum - @param ActualFileSize The whole Ffs File Length. - -**/ -VOID -SetFileChecksum ( - IN EFI_FFS_FILE_HEADER *FfsHeader, - IN UINTN ActualFileSize - ) -{ - if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) { - - FfsHeader->IntegrityCheck.Checksum.File = 0; - - if (IS_FFS_FILE2 (FfsHeader)) { - FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 ( - (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), - ActualFileSize - sizeof (EFI_FFS_FILE_HEADER2) - ); - } else { - FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 ( - (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), - ActualFileSize - sizeof (EFI_FFS_FILE_HEADER) - ); - } - - } else { - - FfsHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; - - } - - return ; -} - -/** - Get the alignment value from File Attributes. - - @param FfsAttributes FFS attribute - - @return Alignment value. - -**/ -UINTN -GetRequiredAlignment ( - IN EFI_FV_FILE_ATTRIBUTES FfsAttributes - ) -{ - UINTN AlignmentValue; - - AlignmentValue = FfsAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT; - - if (AlignmentValue <= 3) { - return 0x08; - } - - if (AlignmentValue > 16) { - // - // Anyway, we won't reach this code - // - return 0x08; - } - - return (UINTN)1 << AlignmentValue; - -} - -/** - Calculate the leading Pad file size to meet the alignment requirement. - - @param FvDevice Cached Firmware Volume. - @param StartAddress The starting address to write the FFS File. - @param BufferSize The FFS File Buffer Size. - @param RequiredAlignment FFS File Data alignment requirement. - - @return The required Pad File Size. - -**/ -UINTN -CalculatePadFileSize ( - IN FV_DEVICE *FvDevice, - IN EFI_PHYSICAL_ADDRESS StartAddress, - IN UINTN BufferSize, - IN UINTN RequiredAlignment - ) -{ - UINTN DataStartPos; - UINTN RelativePos; - UINTN PadSize; - - if (BufferSize > 0x00FFFFFF) { - DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER2); - } else { - DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER); - } - RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv; - - PadSize = 0; - - while ((RelativePos & (RequiredAlignment - 1)) != 0) { - RelativePos++; - PadSize++; - } - // - // If padsize is 0, no pad file needed; - // If padsize is great than 24, then pad file can be created - // - if ((PadSize == 0) || (PadSize >= sizeof (EFI_FFS_FILE_HEADER))) { - return PadSize; - } - - // - // Perhaps following method can save space - // - RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv + sizeof (EFI_FFS_FILE_HEADER); - PadSize = sizeof (EFI_FFS_FILE_HEADER); - - while ((RelativePos & (RequiredAlignment - 1)) != 0) { - RelativePos++; - PadSize++; - } - - return PadSize; -} - -/** - Convert EFI_FV_FILE_ATTRIBUTES to FFS_FILE_ATTRIBUTES. - - @param FvFileAttrib The value of EFI_FV_FILE_ATTRIBUTES - @param FfsFileAttrib Pointer to the got FFS_FILE_ATTRIBUTES value. - -**/ -VOID -FvFileAttrib2FfsFileAttrib ( - IN EFI_FV_FILE_ATTRIBUTES FvFileAttrib, - OUT UINT8 *FfsFileAttrib - ) -{ - UINT8 FvFileAlignment; - UINT8 FfsFileAlignment; - - FvFileAlignment = (UINT8) (FvFileAttrib & EFI_FV_FILE_ATTRIB_ALIGNMENT); - FfsFileAlignment = 0; - - switch (FvFileAlignment) { - case 0: - // - // fall through - // - case 1: - // - // fall through - // - case 2: - // - // fall through - // - case 3: - // - // fall through - // - FfsFileAlignment = 0; - break; - - case 4: - // - // fall through - // - case 5: - // - // fall through - // - case 6: - // - // fall through - // - FfsFileAlignment = 1; - break; - - case 7: - // - // fall through - // - case 8: - // - // fall through - // - FfsFileAlignment = 2; - break; - - case 9: - FfsFileAlignment = 3; - break; - - case 10: - // - // fall through - // - case 11: - // - // fall through - // - FfsFileAlignment = 4; - break; - - case 12: - // - // fall through - // - case 13: - // - // fall through - // - case 14: - // - // fall through - // - FfsFileAlignment = 5; - break; - - case 15: - FfsFileAlignment = 6; - break; - - case 16: - FfsFileAlignment = 7; - break; - } - - *FfsFileAttrib = (UINT8) (FfsFileAlignment << 3); - - return ; -} - -/** - Locate a free space entry that can hold this FFS file. - - @param FvDevice Cached Firmware Volume. - @param Size The FFS file size. - @param RequiredAlignment FFS File Data alignment requirement. - @param PadSize Pointer to the size of leading Pad File. - @param FreeSpaceEntry Pointer to the Free Space Entry that meets the requirement. - - @retval EFI_SUCCESS The free space entry is found. - @retval EFI_NOT_FOUND The free space entry can't be found. - -**/ -EFI_STATUS -FvLocateFreeSpaceEntry ( - IN FV_DEVICE *FvDevice, - IN UINTN Size, - IN UINTN RequiredAlignment, - OUT UINTN *PadSize, - OUT FREE_SPACE_ENTRY **FreeSpaceEntry - ) -{ - FREE_SPACE_ENTRY *FreeSpaceListEntry; - LIST_ENTRY *Link; - UINTN PadFileSize; - - Link = FvDevice->FreeSpaceHeader.ForwardLink; - FreeSpaceListEntry = (FREE_SPACE_ENTRY *) Link; - - // - // Loop the free space entry list to find one that can hold the - // required the file size - // - while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) { - PadFileSize = CalculatePadFileSize ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceListEntry->StartingAddress, - Size, - RequiredAlignment - ); - if (FreeSpaceListEntry->Length >= Size + PadFileSize) { - *FreeSpaceEntry = FreeSpaceListEntry; - *PadSize = PadFileSize; - return EFI_SUCCESS; - } - - FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink; - } - - return EFI_NOT_FOUND; - -} - -/** - Locate Pad File for writing, this is got from FV Cache. - - @param FvDevice Cached Firmware Volume. - @param Size The required FFS file size. - @param RequiredAlignment FFS File Data alignment requirement. - @param PadSize Pointer to the size of leading Pad File. - @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. - - @retval EFI_SUCCESS The required pad file is found. - @retval EFI_NOT_FOUND The required pad file can't be found. - -**/ -EFI_STATUS -FvLocatePadFile ( - IN FV_DEVICE *FvDevice, - IN UINTN Size, - IN UINTN RequiredAlignment, - OUT UINTN *PadSize, - OUT FFS_FILE_LIST_ENTRY **PadFileEntry - ) -{ - FFS_FILE_LIST_ENTRY *FileEntry; - EFI_FFS_FILE_STATE FileState; - EFI_FFS_FILE_HEADER *FileHeader; - UINTN PadAreaLength; - UINTN PadFileSize; - UINTN HeaderSize; - - FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink; - - // - // travel through the whole file list to get the pad file entry - // - while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) { - - FileHeader = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader; - FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); - - if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) { - // - // we find one valid pad file, check its free area length - // - if (IS_FFS_FILE2 (FileHeader)) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize; - } else { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize; - } - - PadFileSize = CalculatePadFileSize ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize, - Size, - RequiredAlignment - ); - if (PadAreaLength >= (Size + PadFileSize)) { - *PadSize = PadFileSize; - *PadFileEntry = FileEntry; - return EFI_SUCCESS; - } - } - - FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink); - } - - return EFI_NOT_FOUND; -} - -/** - Locate a suitable pad file for multiple file writing. - - @param FvDevice Cached Firmware Volume. - @param NumOfFiles The number of Files that needed updating - @param BufferSize The array of each file size. - @param RequiredAlignment The array of of FFS File Data alignment requirement. - @param PadSize The array of size of each leading Pad File. - @param TotalSizeNeeded The totalsize that can hold these files. - @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. - - @retval EFI_SUCCESS The required pad file is found. - @retval EFI_NOT_FOUND The required pad file can't be found. - -**/ -EFI_STATUS -FvSearchSuitablePadFile ( - IN FV_DEVICE *FvDevice, - IN UINTN NumOfFiles, - IN UINTN *BufferSize, - IN UINTN *RequiredAlignment, - OUT UINTN *PadSize, - OUT UINTN *TotalSizeNeeded, - OUT FFS_FILE_LIST_ENTRY **PadFileEntry - ) -{ - FFS_FILE_LIST_ENTRY *FileEntry; - EFI_FFS_FILE_STATE FileState; - EFI_FFS_FILE_HEADER *FileHeader; - UINTN PadAreaLength; - UINTN TotalSize; - UINTN Index; - UINTN HeaderSize; - - FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink; - - // - // travel through the whole file list to get the pad file entry - // - while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) { - - FileHeader = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader; - FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); - - if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) { - // - // we find one valid pad file, check its length - // - if (IS_FFS_FILE2 (FileHeader)) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize; - } else { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize; - } - TotalSize = 0; - - for (Index = 0; Index < NumOfFiles; Index++) { - PadSize[Index] = CalculatePadFileSize ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize + TotalSize, - BufferSize[Index], - RequiredAlignment[Index] - ); - TotalSize += PadSize[Index]; - TotalSize += BufferSize[Index]; - - if (TotalSize > PadAreaLength) { - break; - } - } - - if (PadAreaLength >= TotalSize) { - *PadFileEntry = FileEntry; - *TotalSizeNeeded = TotalSize; - return EFI_SUCCESS; - } - } - - FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink); - } - - return EFI_NOT_FOUND; -} - -/** - Locate a Free Space entry which can hold these files, including - meeting the alignment requirements. - - @param FvDevice Cached Firmware Volume. - @param NumOfFiles The number of Files that needed updating - @param BufferSize The array of each file size. - @param RequiredAlignment The array of of FFS File Data alignment requirement. - @param PadSize The array of size of each leading Pad File. - @param TotalSizeNeeded The got total size that can hold these files. - @param FreeSpaceEntry The Free Space Entry that can hold these files. - - @retval EFI_SUCCESS The free space entry is found. - @retval EFI_NOT_FOUND The free space entry can't be found. - -**/ -EFI_STATUS -FvSearchSuitableFreeSpace ( - IN FV_DEVICE *FvDevice, - IN UINTN NumOfFiles, - IN UINTN *BufferSize, - IN UINTN *RequiredAlignment, - OUT UINTN *PadSize, - OUT UINTN *TotalSizeNeeded, - OUT FREE_SPACE_ENTRY **FreeSpaceEntry - ) -{ - FREE_SPACE_ENTRY *FreeSpaceListEntry; - LIST_ENTRY *Link; - UINTN TotalSize; - UINTN Index; - UINT8 *StartAddr; - - Link = FvDevice->FreeSpaceHeader.ForwardLink; - - FreeSpaceListEntry = (FREE_SPACE_ENTRY *) Link; - - while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) { - TotalSize = 0; - StartAddr = FreeSpaceListEntry->StartingAddress; - - // - // Calculate the totalsize we need - // - for (Index = 0; Index < NumOfFiles; Index++) { - // - // Perhaps we don't need an EFI_FFS_FILE_HEADER, the first file - // have had its leading pad file. - // - PadSize[Index] = CalculatePadFileSize ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) StartAddr + TotalSize, - BufferSize[Index], - RequiredAlignment[Index] - ); - - TotalSize += PadSize[Index]; - TotalSize += BufferSize[Index]; - - if (TotalSize > FreeSpaceListEntry->Length) { - break; - } - } - - if (FreeSpaceListEntry->Length >= TotalSize) { - *FreeSpaceEntry = FreeSpaceListEntry; - *TotalSizeNeeded = TotalSize; - return EFI_SUCCESS; - } - - FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink; - } - - return EFI_NOT_FOUND; -} - -/** - Calculate the length of the remaining space in FV. - - @param FvDevice Cached Firmware Volume - @param Offset Current offset to FV base address. - @param Lba LBA number for the current offset. - @param LOffset Offset in block for the current offset. - - @return the length of remaining space. - -**/ -UINTN -CalculateRemainingLength ( - IN FV_DEVICE *FvDevice, - IN UINTN Offset, - OUT EFI_LBA *Lba, - OUT UINTN *LOffset - ) -{ - LIST_ENTRY *Link; - LBA_ENTRY *LbaEntry; - UINTN Count; - - Count = 0; - *Lba = 0; - Link = FvDevice->LbaHeader.ForwardLink; - LbaEntry = (LBA_ENTRY *) Link; - - while (&LbaEntry->Link != &FvDevice->LbaHeader) { - if (Count > Offset) { - break; - } - - Count += LbaEntry->BlockLength; - (*Lba)++; - Link = LbaEntry->Link.ForwardLink; - LbaEntry = (LBA_ENTRY *) Link; - } - - if (Count <= Offset) { - return 0; - } - - Link = LbaEntry->Link.BackLink; - LbaEntry = (LBA_ENTRY *) Link; - - (*Lba)--; - *LOffset = (UINTN) (LbaEntry->BlockLength - (Count - Offset)); - - Count = 0; - while (&LbaEntry->Link != &FvDevice->LbaHeader) { - - Count += LbaEntry->BlockLength; - - Link = LbaEntry->Link.ForwardLink; - LbaEntry = (LBA_ENTRY *) Link; - } - - Count -= *LOffset; - - return Count; -} - -/** - Writes data beginning at Lba:Offset from FV. The write terminates either - when *NumBytes of data have been written, or when the firmware end is - reached. *NumBytes is updated to reflect the actual number of bytes - written. - - @param FvDevice Cached Firmware Volume - @param Offset Offset in the block at which to begin write - @param NumBytes At input, indicates the requested write size. - At output, indicates the actual number of bytes written. - @param Buffer Buffer containing source data for the write. - - @retval EFI_SUCCESS Data is successfully written into FV. - @return error Data is failed written. - -**/ -EFI_STATUS -FvcWrite ( - IN FV_DEVICE *FvDevice, - IN UINTN Offset, - IN OUT UINTN *NumBytes, - IN UINT8 *Buffer - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - EFI_LBA Lba; - UINTN LOffset; - EFI_FVB_ATTRIBUTES_2 FvbAttributes; - UINTN RemainingLength; - UINTN WriteLength; - UINT8 *TmpBuffer; - - LOffset = 0; - RemainingLength = CalculateRemainingLength (FvDevice, Offset, &Lba, &LOffset); - if ((UINTN) (*NumBytes) > RemainingLength) { - *NumBytes = (UINTN) RemainingLength; - return EFI_INVALID_PARAMETER; - } - - Fvb = FvDevice->Fvb; - - Status = Fvb->GetAttributes ( - Fvb, - &FvbAttributes - ); - if (EFI_ERROR (Status)) { - return Status; - } - - if ((FvbAttributes & EFI_FV2_WRITE_STATUS) == 0) { - return EFI_ACCESS_DENIED; - } - - RemainingLength = *NumBytes; - WriteLength = RemainingLength; - TmpBuffer = Buffer; - - do { - Status = Fvb->Write ( - Fvb, - Lba, - LOffset, - &WriteLength, - TmpBuffer - ); - if (!EFI_ERROR (Status)) { - goto Done; - } - - if (Status == EFI_BAD_BUFFER_SIZE) { - Lba++; - LOffset = 0; - TmpBuffer += WriteLength; - RemainingLength -= WriteLength; - WriteLength = (UINTN) RemainingLength; - - continue; - } else { - return Status; - } - } while (1); - -Done: - return EFI_SUCCESS; -} - -/** - Create a new FFS file into Firmware Volume device. - - @param FvDevice Cached Firmware Volume. - @param FfsFileBuffer A buffer that holds an FFS file,(it contains - a File Header which is in init state). - @param BufferSize The size of FfsFileBuffer. - @param ActualFileSize The actual file length, it may not be multiples of 8. - @param FileName The FFS File Name. - @param FileType The FFS File Type. - @param FileAttributes The Attributes of the FFS File to be created. - - @retval EFI_SUCCESS FFS fle is added into FV. - @retval EFI_INVALID_PARAMETER File type is not valid. - @retval EFI_DEVICE_ERROR FV doesn't set writable attribute. - @retval EFI_NOT_FOUND FV has no enough space for the added file. - -**/ -EFI_STATUS -FvCreateNewFile ( - IN FV_DEVICE *FvDevice, - IN UINT8 *FfsFileBuffer, - IN UINTN BufferSize, - IN UINTN ActualFileSize, - IN EFI_GUID *FileName, - IN EFI_FV_FILETYPE FileType, - IN EFI_FV_FILE_ATTRIBUTES FileAttributes - ) -{ - EFI_STATUS Status; - EFI_FFS_FILE_HEADER *FileHeader; - EFI_PHYSICAL_ADDRESS BufferPtr; - UINTN Offset; - UINTN NumBytesWritten; - UINTN StateOffset; - FREE_SPACE_ENTRY *FreeSpaceEntry; - UINTN RequiredAlignment; - UINTN PadFileSize; - FFS_FILE_LIST_ENTRY *PadFileEntry; - EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - UINTN HeaderSize; - - // - // File Type: 0x0E~0xE0 are reserved - // - if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) { - return EFI_INVALID_PARAMETER; - } - - // - // First find a free space that can hold this image. - // Check alignment, FFS at least must be aligned at 8-byte boundry - // - RequiredAlignment = GetRequiredAlignment (FileAttributes); - - Status = FvLocateFreeSpaceEntry ( - FvDevice, - BufferSize, - RequiredAlignment, - &PadFileSize, - &FreeSpaceEntry - ); - if (EFI_ERROR (Status)) { - // - // Maybe we need to find a PAD file that can hold this image - // - Status = FvCreateNewFileInsidePadFile ( - FvDevice, - FfsFileBuffer, - BufferSize, - ActualFileSize, - FileName, - FileType, - FileAttributes - ); - - return Status; - } - - BufferPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress; - - // - // If we need a leading PAD File, create it first. - // - if (PadFileSize != 0) { - Status = FvCreatePadFileInFreeSpace ( - FvDevice, - FreeSpaceEntry, - PadFileSize - sizeof (EFI_FFS_FILE_HEADER), - &PadFileEntry - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - // - // Maybe we create a pad file, so re-get the free space starting address - // and length - // - BufferPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress; - - // - // File creation step 1: Allocate File Header, - // Mark EFI_FILE_HEADER_CONSTRUCTION bit to TRUE, - // Write Name, IntegrityCheck.Header, Type, Attributes, and Size - // - FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer; - if (ActualFileSize > 0x00FFFFFF) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - } else { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - } - SetFileState (EFI_FILE_HEADER_CONSTRUCTION, FileHeader); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &FileHeader->State - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // update header 2 cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FileHeader, - HeaderSize - ); - - // - // update Free Space Entry, now need to substract the file header length - // - FreeSpaceEntry->StartingAddress += HeaderSize; - FreeSpaceEntry->Length -= HeaderSize; - - CopyGuid (&FileHeader->Name, FileName); - FileHeader->Type = FileType; - - // - // Convert FvFileAttribute to FfsFileAttributes - // - FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute); - - FileHeader->Attributes = TmpFileAttribute; - - // - // File size is including the FFS File Header. - // - if (ActualFileSize > 0x00FFFFFF) { - ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize; - *(UINT32 *) FileHeader->Size &= 0xFF000000; - FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; - } else { - *(UINT32 *) FileHeader->Size &= 0xFF000000; - *(UINT32 *) FileHeader->Size |= ActualFileSize; - } - - SetHeaderChecksum (FileHeader); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - - NumBytesWritten = HeaderSize; - Status = FvcWrite ( - FvDevice, - Offset, - &NumBytesWritten, - (UINT8 *) FileHeader - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // update header 2 cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FileHeader, - HeaderSize - ); - - // - // end of step 1 - // - // File creation step 2: - // MARK EFI_FILE_HEADER_VALID bit to TRUE, - // Write IntegrityCheck.File, File Data - // - SetFileState (EFI_FILE_HEADER_VALID, FileHeader); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &FileHeader->State - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // update header 2 cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FileHeader, - HeaderSize - ); - - // - // update Free Space Entry, now need to substract the file data length - // - FreeSpaceEntry->StartingAddress += (BufferSize - HeaderSize); - FreeSpaceEntry->Length -= (BufferSize - HeaderSize); - - // - // Calculate File Checksum - // - SetFileChecksum (FileHeader, ActualFileSize); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - - NumBytesWritten = BufferSize; - Status = FvcWrite ( - FvDevice, - Offset, - &NumBytesWritten, - FfsFileBuffer - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // each time write block successfully, write also to cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FfsFileBuffer, - NumBytesWritten - ); - - // - // Step 3: Mark EFI_FILE_DATA_VALID to TRUE - // - SetFileState (EFI_FILE_DATA_VALID, FileHeader); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &FileHeader->State - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // update header 2 cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FileHeader, - HeaderSize - ); - - // - // If successfully, insert an FfsFileEntry at the end of ffs file list - // - - FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); - ASSERT (FfsFileEntry != NULL); - FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) BufferPtr; - InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); - - // - // Set cache file to this file - // - FvDevice->CurrentFfsFile = FfsFileEntry; - - return EFI_SUCCESS; -} - -/** - Update a File, so after successful update, there are 2 files existing - in FV, one is marked for deleted, and another one is valid. - - @param FvDevice Cached Firmware Volume. - @param FfsFileBuffer A buffer that holds an FFS file,(it contains - a File Header which is in init state). - @param BufferSize The size of FfsFileBuffer. - @param ActualFileSize The actual file length, it may not be multiples of 8. - @param FileName The FFS File Name. - @param NewFileType The FFS File Type. - @param NewFileAttributes The Attributes of the FFS File to be created. - - @retval EFI_SUCCESS FFS fle is updated into FV. - @retval EFI_INVALID_PARAMETER File type is not valid. - @retval EFI_DEVICE_ERROR FV doesn't set writable attribute. - @retval EFI_NOT_FOUND FV has no enough space for the added file. - FFS with same file name is not found in FV. - -**/ -EFI_STATUS -FvUpdateFile ( - IN FV_DEVICE *FvDevice, - IN UINT8 *FfsFileBuffer, - IN UINTN BufferSize, - IN UINTN ActualFileSize, - IN EFI_GUID *FileName, - IN EFI_FV_FILETYPE NewFileType, - IN EFI_FV_FILE_ATTRIBUTES NewFileAttributes - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; - UINTN NumBytesWritten; - EFI_FV_FILETYPE OldFileType; - EFI_FV_FILE_ATTRIBUTES OldFileAttributes; - UINTN OldFileSize; - EFI_FFS_FILE_HEADER *OldFileHeader; - UINTN OldOffset; - UINTN OldStateOffset; - FFS_FILE_LIST_ENTRY *OldFfsFileEntry; - UINTN Key; - EFI_GUID FileNameGuid; - - Fv = &FvDevice->Fv; - - // - // Step 1, find old file, - // Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE in the older header - // - - // - // Check if the file was read last time. - // - OldFileHeader = NULL; - OldFfsFileEntry = FvDevice->CurrentFfsFile; - - if (OldFfsFileEntry != NULL) { - OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader; - } - - if ((OldFfsFileEntry == NULL) || (!CompareGuid (&OldFileHeader->Name, FileName))) { - Key = 0; - do { - OldFileType = 0; - Status = Fv->GetNextFile ( - Fv, - &Key, - &OldFileType, - &FileNameGuid, - &OldFileAttributes, - &OldFileSize - ); - if (EFI_ERROR (Status)) { - return Status; - } - } while (!CompareGuid (&FileNameGuid, FileName)); - - // - // Get FfsFileEntry from the search key - // - OldFfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key; - - // - // Double check file state before being ready to be removed - // - OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader; - } else { - // - // Mark the cache file to invalid - // - FvDevice->CurrentFfsFile = NULL; - } - // - // Update File: Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE - // - SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader); - - OldOffset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv); - OldStateOffset = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - OldStateOffset, - &NumBytesWritten, - &OldFileHeader->State - ); - if (EFI_ERROR (Status)) { - // - // if failed, write the bit back in the cache, its XOR operation. - // - SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader); - - return Status; - } - - // - // Step 2, Create New Files - // - Status = FvCreateNewFile ( - FvDevice, - FfsFileBuffer, - BufferSize, - ActualFileSize, - FileName, - NewFileType, - NewFileAttributes - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // If successfully, remove this file entry, - // although delete file may fail. - // - (OldFfsFileEntry->Link.BackLink)->ForwardLink = OldFfsFileEntry->Link.ForwardLink; - (OldFfsFileEntry->Link.ForwardLink)->BackLink = OldFfsFileEntry->Link.BackLink; - FreePool (OldFfsFileEntry); - - // - // Step 3: Delete old files, - // by marking EFI_FILE_DELETED to TRUE - // - SetFileState (EFI_FILE_DELETED, OldFileHeader); - - OldOffset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv); - OldStateOffset = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - OldStateOffset, - &NumBytesWritten, - &OldFileHeader->State - ); - if (EFI_ERROR (Status)) { - // - // if failed, write the bit back in the cache, its XOR operation. - // - SetFileState (EFI_FILE_DELETED, OldFileHeader); - - return Status; - } - - return EFI_SUCCESS; -} - -/** - Deleted a given file from FV device. - - @param FvDevice Cached Firmware Volume. - @param NameGuid The FFS File Name. - - @retval EFI_SUCCESS FFS file with the specified FFS name is removed. - @retval EFI_NOT_FOUND FFS file with the specified FFS name is not found. - -**/ -EFI_STATUS -FvDeleteFile ( - IN FV_DEVICE *FvDevice, - IN EFI_GUID *NameGuid - ) -{ - EFI_STATUS Status; - UINTN Key; - EFI_GUID FileNameGuid; - EFI_FV_FILETYPE FileType; - EFI_FV_FILE_ATTRIBUTES FileAttributes; - UINTN FileSize; - EFI_FFS_FILE_HEADER *FileHeader; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - EFI_FFS_FILE_STATE FileState; - EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; - UINTN Offset; - UINTN StateOffset; - UINTN NumBytesWritten; - - Fv = &FvDevice->Fv; - - // - // Check if the file was read last time. - // - FileHeader = NULL; - FfsFileEntry = FvDevice->CurrentFfsFile; - - if (FfsFileEntry != NULL) { - FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; - } - - if ((FfsFileEntry == NULL) || (!CompareGuid (&FileHeader->Name, NameGuid))) { - // - // Next search for the file using GetNextFile - // - Key = 0; - do { - FileType = 0; - Status = Fv->GetNextFile ( - Fv, - &Key, - &FileType, - &FileNameGuid, - &FileAttributes, - &FileSize - ); - if (EFI_ERROR (Status)) { - return Status; - } - } while (!CompareGuid (&FileNameGuid, NameGuid)); - - // - // Get FfsFileEntry from the search key - // - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key; - - // - // Double check file state before being ready to be removed - // - FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; - } else { - // - // Mark the cache file to NULL - // - FvDevice->CurrentFfsFile = NULL; - } - - FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); - - if (FileState == EFI_FILE_HEADER_INVALID) { - return EFI_NOT_FOUND; - } - - if (FileState == EFI_FILE_DELETED) { - return EFI_NOT_FOUND; - } - // - // Delete File: Mark EFI_FILE_DELETED to TRUE - // - SetFileState (EFI_FILE_DELETED, FileHeader); - - Offset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &FileHeader->State - ); - if (EFI_ERROR (Status)) { - // - // if failed, write the bit back in the cache, its XOR operation. - // - SetFileState (EFI_FILE_DELETED, FileHeader); - - return Status; - } - // - // If successfully, remove this file entry - // - FvDevice->CurrentFfsFile = NULL; - - (FfsFileEntry->Link.BackLink)->ForwardLink = FfsFileEntry->Link.ForwardLink; - (FfsFileEntry->Link.ForwardLink)->BackLink = FfsFileEntry->Link.BackLink; - FreePool (FfsFileEntry); - - return EFI_SUCCESS; -} - -/** - Writes one or more files to the firmware volume. - - @param This Indicates the calling context. - @param NumberOfFiles Number of files. - @param WritePolicy WritePolicy indicates the level of reliability - for the write in the event of a power failure or - other system failure during the write operation. - @param FileData FileData is an pointer to an array of - EFI_FV_WRITE_DATA. Each element of array - FileData represents a file to be written. - - @retval EFI_SUCCESS Files successfully written to firmware volume - @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_WRITE_PROTECTED Write protected. - @retval EFI_NOT_FOUND Not found. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_UNSUPPORTED This function not supported. - -**/ -EFI_STATUS -EFIAPI -FvWriteFile ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN UINT32 NumberOfFiles, - IN EFI_FV_WRITE_POLICY WritePolicy, - IN EFI_FV_WRITE_FILE_DATA *FileData - ) -{ - EFI_STATUS Status; - UINTN Index1; - UINTN Index2; - UINT8 *FileBuffer; - UINTN BufferSize; - UINTN ActualSize; - UINT8 ErasePolarity; - FV_DEVICE *FvDevice; - EFI_FV_FILETYPE FileType; - EFI_FV_FILE_ATTRIBUTES FileAttributes; - UINTN Size; - BOOLEAN CreateNewFile[MAX_FILES]; - UINTN NumDelete; - EFI_FV_ATTRIBUTES FvAttributes; - UINT32 AuthenticationStatus; - UINTN HeaderSize; - - if (NumberOfFiles > MAX_FILES) { - return EFI_UNSUPPORTED; - } - - Status = EFI_SUCCESS; - - SetMem (CreateNewFile, NumberOfFiles, TRUE); - - FvDevice = FV_DEVICE_FROM_THIS (This); - - // - // First check the volume attributes. - // - Status = This->GetVolumeAttributes ( - This, - &FvAttributes - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Can we have write right? - // - if ((FvAttributes & EFI_FV2_WRITE_STATUS) == 0) { - return EFI_WRITE_PROTECTED; - } - - ErasePolarity = FvDevice->ErasePolarity; - - // - // Loop for all files - // - NumDelete = 0; - for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { - - if ((FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER) > 0x00FFFFFF) && !FvDevice->IsFfs3Fv) { - // - // Found a file needs a FFS3 formatted file to store it, but it is in a non-FFS3 formatted FV. - // - DEBUG ((EFI_D_ERROR, "FFS3 formatted file can't be written in a non-FFS3 formatted FV.\n")); - return EFI_INVALID_PARAMETER; - } - - if (FileData[Index1].BufferSize == 0) { - // - // Here we will delete this file - // - Status = This->ReadFile ( - This, - FileData[Index1].NameGuid, - NULL, - &Size, - &FileType, - &FileAttributes, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - NumDelete++; - } else { - return Status; - } - } - - if (FileData[Index1].Type == EFI_FV_FILETYPE_FFS_PAD) { - // - // According to PI spec, on EFI_FV_FILETYPE_FFS_PAD: - // "Standard firmware file system services will not return the handle of any pad files, - // nor will they permit explicit creation of such files." - // - return EFI_INVALID_PARAMETER; - } - } - - if ((NumDelete != NumberOfFiles) && (NumDelete != 0)) { - // - // A delete was request with a multiple file write - // - return EFI_INVALID_PARAMETER; - } - - if (NumDelete == NumberOfFiles) { - for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { - // - // Delete Files - // - Status = FvDeleteFile (FvDevice, FileData[Index1].NameGuid); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; - } - - for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { - Status = This->ReadFile ( - This, - FileData[Index1].NameGuid, - NULL, - &Size, - &FileType, - &FileAttributes, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - CreateNewFile[Index1] = FALSE; - } else if (Status == EFI_NOT_FOUND) { - CreateNewFile[Index1] = TRUE; - } else { - return Status; - } - // - // Checking alignment - // - if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) { - UINT8 FFSAlignmentValue; - UINT8 FvAlignmentValue; - - FFSAlignmentValue = (UINT8) (FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT); - FvAlignmentValue = (UINT8) (((UINT32) (FvAttributes & EFI_FV2_ALIGNMENT)) >> 16); - - if (FFSAlignmentValue > FvAlignmentValue) { - return EFI_INVALID_PARAMETER; - } - } - } - - if ((WritePolicy != EFI_FV_RELIABLE_WRITE) && (WritePolicy != EFI_FV_UNRELIABLE_WRITE)) { - return EFI_INVALID_PARAMETER; - } - // - // Checking the reliable write is supported by FV - // - - if ((WritePolicy == EFI_FV_RELIABLE_WRITE) && (NumberOfFiles > 1)) { - // - // Only for multiple files, reliable write is meaningful - // - Status = FvCreateMultipleFiles ( - FvDevice, - NumberOfFiles, - FileData, - CreateNewFile - ); - - return Status; - } - - for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { - // - // Making Buffersize QWORD boundry, and add file tail. - // - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - ActualSize = FileData[Index1].BufferSize + HeaderSize; - if (ActualSize > 0x00FFFFFF) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - ActualSize = FileData[Index1].BufferSize + HeaderSize; - } - BufferSize = ActualSize; - - while ((BufferSize & 0x07) != 0) { - BufferSize++; - } - - FileBuffer = AllocateZeroPool (BufferSize); - if (FileBuffer == NULL) { - return Status; - } - // - // Copy File Data into FileBuffer - // - CopyMem ( - FileBuffer + HeaderSize, - FileData[Index1].Buffer, - FileData[Index1].BufferSize - ); - - if (ErasePolarity == 1) { - // - // Fill the file header and padding byte with Erase Byte - // - for (Index2 = 0; Index2 < HeaderSize; Index2++) { - FileBuffer[Index2] = (UINT8)~FileBuffer[Index2]; - } - - for (Index2 = ActualSize; Index2 < BufferSize; Index2++) { - FileBuffer[Index2] = (UINT8)~FileBuffer[Index2]; - } - } - - if (CreateNewFile[Index1]) { - Status = FvCreateNewFile ( - FvDevice, - FileBuffer, - BufferSize, - ActualSize, - FileData[Index1].NameGuid, - FileData[Index1].Type, - FileData[Index1].FileAttributes - ); - } else { - Status = FvUpdateFile ( - FvDevice, - FileBuffer, - BufferSize, - ActualSize, - FileData[Index1].NameGuid, - FileData[Index1].Type, - FileData[Index1].FileAttributes - ); - } - - FreePool (FileBuffer); - - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/FlashUpdate.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/FlashUpdate.c deleted file mode 100644 index 56514c9855..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/FlashUpdate.c +++ /dev/null @@ -1,1218 +0,0 @@ -/** @file - Functions in this file will program the image into flash area. - - Copyright (c) 2002 - 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 "UpdateDriver.h" - -/** - Write a block size data into flash. - - @param FvbProtocol Pointer to FVB protocol. - @param Lba Logic block index to be updated. - @param BlockSize Block size - @param Buffer Buffer data to be written. - - @retval EFI_SUCCESS Write data successfully. - @retval other errors Write data failed. - -**/ -EFI_STATUS -UpdateOneBlock ( - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN EFI_LBA Lba, - IN UINTN BlockSize, - IN UINT8 *Buffer - ) -{ - EFI_STATUS Status; - UINTN Size; - - // - // First erase the block - // - Status = FvbProtocol->EraseBlocks ( - FvbProtocol, - Lba, // Lba - 1, // NumOfBlocks - EFI_LBA_LIST_TERMINATOR - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Write the block - // - Size = BlockSize; - Status = FvbProtocol->Write ( - FvbProtocol, - Lba, // Lba - 0, // Offset - &Size, // Size - Buffer // Buffer - ); - if ((EFI_ERROR (Status)) || (Size != BlockSize)) { - return Status; - } - - return EFI_SUCCESS; -} - -/** - Write buffer data in a flash block. - - @param FvbProtocol Pointer to FVB protocol. - @param Lba Logic block index to be updated. - @param Offset The offset within the block. - @param Length Size of buffer to be updated. - @param BlockSize Block size. - @param Buffer Buffer data to be updated. - - @retval EFI_SUCCESS Write data successfully. - @retval other errors Write data failed. - -**/ -EFI_STATUS -UpdateBufferInOneBlock ( - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN EFI_LBA Lba, - IN UINTN Offset, - IN UINTN Length, - IN UINTN BlockSize, - IN UINT8 *Buffer - ) -{ - EFI_STATUS Status; - UINTN Size; - UINT8 *ReservedBuffer; - - // - // If we are going to update a whole block - // - if ((Offset == 0) && (Length == BlockSize)) { - Status = UpdateOneBlock ( - FvbProtocol, - Lba, - BlockSize, - Buffer - ); - return Status; - } - - // - // If it is not a full block update, we need to coalesce data in - // the block that is not going to be updated and new data together. - // - - // - // Allocate a reserved buffer to make up the final buffer for update - // - ReservedBuffer = NULL; - ReservedBuffer = AllocatePool (BlockSize); - if (ReservedBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // First get the original content of the block - // - Size = BlockSize; - Status = FvbProtocol->Read ( - FvbProtocol, - Lba, - 0, - &Size, - ReservedBuffer - ); - if ((EFI_ERROR (Status)) || (Size != BlockSize)) { - FreePool (ReservedBuffer); - return Status; - } - - // - // Overwrite the reserved buffer with new content - // - CopyMem (ReservedBuffer + Offset, Buffer, Length); - - Status = UpdateOneBlock ( - FvbProtocol, - Lba, - BlockSize, - ReservedBuffer - ); - - FreePool (ReservedBuffer); - - return Status; -} - -/** - Get the last write log, and check the status of last write. - If not complete, restart will be taken. - - @param FvbHandle Handle of FVB protocol. - @param FtwProtocol FTW protocol instance. - @param ConfigData Config data on updating driver. - @param PrivateDataSize bytes from the private data - stored for this write. - @param PrivateData A pointer to a buffer. The function will copy. - @param Lba The logical block address of the last write. - @param Offset The offset within the block of the last write. - @param Length The length of the last write. - @param Pending A Boolean value with TRUE indicating - that the write was completed. - - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_ABORTED The FTW work space is damaged. - @retval EFI_NOT_FOUND The last write is not done by this driver. - @retval EFI_SUCCESS Last write log is got. - -**/ -EFI_STATUS -RetrieveLastWrite ( - IN EFI_HANDLE FvbHandle, - IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol, - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINTN PrivateDataSize, - IN OUT UPDATE_PRIVATE_DATA *PrivateData, - IN OUT EFI_LBA *Lba, - IN OUT UINTN *Offset, - IN OUT UINTN *Length, - IN OUT BOOLEAN *Pending - ) -{ - EFI_STATUS Status; - EFI_GUID CallerId; - UINTN PrivateBufferSize; - BOOLEAN Complete; - VOID *PrivateDataBuffer; - - // - // Get the last write - // - *Pending = FALSE; - PrivateBufferSize = PrivateDataSize; - PrivateDataBuffer = NULL; - Status = FtwProtocol->GetLastWrite ( - FtwProtocol, - &CallerId, - Lba, - Offset, - Length, - &PrivateBufferSize, - PrivateData, - &Complete - ); - if (EFI_ERROR (Status)) { - // - // If there is no incompleted record, return success. - // - if ((Status == EFI_NOT_FOUND) && Complete) { - return EFI_SUCCESS; - } else if (Status == EFI_BUFFER_TOO_SMALL) { - // - // If buffer too small, reallocate buffer and call getlastwrite again - // - PrivateDataBuffer = AllocatePool (PrivateBufferSize); - - if (PrivateDataBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Status = FtwProtocol->GetLastWrite ( - FtwProtocol, - &CallerId, - Lba, - Offset, - Length, - &PrivateBufferSize, - PrivateDataBuffer, - &Complete - ); - if (EFI_ERROR (Status)) { - FreePool ( PrivateDataBuffer); - return EFI_ABORTED; - } else { - CopyMem (PrivateData, PrivateDataBuffer, PrivateDataSize); - FreePool (PrivateDataBuffer); - PrivateDataBuffer = NULL; - } - } else { - return EFI_ABORTED; - } - } - - *Pending = TRUE; - - // - // If the caller is not the update driver, then return. - // The update driver cannot continue to perform the update - // - if (CompareMem (&CallerId, &gEfiCallerIdGuid, sizeof (EFI_GUID)) != 0) { - return EFI_NOT_FOUND; - } - - // - // Check the private data and see if it is the one I need. - // - if (CompareMem (&(PrivateData->FileGuid), &(ConfigData->FileGuid), sizeof(EFI_GUID)) != 0) { - return EFI_NOT_FOUND; - } - - // - // If the caller is the update driver and complete is not true, then restart(). - // - if (!Complete) { - // - // Re-start the update - // - Status = FtwProtocol->Restart ( - FtwProtocol, - FvbHandle - ); - // - // If restart() error, then abort(). - // - if (EFI_ERROR (Status)) { - FtwProtocol->Abort (FtwProtocol); - // - // Now set Pending as FALSE as this record has been cleared - // - *Pending = FALSE; - return EFI_SUCCESS; - } - - } - - return Status; -} - -/** - Update the whole FV image in fault tolerant write method. - - @param FvbHandle Handle of FVB protocol for the updated flash range. - @param FvbProtocol FVB protocol. - @param BlockMap Block array to specify flash area. - @param ConfigData Config data on updating driver. - @param ImageBuffer Image buffer to be updated. - @param ImageSize Image size. - - @retval EFI_SUCCESS FV image is writed into flash. - @retval EFI_INVALID_PARAMETER Config data is not valid. - @retval EFI_NOT_FOUND FTW protocol doesn't exist. - @retval EFI_OUT_OF_RESOURCES No enough backup space. - @retval EFI_ABORTED Error happen when update FV. - -**/ -EFI_STATUS -FaultTolerantUpdateOnWholeFv ( - IN EFI_HANDLE FvbHandle, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN EFI_FV_BLOCK_MAP_ENTRY *BlockMap, - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINT8 *ImageBuffer, - IN UINTN ImageSize - ) -{ - EFI_STATUS Status; - EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; - UINTN MaxBlockSize; - UINTN FtwMaxBlockSize; - BOOLEAN Pending; - UPDATE_PRIVATE_DATA PrivateData; - EFI_LBA PendingLba; - EFI_LBA Lba; - UINTN PendingOffset; - UINTN Offset; - UINTN PendingLength; - UINTN Length; - EFI_FV_BLOCK_MAP_ENTRY *PtrMap; - UINTN NumOfBlocks; - UINTN Index; - UINT8 *UpdateBuffer; - - if ((ConfigData->UpdateType != UpdateWholeFV) - || (!ConfigData->FaultTolerant)) { - return EFI_INVALID_PARAMETER; - } - - // - // Get the FTW protocol - // - Status = gBS->LocateProtocol ( - &gEfiFaultTolerantWriteProtocolGuid, - NULL, - (VOID **) &FtwProtocol - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - - // - // Get the maximum block size of the FV, and number of blocks - // NumOfBlocks will be the NumOfUdpates. - // - MaxBlockSize = 0; - NumOfBlocks = 0; - PtrMap = BlockMap; - while (TRUE) { - if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { - break; - } - if (MaxBlockSize < PtrMap->Length) { - MaxBlockSize = PtrMap->Length; - } - NumOfBlocks = NumOfBlocks + PtrMap->NumBlocks; - PtrMap++; - } - - FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize); - // - // Not enough backup space. return directly - // - if (FtwMaxBlockSize < MaxBlockSize) { - return EFI_OUT_OF_RESOURCES; - } - - PendingLba = 0; - PendingOffset = 0; - PendingLength = 0; - Pending = FALSE; - - // - // Fault Tolerant Write can only support actual fault tolerance if the write - // is a reclaim operation, which means the data buffer (new and old) are - // acutally both stored in flash. But for component update write, the data - // are now in memory. So we cannot actually recover the data after power - // failure. - // - Status = RetrieveLastWrite ( - FvbHandle, - FtwProtocol, - ConfigData, - sizeof (UPDATE_PRIVATE_DATA), - &PrivateData, - &PendingLba, - &PendingOffset, - &PendingLength, - &Pending - ); - - if (Pending && (Status == EFI_NOT_FOUND)) { - // - // Cannot continue with the write operation - // - return EFI_ABORTED; - } - - if (EFI_ERROR(Status)) { - return EFI_ABORTED; - } - - // - // Currently we start from the pending write if there is any. But as we - // are going to update a whole FV, we can just abort last write and start - // from the very begining. - // - if (!Pending) { - // - // Now allocte the update private data in FTW. If there is pending - // write, it has already been allocated and no need to allocate here. - // - Status = FtwProtocol->Allocate ( - FtwProtocol, - &gEfiCallerIdGuid, - sizeof (UPDATE_PRIVATE_DATA), - NumOfBlocks - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - - // - // Perform the update now. If there are pending writes, we need to - // start from the pending write instead of the very beginning. - // - PtrMap = BlockMap; - Lba = 0; - Offset = 0; - UpdateBuffer = ImageBuffer; - CopyMem ( - (VOID *) &PrivateData.FileGuid, - (VOID *) &ConfigData->FileGuid, - sizeof (EFI_GUID) - ); - - while (TRUE) { - if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { - break; - } - Length = (UINTN)PtrMap->Length; - for (Index = 0; Index < PtrMap->NumBlocks; Index++) { - - // - // Add an extra check here to see if the pending record is correct - // - if (Pending && (Lba == PendingLba)) { - if ((PendingOffset != Offset) || (PendingLength != Length)) { - // - // Error. - // - Status = EFI_ABORTED; - break; - } - } - - if ((!Pending) || (Lba >= PendingLba)) { - Status = FtwProtocol->Write ( - FtwProtocol, - Lba, // Lba - Offset, // Offset - Length, // Size - &PrivateData, // Private Data - FvbHandle, // FVB handle - UpdateBuffer // Buffer - ); - } - - if (EFI_ERROR (Status)) { - break; - } - Lba++; - UpdateBuffer = (UINT8 *) ((UINTN)UpdateBuffer + Length); - } - - if (EFI_ERROR (Status)) { - break; - } - PtrMap++; - } - - return Status; - -} - -/** - Directly update the whole FV image without fault tolerant write method. - - @param FvbHandle Handle of FVB protocol for the updated flash range. - @param FvbProtocol FVB protocol. - @param BlockMap Block array to specify flash area. - @param ConfigData Config data on updating driver. - @param ImageBuffer Image buffer to be updated. - @param ImageSize Image size. - - @retval EFI_SUCCESS FV image is writed into flash. - @retval EFI_INVALID_PARAMETER Config data is not valid. - @retval EFI_ABORTED Error happen when update FV. - -**/ -EFI_STATUS -NonFaultTolerantUpdateOnWholeFv ( - IN EFI_HANDLE FvbHandle, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN EFI_FV_BLOCK_MAP_ENTRY *BlockMap, - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINT8 *ImageBuffer, - IN UINTN ImageSize - ) -{ - EFI_STATUS Status; - EFI_FV_BLOCK_MAP_ENTRY *PtrMap; - UINTN Index; - EFI_LBA UpdateLba; - UINT8 *UpdateBuffer; - UINTN UpdateSize; - - if ((ConfigData->UpdateType != UpdateWholeFV ) - || (ConfigData->FaultTolerant)) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - PtrMap = BlockMap; - UpdateLba = 0; - UpdateBuffer = ImageBuffer; - - // - // Perform the update now - // - while (TRUE) { - if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { - break; - } - UpdateSize = (UINTN)PtrMap->Length; - for (Index = 0; Index < PtrMap->NumBlocks; Index++) { - Status = UpdateOneBlock ( - FvbProtocol, - UpdateLba, - UpdateSize, - UpdateBuffer - ); - if (EFI_ERROR (Status)) { - break; - } - - UpdateLba++; - UpdateBuffer = (UINT8 *) ((UINTN)UpdateBuffer + UpdateSize); - } - - if (EFI_ERROR (Status)) { - break; - } - PtrMap++; - } - - return Status; -} - -/** - Update the whole FV image, and reinsall FVB protocol for the updated FV image. - - @param FvbHandle Handle of FVB protocol for the updated flash range. - @param FvbProtocol FVB protocol. - @param ConfigData Config data on updating driver. - @param ImageBuffer Image buffer to be updated. - @param ImageSize Image size. - - @retval EFI_INVALID_PARAMETER Update type is not UpdateWholeFV. - Or Image size is not same to the size of whole FV. - @retval EFI_OUT_OF_RESOURCES No enoug memory is allocated. - @retval EFI_SUCCESS FV image is updated, and its FVB protocol is reinstalled. - -**/ -EFI_STATUS -PerformUpdateOnWholeFv ( - IN EFI_HANDLE FvbHandle, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINT8 *ImageBuffer, - IN UINTN ImageSize -) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_FV_BLOCK_MAP_ENTRY *BlockMap; - CHAR16 *TmpStr; - - if (ConfigData->UpdateType != UpdateWholeFV) { - return EFI_INVALID_PARAMETER; - } - - // - // Get the header of the firmware volume - // - FwVolHeader = NULL; - FwVolHeader = AllocatePool (((EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (ConfigData->BaseAddress)))->HeaderLength); - if (FwVolHeader == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem ( - FwVolHeader, - (VOID *) ((UINTN) (ConfigData->BaseAddress)), - ((EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (ConfigData->BaseAddress)))->HeaderLength - ); - - // - // Check if ImageSize is the same as the size of the whole FV - // - if ((UINT64)ImageSize != FwVolHeader->FvLength) { - FreePool (FwVolHeader); - return EFI_INVALID_PARAMETER; - } - - // - // Print on screen - // - TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME), NULL); - if (TmpStr != NULL) { - Print (TmpStr, ConfigData->BaseAddress, (FwVolHeader->FvLength + ConfigData->BaseAddress)); - FreePool (TmpStr); - } - - DEBUG ((EFI_D_UPDATE, "UpdateDriver: updating whole FV from %08LX to %08LX\n", - ConfigData->BaseAddress, (FwVolHeader->FvLength + ConfigData->BaseAddress))); - - // - // Get the block map of the firmware volume - // - BlockMap = &(FwVolHeader->BlockMap[0]); - - // - // It is about the same if we are going to fault tolerantly update - // a certain FV in our current design. But we divide non-fault tolerant - // and fault tolerant udpate here for better maintenance as fault - // tolerance may change and may be done more wisely if we have space. - // - if (ConfigData->FaultTolerant) { - Status = FaultTolerantUpdateOnWholeFv ( - FvbHandle, - FvbProtocol, - BlockMap, - ConfigData, - ImageBuffer, - ImageSize - ); - } else { - Status = NonFaultTolerantUpdateOnWholeFv ( - FvbHandle, - FvbProtocol, - BlockMap, - ConfigData, - ImageBuffer, - ImageSize - ); - } - - FreePool (FwVolHeader); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // As the whole FV has been replaced, the FV driver shall re-parse the - // firmware volume. So re-install FVB protocol here - // - Status = gBS->ReinstallProtocolInterface ( - FvbHandle, - &gEfiFirmwareVolumeBlockProtocolGuid, - FvbProtocol, - FvbProtocol - ); - - return Status; -} - -/** - Update certain file in the FV. - - @param FvbHandle Handle of FVB protocol for the updated flash range. - @param FvbProtocol FVB protocol. - @param ConfigData Config data on updating driver. - @param ImageBuffer Image buffer to be updated. - @param ImageSize Image size. - @param FileType FFS file type. - @param FileAttributes FFS file attribute - - @retval EFI_INVALID_PARAMETER Update type is not UpdateFvFile. - Or Image size is not same to the size of whole FV. - @retval EFI_UNSUPPORTED PEIM FFS is unsupported to be updated. - @retval EFI_SUCCESS The FFS file is added into FV. - -**/ -EFI_STATUS -PerformUpdateOnFvFile ( - IN EFI_HANDLE FvbHandle, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINT8 *ImageBuffer, - IN UINTN ImageSize, - IN EFI_FV_FILETYPE FileType, - IN EFI_FV_FILE_ATTRIBUTES FileAttributes - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol; - EFI_FV_WRITE_FILE_DATA FileData; - CHAR16 *TmpStr; - - if (ConfigData->UpdateType != UpdateFvFile) { - return EFI_INVALID_PARAMETER; - } - - // - // Print on screen - // - TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME_FILE), NULL); - if (TmpStr != NULL) { - Print (TmpStr, &(ConfigData->FileGuid)); - FreePool (TmpStr); - } - - DEBUG ((EFI_D_UPDATE, "UpdateDriver: updating file: %g\n", - &(ConfigData->FileGuid))); - - // - // Get Firmware volume protocol on this FVB protocol - // - Status = gBS->HandleProtocol ( - FvbHandle, - &gEfiFirmwareVolume2ProtocolGuid, - (VOID **) &FwVolProtocol - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // If it is a PEIM, we need first to rebase it before committing - // the write to target - // - if ((FileType == EFI_FV_FILETYPE_PEI_CORE) || (FileType == EFI_FV_FILETYPE_PEIM ) - || (FileType == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { - return EFI_UNSUPPORTED; - } - - FileData.NameGuid = &(ConfigData->FileGuid); - FileData.Type = FileType; - FileData.FileAttributes = FileAttributes; - FileData.Buffer = ImageBuffer; - FileData.BufferSize = (UINT32) ImageSize; - - Status = FwVolProtocol->WriteFile ( - FwVolProtocol, - 1, // NumberOfFiles - (EFI_FV_WRITE_POLICY)ConfigData->FaultTolerant, - &FileData - ); - return Status; -} - -/** - Update the buffer into flash area in fault tolerant write method. - - @param ImageBuffer Image buffer to be updated. - @param SizeLeft Size of the image buffer. - @param UpdatedSize Size of the updated buffer. - @param ConfigData Config data on updating driver. - @param FlashAddress Flash address to be updated as start address. - @param FvbProtocol FVB protocol. - @param FvbHandle Handle of FVB protocol for the updated flash range. - - @retval EFI_SUCCESS Buffer data is updated into flash. - @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area. - @retval EFI_NOT_FOUND FTW protocol doesn't exist. - @retval EFI_OUT_OF_RESOURCES No enough backup space. - @retval EFI_ABORTED Error happen when update flash area. - -**/ -EFI_STATUS -FaultTolerantUpdateOnPartFv ( - IN UINT8 *ImageBuffer, - IN UINTN SizeLeft, - IN OUT UINTN *UpdatedSize, - IN UPDATE_CONFIG_DATA *ConfigData, - IN EFI_PHYSICAL_ADDRESS FlashAddress, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN EFI_HANDLE FvbHandle - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeaderTmp; - EFI_PHYSICAL_ADDRESS BaseAddress; - EFI_PHYSICAL_ADDRESS FvBase; - EFI_PHYSICAL_ADDRESS NextBlock; - EFI_FV_BLOCK_MAP_ENTRY *BlockMap; - EFI_FV_BLOCK_MAP_ENTRY *PtrMap; - UINTN NumOfUpdates; - UINTN TotalSize; - EFI_PHYSICAL_ADDRESS StartAddress; - EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; - UINTN MaxBlockSize; - UINTN FtwMaxBlockSize; - BOOLEAN Pending; - UPDATE_PRIVATE_DATA PrivateData; - EFI_LBA PendingLba; - EFI_LBA Lba; - UINTN BlockSize; - UINTN PendingOffset; - UINTN Offset; - UINTN PendingLength; - UINTN Length; - UINTN Index; - UINT8 *Image; - - // - // Get the block map to update the block one by one - // - Status = FvbProtocol->GetPhysicalAddress ( - FvbProtocol, - &FvBase - ); - if (EFI_ERROR (Status)) { - return Status; - } - - FwVolHeaderTmp = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase; - if ((FlashAddress < FvBase) || (FlashAddress > (FvBase + FwVolHeaderTmp->FvLength))) { - return EFI_INVALID_PARAMETER; - } - - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AllocateCopyPool ( - FwVolHeaderTmp->HeaderLength, - FwVolHeaderTmp - ); - if (FwVolHeader == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // For fault tolerant write, we have to know how many blocks we need to - // update. So we will calculate number of updates and max block size first - // - NumOfUpdates = 0; - MaxBlockSize = 0; - TotalSize = SizeLeft; - StartAddress = FlashAddress; - BaseAddress = FvBase; - BlockMap = &(FwVolHeader->BlockMap[0]); - PtrMap = BlockMap; - - while (TotalSize > 0) { - if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { - break; - } - - BlockSize = PtrMap->Length; - for (Index = 0; Index < PtrMap->NumBlocks; Index++) { - NextBlock = BaseAddress + BlockSize; - // - // Check if this block need to be updated - // - if ((StartAddress >= BaseAddress) && (StartAddress < NextBlock)) { - // - // Get the maximum block size - // - if (MaxBlockSize < BlockSize) { - MaxBlockSize = BlockSize; - } - - // - // This block shall be udpated. So increment number of updates - // - NumOfUpdates++; - Offset = (UINTN) (StartAddress - BaseAddress); - Length = TotalSize; - if ((Length + Offset ) > BlockSize) { - Length = BlockSize - Offset; - } - - StartAddress = StartAddress + Length; - TotalSize = TotalSize - Length; - if (TotalSize <= 0) { - break; - } - } - BaseAddress = NextBlock; - } - PtrMap++; - } - - // - // Get the FTW protocol - // - Status = gBS->LocateProtocol ( - &gEfiFaultTolerantWriteProtocolGuid, - NULL, - (VOID **) &FtwProtocol - ); - if (EFI_ERROR (Status)) { - FreePool (FwVolHeader); - return EFI_NOT_FOUND; - } - - FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize); - - // - // Not enough backup space. return directly - // - if (FtwMaxBlockSize < MaxBlockSize) { - FreePool (FwVolHeader); - return EFI_OUT_OF_RESOURCES; - } - - PendingLba = 0; - PendingOffset = 0; - PendingLength = 0; - Pending = FALSE; - - // - // Fault Tolerant Write can only support actual fault tolerance if the write - // is a reclaim operation, which means the data buffer (new and old) are - // acutally both stored in flash. But for component update write, the data - // are now in memory. So we cannot actually recover the data after power - // failure. - // - Status = RetrieveLastWrite ( - FvbHandle, - FtwProtocol, - ConfigData, - sizeof (UPDATE_PRIVATE_DATA), - &PrivateData, - &PendingLba, - &PendingOffset, - &PendingLength, - &Pending - ); - if (Pending && (Status == EFI_NOT_FOUND)) { - // - // I'm not the owner of the pending fault tolerant write record - // Cannot continue with the write operation - // - FreePool (FwVolHeader); - return EFI_ABORTED; - } - - if (EFI_ERROR(Status)) { - FreePool (FwVolHeader); - return EFI_ABORTED; - } - - // - // Currently we start from the pending write if there is any. But if the - // caller is exactly the same, and the new data is already a in memory, (it - // cannot be stored in flash in last write,) we can just abort last write - // and start from the very begining. - // - if (!Pending) { - // - // Now allocte the update private data in FTW. If there is pending - // write, it has already been allocated and no need to allocate here. - // - Status = FtwProtocol->Allocate ( - FtwProtocol, - &gEfiCallerIdGuid, - sizeof (UPDATE_PRIVATE_DATA), - NumOfUpdates - ); - if (EFI_ERROR (Status)) { - FreePool (FwVolHeader); - return Status; - } - } - - // - // Perform the update now. If there are pending writes, we need to - // start from the pending write instead of the very beginning. - // - TotalSize = SizeLeft; - Lba = 0; - StartAddress = FlashAddress; - BaseAddress = FvBase; - PtrMap = BlockMap; - Image = ImageBuffer; - CopyMem ( - (VOID *) &PrivateData.FileGuid, - (VOID *) &ConfigData->FileGuid, - sizeof (EFI_GUID) - ); - - while (TotalSize > 0) { - if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) { - break; - } - - BlockSize = (UINTN)PtrMap->Length; - for (Index = 0; Index < PtrMap->NumBlocks; Index++) { - NextBlock = BaseAddress + BlockSize; - if ((StartAddress >= BaseAddress) && (StartAddress < NextBlock)) { - // - // So we need to update this block - // - Offset = (UINTN) (StartAddress - BaseAddress); - Length = TotalSize; - if ((Length + Offset ) > BlockSize) { - Length = BlockSize - Offset; - } - - // - // Add an extra check here to see if the pending record is correct - // - if (Pending && (Lba == PendingLba)) { - if ((PendingOffset != Offset) || (PendingLength != Length)) { - // - // Error. - // - Status = EFI_ABORTED; - break; - } - } - - if ((!Pending) || (Lba >= PendingLba)) { - DEBUG ((EFI_D_UPDATE, "Update Flash area from %08LX to %08LX\n", StartAddress, (UINT64)StartAddress + Length)); - Status = FtwProtocol->Write ( - FtwProtocol, - Lba, // Lba - Offset, // Offset - Length, // Size - &PrivateData, // Private Data - FvbHandle, // FVB handle - Image // Buffer - ); - if (EFI_ERROR (Status)) { - break; - } - } - - // - // Now increment StartAddress, ImageBuffer and decrease the - // left size to prepare for the next block update. - // - StartAddress = StartAddress + Length; - Image = Image + Length; - TotalSize = TotalSize - Length; - if (TotalSize <= 0) { - break; - } - } - BaseAddress = NextBlock; - Lba++; - } - - if (EFI_ERROR (Status)) { - break; - } - PtrMap++; - } - - FreePool (FwVolHeader); - - *UpdatedSize = SizeLeft - TotalSize; - - return EFI_SUCCESS; -} - -/** - Directly update the buffer into flash area without fault tolerant write method. - - @param ImageBuffer Image buffer to be updated. - @param SizeLeft Size of the image buffer. - @param UpdatedSize Size of the updated buffer. - @param FlashAddress Flash address to be updated as start address. - @param FvbProtocol FVB protocol. - @param FvbHandle Handle of FVB protocol for the updated flash range. - - @retval EFI_SUCCESS Buffer data is updated into flash. - @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area. - @retval EFI_OUT_OF_RESOURCES No enough backup space. - -**/ -EFI_STATUS -NonFaultTolerantUpdateOnPartFv ( - IN UINT8 *ImageBuffer, - IN UINTN SizeLeft, - IN OUT UINTN *UpdatedSize, - IN EFI_PHYSICAL_ADDRESS FlashAddress, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN EFI_HANDLE FvbHandle - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeaderTmp; - EFI_PHYSICAL_ADDRESS BaseAddress; - EFI_PHYSICAL_ADDRESS NextBlock; - EFI_FV_BLOCK_MAP_ENTRY *BlockMap; - UINTN Index; - UINTN TotalSize; - UINTN BlockSize; - EFI_LBA Lba; - UINTN Offset; - UINTN Length; - UINT8 *Image; - - // - // Get the block map to update the block one by one - // - Status = FvbProtocol->GetPhysicalAddress ( - FvbProtocol, - &BaseAddress - ); - if (EFI_ERROR (Status)) { - return Status; - } - - FwVolHeaderTmp = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress; - if ((FlashAddress < BaseAddress) || (FlashAddress > ( BaseAddress + FwVolHeaderTmp->FvLength ))) { - return EFI_INVALID_PARAMETER; - } - - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AllocateCopyPool ( - FwVolHeaderTmp->HeaderLength, - FwVolHeaderTmp - ); - if (FwVolHeader == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Image = ImageBuffer; - TotalSize = SizeLeft; - BlockMap = &(FwVolHeader->BlockMap[0]); - Lba = 0; - - while (TotalSize > 0) { - if ((BlockMap->NumBlocks == 0) || (BlockMap->Length == 0)) { - break; - } - - BlockSize = BlockMap->Length; - for (Index = 0 ; Index < BlockMap->NumBlocks ; Index++) { - NextBlock = BaseAddress + BlockSize; - if ((FlashAddress >= BaseAddress) && (FlashAddress < NextBlock)) { - // - // So we need to update this block - // - Offset = (UINTN) FlashAddress - (UINTN) BaseAddress; - Length = TotalSize; - if ((Length + Offset ) > BlockSize) { - Length = BlockSize - Offset; - } - - DEBUG ((EFI_D_UPDATE, "Update Flash area from %08LX to %08LX\n", FlashAddress, (UINT64)FlashAddress + Length)); - // - // Update the block - // - Status = UpdateBufferInOneBlock ( - FvbProtocol, - Lba, - Offset, - Length, - BlockSize, - Image - ); - if (EFI_ERROR (Status)) { - FreePool (FwVolHeader); - return Status; - } - - // - // Now increment FlashAddress, ImageBuffer and decrease the - // left size to prepare for the next block update. - // - FlashAddress = FlashAddress + Length; - Image = Image + Length; - TotalSize = TotalSize - Length; - if (TotalSize <= 0) { - break; - } - } - BaseAddress = NextBlock; - Lba++; - } - - if (EFI_ERROR (Status)) { - break; - } - BlockMap++; - } - - FreePool (FwVolHeader); - - *UpdatedSize = SizeLeft - TotalSize; - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c deleted file mode 100644 index 023506e6ee..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c +++ /dev/null @@ -1,1133 +0,0 @@ -/** @file - Source file for the component update driver. It parse the update - configuration file and pass the information to the update driver - so that the driver can perform updates accordingly. - - Copyright (c) 2002 - 2015, Intel 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 "UpdateDriver.h" - -/** - Copy one line data from buffer data to the line buffer. - - @param Buffer Buffer data. - @param BufferSize Buffer Size. - @param LineBuffer Line buffer to store the found line data. - @param LineSize On input, size of the input line buffer. - On output, size of the actual line buffer. - - @retval EFI_BUFFER_TOO_SMALL The size of input line buffer is not enough. - @retval EFI_SUCCESS Copy line data into the line buffer. - -**/ -EFI_STATUS -ProfileGetLine ( - IN UINT8 *Buffer, - IN UINTN BufferSize, - IN OUT UINT8 *LineBuffer, - IN OUT UINTN *LineSize - ) -{ - UINTN Length; - UINT8 *PtrBuf; - UINTN PtrEnd; - - PtrBuf = Buffer; - PtrEnd = (UINTN)Buffer + BufferSize; - - // - // 0x0D indicates a line break. Otherwise there is no line break - // - while ((UINTN)PtrBuf < PtrEnd) { - if (*PtrBuf == 0x0D) { - break; - } - PtrBuf++; - } - - if ((UINTN)PtrBuf >= (PtrEnd - 1)) { - // - // The buffer ends without any line break - // or it is the last character of the buffer - // - Length = BufferSize; - } else if (*(PtrBuf + 1) == 0x0A) { - // - // Further check if a 0x0A follows. If yes, count 0xA - // - Length = (UINTN) PtrBuf - (UINTN) Buffer + 2; - } else { - Length = (UINTN) PtrBuf - (UINTN) Buffer + 1; - } - - if (Length > (*LineSize)) { - *LineSize = Length; - return EFI_BUFFER_TOO_SMALL; - } - - SetMem (LineBuffer, *LineSize, 0x0); - *LineSize = Length; - CopyMem (LineBuffer, Buffer, Length); - - return EFI_SUCCESS; -} - -/** - Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail. - - @param Buffer On input, buffer data to be trimed. - On output, the trimmed buffer. - @param BufferSize On input, size of original buffer data. - On output, size of the trimmed buffer. - -**/ -VOID -ProfileTrim ( - IN OUT UINT8 *Buffer, - IN OUT UINTN *BufferSize - ) -{ - UINTN Length; - UINT8 *PtrBuf; - UINT8 *PtrEnd; - - if (*BufferSize == 0) { - return; - } - - // - // Trim the tail first, include CR, LF, TAB, and SPACE. - // - Length = *BufferSize; - PtrBuf = (UINT8 *) ((UINTN) Buffer + Length - 1); - while (PtrBuf >= Buffer) { - if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A ) - && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) { - break; - } - PtrBuf --; - } - - // - // all spaces, a blank line, return directly; - // - if (PtrBuf < Buffer) { - *BufferSize = 0; - return; - } - - Length = (UINTN)PtrBuf - (UINTN)Buffer + 1; - PtrEnd = PtrBuf; - PtrBuf = Buffer; - - // - // Now skip the heading CR, LF, TAB and SPACE - // - while (PtrBuf <= PtrEnd) { - if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A ) - && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) { - break; - } - PtrBuf++; - } - - // - // If no heading CR, LF, TAB or SPACE, directly return - // - if (PtrBuf == Buffer) { - *BufferSize = Length; - return; - } - - *BufferSize = (UINTN)PtrEnd - (UINTN)PtrBuf + 1; - - // - // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE. - // Now move out all these characters. - // - while (PtrBuf <= PtrEnd) { - *Buffer = *PtrBuf; - Buffer++; - PtrBuf++; - } - - return; -} - -/** - Insert new comment item into comment head. - - @param Buffer Comment buffer to be added. - @param BufferSize Size of comment buffer. - @param CommentHead Comment Item head entry. - - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_SUCCESS New comment item is inserted. - -**/ -EFI_STATUS -ProfileGetComments ( - IN UINT8 *Buffer, - IN UINTN BufferSize, - IN OUT COMMENT_LINE **CommentHead - ) -{ - COMMENT_LINE *CommentItem; - - CommentItem = NULL; - CommentItem = AllocatePool (sizeof (COMMENT_LINE)); - if (CommentItem == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - CommentItem->ptrNext = *CommentHead; - *CommentHead = CommentItem; - - // - // Add a trailing '\0' - // - CommentItem->ptrComment = AllocatePool (BufferSize + 1); - if (CommentItem->ptrComment == NULL) { - FreePool (CommentItem); - return EFI_OUT_OF_RESOURCES; - } - CopyMem (CommentItem->ptrComment, Buffer, BufferSize); - *(CommentItem->ptrComment + BufferSize) = '\0'; - - return EFI_SUCCESS; -} - -/** - Add new section item into Section head. - - @param Buffer Section item data buffer. - @param BufferSize Size of section item. - @param SectionHead Section item head entry. - - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_SUCCESS Section item is NULL or Section item is added. - -**/ -EFI_STATUS -ProfileGetSection ( - IN UINT8 *Buffer, - IN UINTN BufferSize, - IN OUT SECTION_ITEM **SectionHead - ) -{ - EFI_STATUS Status; - SECTION_ITEM *SectionItem; - UINTN Length; - UINT8 *PtrBuf; - - Status = EFI_SUCCESS; - // - // The first character of Buffer is '[', now we want for ']' - // - PtrBuf = (UINT8 *)((UINTN)Buffer + BufferSize - 1); - while (PtrBuf > Buffer) { - if (*PtrBuf == ']') { - break; - } - PtrBuf --; - } - if (PtrBuf <= Buffer) { - // - // Not found. Omit this line - // - return Status; - } - - // - // excluding the heading '[' and tailing ']' - // - Length = PtrBuf - Buffer - 1; - ProfileTrim ( - Buffer + 1, - &Length - ); - - // - // omit this line if the section name is null - // - if (Length == 0) { - return Status; - } - - SectionItem = AllocatePool (sizeof (SECTION_ITEM)); - if (SectionItem == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - SectionItem->ptrSection = NULL; - SectionItem->SecNameLen = Length; - SectionItem->ptrEntry = NULL; - SectionItem->ptrValue = NULL; - SectionItem->ptrNext = *SectionHead; - *SectionHead = SectionItem; - - // - // Add a trailing '\0' - // - SectionItem->ptrSection = AllocatePool (Length + 1); - if (SectionItem->ptrSection == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // excluding the heading '[' - // - CopyMem (SectionItem->ptrSection, Buffer + 1, Length); - *(SectionItem->ptrSection + Length) = '\0'; - - return EFI_SUCCESS; -} - -/** - Add new section entry and entry value into Section head. - - @param Buffer Section entry data buffer. - @param BufferSize Size of section entry. - @param SectionHead Section item head entry. - - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_SUCCESS Section entry is NULL or Section entry is added. - -**/ -EFI_STATUS -ProfileGetEntry ( - IN UINT8 *Buffer, - IN UINTN BufferSize, - IN OUT SECTION_ITEM **SectionHead - ) -{ - EFI_STATUS Status; - SECTION_ITEM *SectionItem; - SECTION_ITEM *PtrSection; - UINTN Length; - UINT8 *PtrBuf; - UINT8 *PtrEnd; - - Status = EFI_SUCCESS; - PtrBuf = Buffer; - PtrEnd = (UINT8 *) ((UINTN)Buffer + BufferSize - 1); - - // - // First search for '=' - // - while (PtrBuf <= PtrEnd) { - if (*PtrBuf == '=') { - break; - } - PtrBuf++; - } - if (PtrBuf > PtrEnd) { - // - // Not found. Omit this line - // - return Status; - } - - // - // excluding the tailing '=' - // - Length = PtrBuf - Buffer; - ProfileTrim ( - Buffer, - &Length - ); - - // - // Omit this line if the entry name is null - // - if (Length == 0) { - return Status; - } - - // - // Omit this line if no section header has been found before - // - if (*SectionHead == NULL) { - return Status; - } - PtrSection = *SectionHead; - - SectionItem = AllocatePool (sizeof (SECTION_ITEM)); - if (SectionItem == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - SectionItem->ptrSection = NULL; - SectionItem->ptrEntry = NULL; - SectionItem->ptrValue = NULL; - SectionItem->SecNameLen = PtrSection->SecNameLen; - SectionItem->ptrNext = *SectionHead; - *SectionHead = SectionItem; - - // - // SectionName, add a trailing '\0' - // - SectionItem->ptrSection = AllocatePool (PtrSection->SecNameLen + 1); - if (SectionItem->ptrSection == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem (SectionItem->ptrSection, PtrSection->ptrSection, PtrSection->SecNameLen + 1); - - // - // EntryName, add a trailing '\0' - // - SectionItem->ptrEntry = AllocatePool (Length + 1); - if (SectionItem->ptrEntry == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem (SectionItem->ptrEntry, Buffer, Length); - *(SectionItem->ptrEntry + Length) = '\0'; - - // - // Next search for '#' - // - PtrBuf = PtrBuf + 1; - Buffer = PtrBuf; - while (PtrBuf <= PtrEnd) { - if (*PtrBuf == '#') { - break; - } - PtrBuf++; - } - Length = PtrBuf - Buffer; - ProfileTrim ( - Buffer, - &Length - ); - - if (Length > 0) { - // - // EntryValue, add a trailing '\0' - // - SectionItem->ptrValue = AllocatePool (Length + 1); - if (SectionItem->ptrValue == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem (SectionItem->ptrValue, Buffer, Length); - *(SectionItem->ptrValue + Length) = '\0'; - } - - return EFI_SUCCESS; -} - -/** - Free all comment entry and section entry. - - @param Section Section entry list. - @param Comment Comment entry list. - -**/ -VOID -FreeAllList ( - IN SECTION_ITEM *Section, - IN COMMENT_LINE *Comment - ) -{ - SECTION_ITEM *PtrSection; - COMMENT_LINE *PtrComment; - - while (Section != NULL) { - PtrSection = Section; - Section = Section->ptrNext; - if (PtrSection->ptrEntry != NULL) { - FreePool (PtrSection->ptrEntry); - } - if (PtrSection->ptrSection != NULL) { - FreePool (PtrSection->ptrSection); - } - if (PtrSection->ptrValue != NULL) { - FreePool (PtrSection->ptrValue); - } - FreePool (PtrSection); - } - - while (Comment != NULL) { - PtrComment = Comment; - Comment = Comment->ptrNext; - if (PtrComment->ptrComment != NULL) { - FreePool (PtrComment->ptrComment); - } - FreePool (PtrComment); - } - - return; -} - -/** - Get section entry value. - - @param Section Section entry list. - @param SectionName Section name. - @param EntryName Section entry name. - @param EntryValue Point to the got entry value. - - @retval EFI_NOT_FOUND Section is not found. - @retval EFI_SUCCESS Section entry value is got. - -**/ -EFI_STATUS -UpdateGetProfileString ( - IN SECTION_ITEM *Section, - IN UINT8 *SectionName, - IN UINT8 *EntryName, - OUT UINT8 **EntryValue - ) -{ - *EntryValue = NULL; - - while (Section != NULL) { - if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrSection, (CONST CHAR8 *) SectionName) == 0) { - if (Section->ptrEntry != NULL) { - if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrEntry, (CONST CHAR8 *) EntryName) == 0) { - break; - } - } - } - Section = Section->ptrNext; - } - - if (Section == NULL) { - return EFI_NOT_FOUND; - } - - *EntryValue = (UINT8 *) Section->ptrValue; - - return EFI_SUCCESS; -} - -/** - Convert the dec or hex ascii string to value. - - @param Str ascii string to be converted. - - @return the converted value. - -**/ -UINTN -UpdateAtoi ( - IN UINT8 *Str - ) -{ - UINTN Number; - - Number = 0; - - // - // Skip preceeding while spaces - // - while (*Str != '\0') { - if (*Str != 0x20) { - break; - } - Str++; - } - - if (*Str == '\0') { - return Number; - } - - // - // Find whether the string is prefixed by 0x. - // That is, it should be xtoi or atoi. - // - if (*Str == '0') { - if ((*(Str+1) == 'x' ) || ( *(Str+1) == 'X')) { - return AsciiStrHexToUintn ((CONST CHAR8 *) Str); - } - } - - while (*Str != '\0') { - if ((*Str >= '0') && (*Str <= '9')) { - Number = Number * 10 + *Str - '0'; - } else { - break; - } - Str++; - } - - return Number; -} - -/** - Converts a decimal value to a Null-terminated ascii string. - - @param Buffer Pointer to the output buffer for the produced Null-terminated - ASCII string. - @param Value The 64-bit sgned value to convert to a string. - - @return The number of ASCII characters in Buffer not including the Null-terminator. - -**/ -UINTN -UpdateValueToString ( - IN OUT UINT8 *Buffer, - IN INT64 Value - ) -{ - UINT8 TempBuffer[30]; - UINT8 *TempStr; - UINT8 *BufferPtr; - UINTN Count; - UINT32 Remainder; - - TempStr = TempBuffer; - BufferPtr = Buffer; - Count = 0; - - if (Value < 0) { - *BufferPtr = '-'; - BufferPtr++; - Value = -Value; - Count++; - } - - do { - Value = (INT64) DivU64x32Remainder ((UINT64)Value, 10, &Remainder); - // - // The first item of TempStr is not occupied. It's kind of flag - // - TempStr++; - Count++; - *TempStr = (UINT8) ((UINT8)Remainder + '0'); - } while (Value != 0); - - // - // Reverse temp string into Buffer. - // - while (TempStr != TempBuffer) { - *BufferPtr = *TempStr; - BufferPtr++; - TempStr --; - } - - *BufferPtr = 0; - - return Count; -} - -/** - Convert the input value to a ascii string, - and concatenates this string to the input string. - - @param Str Pointer to a Null-terminated ASCII string. - @param Number The unsgned value to convert to a string. - -**/ -VOID -UpdateStrCatNumber ( - IN OUT UINT8 *Str, - IN UINTN Number - ) -{ - UINTN Count; - - while (*Str != '\0') { - Str++; - } - - Count = UpdateValueToString (Str, (INT64)Number); - - *(Str + Count) = '\0'; - - return; -} - -/** - Convert the input ascii string into GUID value. - - @param Str Ascii GUID string to be converted. - @param Guid Pointer to the converted GUID value. - - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_NOT_FOUND The input ascii string is not a valid GUID format string. - @retval EFI_SUCCESS GUID value is got. - -**/ -EFI_STATUS -UpdateStringToGuid ( - IN UINT8 *Str, - IN OUT EFI_GUID *Guid - ) -{ - UINT8 *PtrBuffer; - UINT8 *PtrPosition; - UINT8 *Buffer; - UINTN Data; - UINTN StrLen; - UINTN Index; - UINT8 Digits[3]; - - StrLen = AsciiStrLen ((CONST CHAR8 *) Str); - Buffer = AllocateCopyPool (StrLen + 1, Str); - if (Buffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Data1 - // - PtrBuffer = Buffer; - PtrPosition = PtrBuffer; - while (*PtrBuffer != '\0') { - if (*PtrBuffer == '-') { - break; - } - PtrBuffer++; - } - if (*PtrBuffer == '\0') { - FreePool (Buffer); - return EFI_NOT_FOUND; - } - - *PtrBuffer = '\0'; - Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition); - Guid->Data1 = (UINT32)Data; - - // - // Data2 - // - PtrBuffer++; - PtrPosition = PtrBuffer; - while (*PtrBuffer != '\0') { - if (*PtrBuffer == '-') { - break; - } - PtrBuffer++; - } - if (*PtrBuffer == '\0') { - FreePool (Buffer); - return EFI_NOT_FOUND; - } - *PtrBuffer = '\0'; - Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition); - Guid->Data2 = (UINT16)Data; - - // - // Data3 - // - PtrBuffer++; - PtrPosition = PtrBuffer; - while (*PtrBuffer != '\0') { - if (*PtrBuffer == '-') { - break; - } - PtrBuffer++; - } - if (*PtrBuffer == '\0') { - FreePool (Buffer); - return EFI_NOT_FOUND; - } - *PtrBuffer = '\0'; - Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition); - Guid->Data3 = (UINT16)Data; - - // - // Data4[0..1] - // - for ( Index = 0 ; Index < 2 ; Index++) { - PtrBuffer++; - if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) { - FreePool (Buffer); - return EFI_NOT_FOUND; - } - Digits[0] = *PtrBuffer; - PtrBuffer++; - Digits[1] = *PtrBuffer; - Digits[2] = '\0'; - Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits); - Guid->Data4[Index] = (UINT8)Data; - } - - // - // skip the '-' - // - PtrBuffer++; - if ((*PtrBuffer != '-' ) || ( *PtrBuffer == '\0')) { - return EFI_NOT_FOUND; - } - - // - // Data4[2..7] - // - for ( ; Index < 8; Index++) { - PtrBuffer++; - if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) { - FreePool (Buffer); - return EFI_NOT_FOUND; - } - Digits[0] = *PtrBuffer; - PtrBuffer++; - Digits[1] = *PtrBuffer; - Digits[2] = '\0'; - Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits); - Guid->Data4[Index] = (UINT8)Data; - } - - FreePool (Buffer); - - return EFI_SUCCESS; -} - -/** - Pre process config data buffer into Section entry list and Comment entry list. - - @param DataBuffer Config raw file buffer. - @param BufferSize Size of raw buffer. - @param SectionHead Pointer to the section entry list. - @param CommentHead Pointer to the comment entry list. - - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_SUCCESS Config data buffer is preprocessed. - -**/ -EFI_STATUS -PreProcessDataFile ( - IN UINT8 *DataBuffer, - IN UINTN BufferSize, - IN OUT SECTION_ITEM **SectionHead, - IN OUT COMMENT_LINE **CommentHead - ) -{ - EFI_STATUS Status; - CHAR8 *Source; - CHAR8 *CurrentPtr; - CHAR8 *BufferEnd; - CHAR8 *PtrLine; - UINTN LineLength; - UINTN SourceLength; - UINTN MaxLineLength; - - *SectionHead = NULL; - *CommentHead = NULL; - BufferEnd = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize); - CurrentPtr = (CHAR8 *) DataBuffer; - MaxLineLength = MAX_LINE_LENGTH; - Status = EFI_SUCCESS; - - PtrLine = AllocatePool (MaxLineLength); - if (PtrLine == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - while (CurrentPtr < BufferEnd) { - Source = CurrentPtr; - SourceLength = (UINTN)BufferEnd - (UINTN)CurrentPtr; - LineLength = MaxLineLength; - // - // With the assumption that line length is less than 512 - // characters. Otherwise BUFFER_TOO_SMALL will be returned. - // - Status = ProfileGetLine ( - (UINT8 *) Source, - SourceLength, - (UINT8 *) PtrLine, - &LineLength - ); - if (EFI_ERROR (Status)) { - if (Status == EFI_BUFFER_TOO_SMALL) { - // - // If buffer too small, re-allocate the buffer according - // to the returned LineLength and try again. - // - FreePool (PtrLine); - PtrLine = NULL; - PtrLine = AllocatePool (LineLength); - if (PtrLine == NULL) { - Status = EFI_OUT_OF_RESOURCES; - break; - } - SourceLength = LineLength; - Status = ProfileGetLine ( - (UINT8 *) Source, - SourceLength, - (UINT8 *) PtrLine, - &LineLength - ); - if (EFI_ERROR (Status)) { - break; - } - MaxLineLength = LineLength; - } else { - break; - } - } - CurrentPtr = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength); - - // - // Line got. Trim the line before processing it. - // - ProfileTrim ( - (UINT8 *) PtrLine, - &LineLength - ); - - // - // Blank line - // - if (LineLength == 0) { - continue; - } - - if (PtrLine[0] == '#') { - Status = ProfileGetComments ( - (UINT8 *) PtrLine, - LineLength, - CommentHead - ); - } else if (PtrLine[0] == '[') { - Status = ProfileGetSection ( - (UINT8 *) PtrLine, - LineLength, - SectionHead - ); - } else { - Status = ProfileGetEntry ( - (UINT8 *) PtrLine, - LineLength, - SectionHead - ); - } - - if (EFI_ERROR (Status)) { - break; - } - } - - // - // Free buffer - // - FreePool (PtrLine); - - return Status; -} - -/** - Parse Config data file to get the updated data array. - - @param DataBuffer Config raw file buffer. - @param BufferSize Size of raw buffer. - @param NumOfUpdates Pointer to the number of update data. - @param UpdateArray Pointer to the config of update data. - - @retval EFI_NOT_FOUND No config data is found. - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_SUCCESS Parse the config file successfully. - -**/ -EFI_STATUS -ParseUpdateDataFile ( - IN UINT8 *DataBuffer, - IN UINTN BufferSize, - IN OUT UINTN *NumOfUpdates, - IN OUT UPDATE_CONFIG_DATA **UpdateArray - ) -{ - EFI_STATUS Status; - CHAR8 *Value; - CHAR8 *SectionName; - CHAR8 Entry[MAX_LINE_LENGTH]; - SECTION_ITEM *SectionHead; - COMMENT_LINE *CommentHead; - UINTN Num; - UINTN Index; - EFI_GUID FileGuid; - - SectionHead = NULL; - CommentHead = NULL; - - // - // First process the data buffer and get all sections and entries - // - Status = PreProcessDataFile ( - DataBuffer, - BufferSize, - &SectionHead, - &CommentHead - ); - if (EFI_ERROR (Status)) { - FreeAllList (SectionHead, CommentHead); - return Status; - } - - // - // Now get NumOfUpdate - // - Value = NULL; - Status = UpdateGetProfileString ( - SectionHead, - (UINT8 *) "Head", - (UINT8 *) "NumOfUpdate", - (UINT8 **) &Value - ); - if (Value == NULL) { - FreeAllList (SectionHead, CommentHead); - return EFI_NOT_FOUND; - } - Num = UpdateAtoi((UINT8 *) Value); - if (Num <= 0) { - FreeAllList (SectionHead, CommentHead); - return EFI_NOT_FOUND; - } - - *NumOfUpdates = Num; - *UpdateArray = AllocatePool ((sizeof (UPDATE_CONFIG_DATA) * Num)); - if (*UpdateArray == NULL) { - FreeAllList (SectionHead, CommentHead); - return EFI_OUT_OF_RESOURCES; - } - - for ( Index = 0 ; Index < *NumOfUpdates ; Index++) { - // - // Get the section name of each update - // - AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update"); - UpdateStrCatNumber ((UINT8 *) Entry, Index); - Value = NULL; - Status = UpdateGetProfileString ( - SectionHead, - (UINT8 *) "Head", - (UINT8 *) Entry, - (UINT8 **) &Value - ); - if (Value == NULL) { - FreeAllList (SectionHead, CommentHead); - return EFI_NOT_FOUND; - } - - // - // The section name of this update has been found. - // Now looks for all the config data of this update - // - SectionName = Value; - - // - // UpdateType - // - Value = NULL; - Status = UpdateGetProfileString ( - SectionHead, - (UINT8 *) SectionName, - (UINT8 *) "UpdateType", - (UINT8 **) &Value - ); - if (Value == NULL) { - FreeAllList (SectionHead, CommentHead); - return EFI_NOT_FOUND; - } - - Num = UpdateAtoi((UINT8 *) Value); - if (( Num >= (UINTN) UpdateOperationMaximum)) { - FreeAllList (SectionHead, CommentHead); - return Status; - } - (*UpdateArray)[Index].Index = Index; - (*UpdateArray)[Index].UpdateType = (UPDATE_OPERATION_TYPE) Num; - - // - // FvBaseAddress - // - Value = NULL; - Status = UpdateGetProfileString ( - SectionHead, - (UINT8 *) SectionName, - (UINT8 *) "FvBaseAddress", - (UINT8 **) &Value - ); - if (Value == NULL) { - FreeAllList (SectionHead, CommentHead); - return EFI_NOT_FOUND; - } - - Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value); - (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num; - - // - // FileBuid - // - Value = NULL; - Status = UpdateGetProfileString ( - SectionHead, - (UINT8 *) SectionName, - (UINT8 *) "FileGuid", - (UINT8 **) &Value - ); - if (Value == NULL) { - FreeAllList (SectionHead, CommentHead); - return EFI_NOT_FOUND; - } - - Status = UpdateStringToGuid ((UINT8 *) Value, &FileGuid); - if (EFI_ERROR (Status)) { - FreeAllList (SectionHead, CommentHead); - return Status; - } - CopyMem (&((*UpdateArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID)); - - // - // FaultTolerant - // Default value is FALSE - // - Value = NULL; - (*UpdateArray)[Index].FaultTolerant = FALSE; - Status = UpdateGetProfileString ( - SectionHead, - (UINT8 *) SectionName, - (UINT8 *) "FaultTolerant", - (UINT8 **) &Value - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - FreeAllList (SectionHead, CommentHead); - return Status; - } else if (Value != NULL) { - if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "TRUE") == 0) { - (*UpdateArray)[Index].FaultTolerant = TRUE; - } else if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "FALSE") == 0) { - (*UpdateArray)[Index].FaultTolerant = FALSE; - } - } - - if ((*UpdateArray)[Index].UpdateType == UpdateFvRange) { - // - // Length - // - Value = NULL; - Status = UpdateGetProfileString ( - SectionHead, - (UINT8 *) SectionName, - (UINT8 *) "Length", - (UINT8 **) &Value - ); - if (Value == NULL) { - FreeAllList (SectionHead, CommentHead); - return EFI_NOT_FOUND; - } - - Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value); - (*UpdateArray)[Index].Length = (UINTN) Num; - } - } - - // - // Now all configuration data got. Free those temporary buffers - // - FreeAllList (SectionHead, CommentHead); - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c deleted file mode 100644 index e1f1b023dc..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c +++ /dev/null @@ -1,846 +0,0 @@ -/** @file - Functions in this file will mainly focus on looking through the capsule - for the image to be programmed, and the flash area that is going to be - programed. - - Copyright (c) 2002 - 2014, Intel 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 "UpdateDriver.h" - -EFI_HII_HANDLE gHiiHandle; - -/** - Update the whole FV, or certain files in the FV. - - @param ConfigData Pointer to the config data on updating file. - @param ImageBuffer Image buffer to be updated. - @param ImageSize Image size. - @param FileType FFS file type. - @param FileAttributes FFS file attribute. - - @retval EFI_NOT_FOUND The matched FVB protocol is not found. - @retval EFI_SUCCESS The image buffer is updated into FV. - -**/ -EFI_STATUS -PerformUpdateOnFirmwareVolume ( - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINT8 *ImageBuffer, - IN UINTN ImageSize, - IN EFI_FV_FILETYPE FileType, - IN EFI_FV_FILE_ATTRIBUTES FileAttributes - ) -{ - EFI_STATUS Status; - BOOLEAN Found; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; - UINTN Index; - UINTN NumOfHandles; - EFI_HANDLE *HandleBuffer; - EFI_PHYSICAL_ADDRESS BaseAddress; - EFI_FVB_ATTRIBUTES_2 Attributes; - - // - // Locate all Fvb protocol - // - HandleBuffer = NULL; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiFirmwareVolumeBlockProtocolGuid, - NULL, - &NumOfHandles, - &HandleBuffer - ); - if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) { - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - } - return EFI_NOT_FOUND; - } - - // - // Check the FVB protocol one by one - // - Found = FALSE; - FvbProtocol = NULL; - for (Index = 0; Index < NumOfHandles; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiFirmwareVolumeBlockProtocolGuid, - (VOID **) &FvbProtocol - ); - if (EFI_ERROR (Status)) { - break; - } - - // - // Ensure this FVB protocol supported Write operation. - // - Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes); - if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) { - continue; - } - - Status = FvbProtocol->GetPhysicalAddress ( - FvbProtocol, - &BaseAddress - ); - if (EFI_ERROR (Status)) { - break; - } - if (BaseAddress == ConfigData->BaseAddress) { - Found = TRUE; - break; - } - } - - if (!Found) { - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - HandleBuffer = NULL; - } - return EFI_NOT_FOUND; - } - - // - // Now we have got the corresponding FVB protocol. Use the FVB protocol - // to update the whole FV, or certain files in the FV. - // - if (ConfigData->UpdateType == UpdateWholeFV) { - if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { - Status = EFI_INVALID_PARAMETER; - } else { - Status = PerformUpdateOnWholeFv ( - HandleBuffer[Index], - FvbProtocol, - ConfigData, - ImageBuffer, - ImageSize - ); - } - } else if (ConfigData->UpdateType == UpdateFvFile) { - Status = PerformUpdateOnFvFile ( - HandleBuffer[Index], - FvbProtocol, - ConfigData, - ImageBuffer, - ImageSize, - FileType, - FileAttributes - ); - } - - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - HandleBuffer = NULL; - } - - return Status; -} - -/** - Update the file directly into flash area. - - @param ConfigData Pointer to the config data on updating file. - @param ImageBuffer Image buffer to be updated. - @param ImageSize Image size. - - @retval EFI_SUCCESS The file is updated into flash area. - @retval EFI_NOT_FOUND The FVB protocol for the updated flash area is not found. - -**/ -EFI_STATUS -PerformUpdateOnFlashArea ( - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINT8 *ImageBuffer, - IN UINTN ImageSize - ) -{ - EFI_STATUS Status; - UINTN SizeLeft; - EFI_PHYSICAL_ADDRESS FlashAddress; - UINT8 *PtrImage; - BOOLEAN Found; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; - UINTN Index; - UINTN NumOfHandles; - EFI_HANDLE *HandleBuffer; - EFI_PHYSICAL_ADDRESS BaseAddress; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_HANDLE FvbHandle; - UINTN SizeUpdated; - CHAR16 *TmpStr; - EFI_FVB_ATTRIBUTES_2 Attributes; - - SizeLeft = ImageSize; - PtrImage = ImageBuffer; - FlashAddress = ConfigData->BaseAddress; - Status = EFI_SUCCESS; - HandleBuffer = NULL; - - // - // Print on screen - // - TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FLASH_RANGE), NULL); - if (TmpStr != NULL) { - Print (TmpStr, FlashAddress, ((UINT64)SizeLeft + FlashAddress)); - FreePool (TmpStr); - } - - // - // Locate all Fvb protocol - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiFirmwareVolumeBlockProtocolGuid, - NULL, - &NumOfHandles, - &HandleBuffer - ); - if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) { - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - } - return EFI_NOT_FOUND; - } - - while (SizeLeft > 0) { - // - // First get the FVB protocols. If the flash area is a FV, or sub FV, - // we can directly locate all the FVB protocol. Otherwise we should use - // implementation specific method to get the alternate FVB protocol - // - Found = FALSE; - FvbProtocol = NULL; - - // - // Check the FVB protocol one by one - // - for (Index = 0; Index < NumOfHandles; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiFirmwareVolumeBlockProtocolGuid, - (VOID **) &FvbProtocol - ); - if (EFI_ERROR (Status)) { - break; - } - - // - // Ensure this FVB protocol supported Write operation. - // - Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes); - if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) { - continue; - } - - Status = FvbProtocol->GetPhysicalAddress ( - FvbProtocol, - &BaseAddress - ); - if (EFI_ERROR (Status)) { - break; - } - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress; - - // - // This sub area entry falls in the range of the FV - // - if ((FlashAddress >= BaseAddress) && (FlashAddress < (BaseAddress + FwVolHeader->FvLength))) { - Found = TRUE; - break; - } - } - - if (!Found) { - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - HandleBuffer = NULL; - } - return EFI_NOT_FOUND; - } - - FvbHandle = HandleBuffer[Index]; - SizeUpdated = 0; - - // - // If the flash area is boot required, the update must be fault tolerant - // - if (ConfigData->FaultTolerant) { - // - // Finally we are here. We have got the corresponding FVB protocol. Now - // we need to convert the physical address to LBA and offset and call - // FTW write. Also check if the flash range is larger than the FV. - // - Status = FaultTolerantUpdateOnPartFv ( - PtrImage, - SizeLeft, - &SizeUpdated, - ConfigData, - FlashAddress, - FvbProtocol, - FvbHandle - ); - } else { - // - // Finally we are here. We have got the corresponding FVB protocol. Now - // we need to convert the physical address to LBA and offset and call - // FVB write. Also check if the flash range is larger than the FV. - // - Status = NonFaultTolerantUpdateOnPartFv ( - PtrImage, - SizeLeft, - &SizeUpdated, - FlashAddress, - FvbProtocol, - FvbHandle - ); - } - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // As part of the FV has been replaced, the FV driver shall re-parse - // the firmware volume. So re-install FVB protocol here - // - Status = gBS->ReinstallProtocolInterface ( - FvbHandle, - &gEfiFirmwareVolumeBlockProtocolGuid, - FvbProtocol, - FvbProtocol - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Check if we are done with the update - // - SizeLeft = SizeLeft - SizeUpdated; - FlashAddress = FlashAddress + SizeUpdated; - PtrImage = PtrImage + SizeUpdated; - } - - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - HandleBuffer = NULL; - } - - return Status; -} - -/** - Find the updated file, and program it into the flash area based on the config data. - - @param FwVolProtocol Pointer to FV protocol that contains the updated file. - @param ConfigData Pointer to the Config Data on updating file. - - @retval EFI_INVALID_PARAMETER The update operation is not valid. - @retval EFI_NOT_FOUND The updated file is not found. - @retval EFI_SUCCESS The file is updated into the flash area. - -**/ -EFI_STATUS -PerformUpdate ( - IN EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol, - IN UPDATE_CONFIG_DATA *ConfigData - ) -{ - EFI_STATUS Status; - UINT8 *FileBuffer; - UINTN FileBufferSize; - EFI_FV_FILETYPE FileType; - EFI_FV_FILE_ATTRIBUTES Attrib; - EFI_SECTION_TYPE SectionType; - UINT32 AuthenticationStatus; - CHAR16 *TmpStr; - BOOLEAN StartToUpdate; - - Status = EFI_SUCCESS; - FileBuffer = NULL; - FileBufferSize = 0; - Status = FwVolProtocol->ReadFile ( - FwVolProtocol, - &(ConfigData->FileGuid), - (VOID **) &FileBuffer, - &FileBufferSize, - &FileType, - &Attrib, - &AuthenticationStatus - ); - if (EFI_ERROR (Status)) { - return Status; - } - - StartToUpdate = FALSE; - - // - // Check if the update image is the one we require - // and then perform the update - // - switch (ConfigData->UpdateType) { - - case UpdateWholeFV: - - // - // For UpdateWholeFv, the update file shall be a firmware volume - // image file. - // - if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { - DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be of TYPE EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n")); - Status = EFI_INVALID_PARAMETER; - } else { - if (FileBuffer != NULL) { - FreePool (FileBuffer); - } - SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; - FileBuffer = NULL; - FileBufferSize = 0; - Status = FwVolProtocol->ReadSection ( - FwVolProtocol, - &(ConfigData->FileGuid), - SectionType, - 0, - (VOID **) &FileBuffer, - &FileBufferSize, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - // - // Execute the update. For UpdateWholeFv, the update - // will always execute on a whole FV - // - StartToUpdate = TRUE; - Status = PerformUpdateOnFirmwareVolume ( - ConfigData, - FileBuffer, - FileBufferSize, - FileType, - Attrib - ); - - } else { - DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be sectioned with TYPE EFI_SECTION_FIRMWARE_VOLUME_IMAGE\n")); - } - } - break; - - case UpdateFvRange: - - // - // For UpdateFvRange, the update file shall be a raw file - // which does not contain any sections. The contents of the file - // will be directly programmed. - // - if (FileType != EFI_FV_FILETYPE_RAW) { - DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should of TYPE EFI_FV_FILETYPE_RAW\n")); - Status = EFI_INVALID_PARAMETER; - } else { - // - // For UpdateFvRange, the update may be performed on a sub area - // of a certain FV, or a flash area that is not FV, or part of FV. - // The update may also go across more than one FVs. - // - StartToUpdate = TRUE; - Status = PerformUpdateOnFlashArea ( - ConfigData, - FileBuffer, - FileBufferSize - ); - } - break; - - case UpdateFvFile: - - // - // No check will be done the the file got. The contents of the file - // will be directly programmed. - // Though UpdateFvFile will only update a single file, but the update - // will always execute on a FV - // - StartToUpdate = TRUE; - Status = PerformUpdateOnFirmwareVolume ( - ConfigData, - FileBuffer, - FileBufferSize, - FileType, - Attrib - ); - break; - - default: - Status = EFI_INVALID_PARAMETER; - } - - if (StartToUpdate) { - if (EFI_ERROR (Status)) { - TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_ABORTED), NULL); - } else { - TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_DONE), NULL); - } - if (TmpStr != NULL) { - Print (TmpStr); - FreePool (TmpStr); - } - } - - if (FileBuffer != NULL) { - FreePool(FileBuffer); - FileBuffer = NULL; - } - - return Status; -} - -/** - Process the input firmware volume by using DXE service ProcessFirmwareVolume. - - @param DataBuffer Point to the FV image to be processed. - @param BufferSize Size of the FV image buffer. - @param FwVolProtocol Point to the installed FV protocol for the input FV image. - - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_VOLUME_CORRUPTED FV image is corrupted. - @retval EFI_SUCCESS FV image is processed and FV protocol is installed. - -**/ -EFI_STATUS -ProcessUpdateImage ( - UINT8 *DataBuffer, - UINTN BufferSize, - EFI_FIRMWARE_VOLUME2_PROTOCOL **FwVolProtocol - ) -{ - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_HANDLE FwVolHandle; - EFI_STATUS Status; - UINT8 *ProcessedDataBuffer; - UINT32 FvAlignment; - - ProcessedDataBuffer = NULL; - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DataBuffer; - if (FwVolHeader->FvLength != BufferSize) { - return EFI_VOLUME_CORRUPTED; - } - - FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); - // - // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value. - // - if (FvAlignment < 8) { - FvAlignment = 8; - } - // - // Check FvImage Align is required. - // - if (((UINTN) FwVolHeader % FvAlignment) == 0) { - ProcessedDataBuffer = DataBuffer; - } else { - // - // Allocate new aligned buffer to store DataBuffer. - // - ProcessedDataBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment); - if (ProcessedDataBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem (ProcessedDataBuffer, DataBuffer, BufferSize); - } - // - // Process the firmware volume - // - gDS->ProcessFirmwareVolume ( - ProcessedDataBuffer, - BufferSize, - &FwVolHandle - ); - - // - // Get the FwVol protocol - // - Status = gBS->HandleProtocol ( - FwVolHandle, - &gEfiFirmwareVolume2ProtocolGuid, - (VOID **) FwVolProtocol - ); - - return Status; -} - -/** - Find the image in the same FV and program it in a target Firmware Volume device. - After update image, it will reset system and no return. - - @param ImageHandle A handle for the image that is initializing this driver - @param SystemTable A pointer to the EFI system table - - @retval EFI_ABORTED System reset failed. - @retval EFI_NOT_FOUND The updated image is not found in the same FV. - -**/ -EFI_STATUS -EFIAPI -InitializeUpdateDriver ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol; - EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol; - EFI_FIRMWARE_VOLUME2_PROTOCOL *DataFwVolProtocol; - MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode; - MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *AlignedDevPathNode; - EFI_DEVICE_PATH_PROTOCOL *FilePathNode; - EFI_SECTION_TYPE SectionType; - UINT8 *FileBuffer; - UINTN FileBufferSize; - EFI_FV_FILETYPE FileType; - EFI_FV_FILE_ATTRIBUTES Attrib; - UINT32 AuthenticationStatus; - UPDATE_CONFIG_DATA *ConfigData; - UPDATE_CONFIG_DATA *UpdateConfigData; - UINTN NumOfUpdates; - UINTN Index; - CHAR16 *TmpStr; - - // - // Clear screen - // - if (gST->ConOut != NULL) { - gST->ConOut->ClearScreen (gST->ConOut); - gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT); - gST->ConOut->EnableCursor (gST->ConOut, FALSE); - } - - gHiiHandle = HiiAddPackages ( - &gEfiCallerIdGuid, - NULL, - UpdateDriverDxeStrings, - NULL - ); - ASSERT (gHiiHandle != NULL); - - // - // In order to look for the update data file and programmed image file - // from the same volume which this driver is dispatched from, we need - // to get the device path of this driver image. It is done by first - // locate the LoadedImageProtocol and then get its device path - // - Status = gBS->OpenProtocol ( - ImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID **)&LoadedImageProtocol, - ImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Get the firmware volume protocol where this file resides - // - Status = gBS->HandleProtocol ( - LoadedImageProtocol->DeviceHandle, - &gEfiFirmwareVolume2ProtocolGuid, - (VOID **) &FwVolProtocol - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - - // - // Shall do some extra check to see if it is really contained in the FV? - // Should be able to find the section of this driver in the the FV. - // - FilePathNode = LoadedImageProtocol->FilePath; - FwVolFilePathNode = NULL; - while (!IsDevicePathEnd (FilePathNode)) { - if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePathNode)!= NULL) { - FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePathNode; - break; - } - FilePathNode = NextDevicePathNode (FilePathNode); - } - - if (FwVolFilePathNode != NULL) { - AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength (FwVolFilePathNode), FwVolFilePathNode); - - SectionType = EFI_SECTION_PE32; - FileBuffer = NULL; - FileBufferSize = 0; - Status = FwVolProtocol->ReadSection ( - FwVolProtocol, - &(AlignedDevPathNode->FvFileName), - SectionType, - 0, - (VOID **) &FileBuffer, - &FileBufferSize, - &AuthenticationStatus - ); - if (EFI_ERROR (Status)) { - FreePool (AlignedDevPathNode); - return Status; - } - - if (FileBuffer != NULL) { - FreePool(FileBuffer); - FileBuffer = NULL; - } - - // - // Check the NameGuid of the udpate driver so that it can be - // used as the CallerId in fault tolerant write protocol - // - if (!CompareGuid (&gEfiCallerIdGuid, &(AlignedDevPathNode->FvFileName))) { - FreePool (AlignedDevPathNode); - return EFI_NOT_FOUND; - } - FreePool (AlignedDevPathNode); - } else { - return EFI_NOT_FOUND; - } - - // - // Now try to find the script file. The script file is usually - // a raw data file which does not contain any sections. - // - FileBuffer = NULL; - FileBufferSize = 0; - Status = FwVolProtocol->ReadFile ( - FwVolProtocol, - &gEfiConfigFileNameGuid, - (VOID **) &FileBuffer, - &FileBufferSize, - &FileType, - &Attrib, - &AuthenticationStatus - ); - if (EFI_ERROR (Status)) { - return Status; - } - if (FileType != EFI_FV_FILETYPE_RAW) { - return EFI_NOT_FOUND; - } - - // - // Parse the configuration file. - // - ConfigData = NULL; - NumOfUpdates = 0; - Status = ParseUpdateDataFile ( - FileBuffer, - FileBufferSize, - &NumOfUpdates, - &ConfigData - ); - if (FileBuffer != NULL) { - FreePool (FileBuffer); - FileBuffer = NULL; - } - if (EFI_ERROR (Status)) { - return Status; - } - ASSERT (ConfigData != NULL); - - // - // Now find the update image. The update image should be put in a FV, and then - // encapsulated as a raw FFS file. This is to prevent the update image from - // being dispatched. So the raw data we get here should be an FV. We need to - // process this FV and read the files that is going to be updated. - // - FileBuffer = NULL; - FileBufferSize = 0; - Status = FwVolProtocol->ReadFile ( - FwVolProtocol, - &gEfiUpdateDataFileGuid, - (VOID **) &FileBuffer, - &FileBufferSize, - &FileType, - &Attrib, - &AuthenticationStatus - ); - if (EFI_ERROR (Status)) { - return Status; - } - if (FileType != EFI_FV_FILETYPE_RAW) { - return EFI_NOT_FOUND; - } - - // - // FileBuffer should be an FV. Process the FV - // - DataFwVolProtocol = NULL; - Status = ProcessUpdateImage ( - FileBuffer, - FileBufferSize, - &DataFwVolProtocol - ); - if (EFI_ERROR (Status)) { - FreePool (FileBuffer); - return Status; - } - - // - // Print on screen - // - TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_PROCESS_DATA), NULL); - if (TmpStr != NULL) { - Print (TmpStr); - FreePool(TmpStr); - } - - // - // Execute the update - // - Index = 0; - UpdateConfigData = ConfigData; - while (Index < NumOfUpdates) { - Status = PerformUpdate ( - DataFwVolProtocol, - UpdateConfigData - ); - // - // Shall updates be serialized so that if an update is not successfully completed, - // the remaining updates won't be performed. - // - if (EFI_ERROR (Status)) { - break; - } - - Index++; - UpdateConfigData++; - } - - if (EFI_ERROR (Status)) { - if (ConfigData != NULL) { - FreePool(ConfigData); - ConfigData = NULL; - } - return Status; - } - - // - // Call system reset - // - gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); - - // - // Hopefully it won't be reached - // - return EFI_ABORTED; -} diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriver.h b/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriver.h deleted file mode 100644 index e1f22a9d5a..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriver.h +++ /dev/null @@ -1,213 +0,0 @@ -/** @file - Common defines and definitions for a component update driver. - - Copyright (c) 2002 - 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 _EFI_UPDATE_DRIVER_H_ -#define _EFI_UPDATE_DRIVER_H_ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern EFI_HII_HANDLE gHiiHandle; - -typedef enum { - UpdateWholeFV = 0, // 0, update whole FV - UpdateFvFile, // 1, update a set of FV files asynchronously - UpdateFvRange, // 2, update part of FV or flash - UpdateOperationMaximum // 3 -} UPDATE_OPERATION_TYPE; - -typedef struct { - UINTN Index; - UPDATE_OPERATION_TYPE UpdateType; - EFI_DEVICE_PATH_PROTOCOL DevicePath; - EFI_PHYSICAL_ADDRESS BaseAddress; - EFI_GUID FileGuid; - UINTN Length; - BOOLEAN FaultTolerant; -} UPDATE_CONFIG_DATA; - -typedef struct _SECTION_ITEM SECTION_ITEM; -struct _SECTION_ITEM { - CHAR8 *ptrSection; - UINTN SecNameLen; - CHAR8 *ptrEntry; - CHAR8 *ptrValue; - SECTION_ITEM *ptrNext; -}; - -typedef struct _COMMENT_LINE COMMENT_LINE; -struct _COMMENT_LINE { - CHAR8 *ptrComment; - COMMENT_LINE *ptrNext; -}; - -typedef struct { - EFI_GUID FileGuid; -} UPDATE_PRIVATE_DATA; - -#define MAX_LINE_LENGTH 512 -#define EFI_D_UPDATE EFI_D_ERROR - -#define MIN_ALIGNMENT_SIZE 4 -#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0) - -/** - Parse Config data file to get the updated data array. - - @param DataBuffer Config raw file buffer. - @param BufferSize Size of raw buffer. - @param NumOfUpdates Pointer to the number of update data. - @param UpdateArray Pointer to the config of update data. - - @retval EFI_NOT_FOUND No config data is found. - @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. - @retval EFI_SUCCESS Parse the config file successfully. - -**/ -EFI_STATUS -ParseUpdateDataFile ( - IN UINT8 *DataBuffer, - IN UINTN BufferSize, - IN OUT UINTN *NumOfUpdates, - IN OUT UPDATE_CONFIG_DATA **UpdateArray - ); - -/** - Update the whole FV image, and reinsall FVB protocol for the updated FV image. - - @param FvbHandle Handle of FVB protocol for the updated flash range. - @param FvbProtocol FVB protocol. - @param ConfigData Config data on updating driver. - @param ImageBuffer Image buffer to be updated. - @param ImageSize Image size. - - @retval EFI_INVALID_PARAMETER Update type is not UpdateWholeFV. - Or Image size is not same to the size of whole FV. - @retval EFI_OUT_OF_RESOURCES No enoug memory is allocated. - @retval EFI_SUCCESS FV image is updated, and its FVB protocol is reinstalled. - -**/ -EFI_STATUS -PerformUpdateOnWholeFv ( - IN EFI_HANDLE FvbHandle, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINT8 *ImageBuffer, - IN UINTN ImageSize - ); - -/** - Update certain file in the FV. - - @param FvbHandle Handle of FVB protocol for the updated flash range. - @param FvbProtocol FVB protocol. - @param ConfigData Config data on updating driver. - @param ImageBuffer Image buffer to be updated. - @param ImageSize Image size. - @param FileType FFS file type. - @param FileAttributes FFS file attribute - - @retval EFI_INVALID_PARAMETER Update type is not UpdateFvFile. - Or Image size is not same to the size of whole FV. - @retval EFI_UNSUPPORTED PEIM FFS is unsupported to be updated. - @retval EFI_SUCCESS The FFS file is added into FV. - -**/ -EFI_STATUS -PerformUpdateOnFvFile ( - IN EFI_HANDLE FvbHandle, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN UPDATE_CONFIG_DATA *ConfigData, - IN UINT8 *ImageBuffer, - IN UINTN ImageSize, - IN EFI_FV_FILETYPE FileType, - IN EFI_FV_FILE_ATTRIBUTES FileAttributes - ); - -/** - Update the buffer into flash area in fault tolerant write method. - - @param ImageBuffer Image buffer to be updated. - @param SizeLeft Size of the image buffer. - @param UpdatedSize Size of the updated buffer. - @param ConfigData Config data on updating driver. - @param FlashAddress Flash address to be updated as start address. - @param FvbProtocol FVB protocol. - @param FvbHandle Handle of FVB protocol for the updated flash range. - - @retval EFI_SUCCESS Buffer data is updated into flash. - @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area. - @retval EFI_NOT_FOUND FTW protocol doesn't exist. - @retval EFI_OUT_OF_RESOURCES No enough backup space. - @retval EFI_ABORTED Error happen when update flash area. - -**/ -EFI_STATUS -FaultTolerantUpdateOnPartFv ( - IN UINT8 *ImageBuffer, - IN UINTN SizeLeft, - IN OUT UINTN *UpdatedSize, - IN UPDATE_CONFIG_DATA *ConfigData, - IN EFI_PHYSICAL_ADDRESS FlashAddress, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN EFI_HANDLE FvbHandle - ); - -/** - Directly update the buffer into flash area without fault tolerant write method. - - @param ImageBuffer Image buffer to be updated. - @param SizeLeft Size of the image buffer. - @param UpdatedSize Size of the updated buffer. - @param FlashAddress Flash address to be updated as start address. - @param FvbProtocol FVB protocol. - @param FvbHandle Handle of FVB protocol for the updated flash range. - - @retval EFI_SUCCESS Buffer data is updated into flash. - @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area. - @retval EFI_OUT_OF_RESOURCES No enough backup space. - -**/ -EFI_STATUS -NonFaultTolerantUpdateOnPartFv ( - IN UINT8 *ImageBuffer, - IN UINTN SizeLeft, - IN OUT UINTN *UpdatedSize, - IN EFI_PHYSICAL_ADDRESS FlashAddress, - IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol, - IN EFI_HANDLE FvbHandle - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf b/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf deleted file mode 100644 index d83a1ecb57..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf +++ /dev/null @@ -1,76 +0,0 @@ -## @file -# Update Driver for Capulse update. -# -# This driver is intended to be put in a capsule (FV). If all goes well, -# then it should be dispatched from the capsule FV, then find the image -# in the same FV and program it in a target Firmware Volume device. -# -# 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 -# 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 = UpdateDriverDxe - MODULE_UNI_FILE = UpdateDriverDxe.uni - FILE_GUID = 0E84FC69-29CC-4C6D-92AC-6D476921850F - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializeUpdateDriver - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - UpdateDriver.h - UpdateStrings.uni - UpdateDispatcher.c - ParseUpdateProfile.c - FlashUpdate.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - BaseLib - PrintLib - HiiLib - DxeServicesTableLib - MemoryAllocationLib - UefiLib - UefiBootServicesTableLib - UefiDriverEntryPoint - UefiRuntimeServicesTableLib - BaseMemoryLib - DebugLib - DevicePathLib - -[Guids] - gEfiConfigFileNameGuid ## CONSUMES ## File # FileName to store ConfigFile - gEfiUpdateDataFileGuid ## CONSUMES ## File # FileName to store Capsule Data. - -[Protocols] - gEfiFaultTolerantWriteProtocolGuid ## CONSUMES - gEfiFirmwareVolume2ProtocolGuid ## CONSUMES - gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES - gEfiLoadedImageProtocolGuid ## CONSUMES - -[Depex] - gEfiFirmwareVolumeBlockProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid - -[UserExtensions.TianoCore."ExtraFiles"] - UpdateDriverDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.uni b/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.uni deleted file mode 100644 index dd37abe216..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxeExtra.uni b/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxeExtra.uni deleted file mode 100644 index a01d23de84..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateStrings.uni b/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateStrings.uni deleted file mode 100644 index 16455937e5..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateStrings.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegion.c b/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegion.c deleted file mode 100644 index e432cf4403..0000000000 --- a/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegion.c +++ /dev/null @@ -1,170 +0,0 @@ -/** @file - Produces the Legacy Region Protocol. - - This generic implementation of the Legacy Region Protocol does not actually - perform any lock/unlock operations. This module may be used on platforms - that do not provide HW locking of the legacy memory regions. It can also - be used as a template driver for implementing the Legacy Region Protocol on - a platform that does support HW locking of the legacy memory regions. - -Copyright (c) 2009, Intel 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 - -/** - Sets hardware to decode or not decode a region. - - @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance - @param Start Start of region to decode. - @param Length Size in bytes of the region. - @param On Decode/nondecode flag. - - @retval EFI_SUCCESS Decode range successfully changed. - -**/ -EFI_STATUS -EFIAPI -LegacyRegionDecode ( - IN EFI_LEGACY_REGION_PROTOCOL *This, - IN UINT32 Start, - IN UINT32 Length, - IN BOOLEAN *On - ) -{ - return EFI_SUCCESS; -} - -/** - Sets a region to read only. - - @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance - @param Start Start of region to lock. - @param Length Size in bytes of the region. - @param Granularity Lock attribute affects this granularity in bytes. - - @retval EFI_SUCCESS The region was made read only. - -**/ -EFI_STATUS -EFIAPI -LegacyRegionLock ( - IN EFI_LEGACY_REGION_PROTOCOL *This, - IN UINT32 Start, - IN UINT32 Length, - OUT UINT32 *Granularity OPTIONAL - ) -{ - return EFI_SUCCESS; -} - -/** - Sets a region to read only and ensures that flash is locked from being - inadvertently modified. - - @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance - @param Start Start of region to lock. - @param Length Size in bytes of the region. - @param Granularity Lock attribute affects this granularity in bytes. - - @retval EFI_SUCCESS The region was made read only and flash is locked. - -**/ -EFI_STATUS -EFIAPI -LegacyRegionBootLock ( - IN EFI_LEGACY_REGION_PROTOCOL *This, - IN UINT32 Start, - IN UINT32 Length, - OUT UINT32 *Granularity OPTIONAL - ) -{ - return EFI_SUCCESS; -} - -/** - Sets a region to read-write. - - @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance - @param Start Start of region to lock. - @param Length Size in bytes of the region. - @param Granularity Lock attribute affects this granularity in bytes. - - @retval EFI_SUCCESS The region was successfully made read-write. - -**/ -EFI_STATUS -EFIAPI -LegacyRegionUnlock ( - IN EFI_LEGACY_REGION_PROTOCOL *This, - IN UINT32 Start, - IN UINT32 Length, - OUT UINT32 *Granularity OPTIONAL - ) -{ - return EFI_SUCCESS; -} - -// -// Module global for the handle the Legacy Region Protocol is installed -// -EFI_HANDLE mLegacyRegionHandle = NULL; - -// -// Module global for the Legacy Region Protocol instance that is installed onto -// mLegacyRegionHandle -// -EFI_LEGACY_REGION_PROTOCOL mLegacyRegion = { - LegacyRegionDecode, - LegacyRegionLock, - LegacyRegionBootLock, - LegacyRegionUnlock -}; - -/** - The user Entry Point for module LegacyRegionDxe. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -LegacyRegionInstall ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Make sure the Legacy Region Protocol is not already installed in the system - // - ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiLegacyRegionProtocolGuid); - - // - // Install the protocol on a new handle. - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &mLegacyRegionHandle, - &gEfiLegacyRegionProtocolGuid, &mLegacyRegion, - NULL - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf b/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf deleted file mode 100644 index f8e5639dec..0000000000 --- a/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf +++ /dev/null @@ -1,55 +0,0 @@ -## @file -# Produces Framework Legacy Region Protocol. -# -# This generic implementation of the Legacy Region Protocol does not actually -# perform any lock/unlock operations. This module may be used on platforms -# that do not provide HW locking of the legacy memory regions. It can also -# be used as a template driver for implementing the Legacy Region Protocol on -# a platform that does support HW locking of the legacy memory regions. -# -# 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 -# 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 = LegacyRegionDxe - MODULE_UNI_FILE = LegacyRegionDxe.uni - FILE_GUID = 8C439043-85CA-467a-96F1-CB14F4D0DCDA - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = LegacyRegionInstall - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - LegacyRegion.c - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - -[LibraryClasses] - UefiDriverEntryPoint - DebugLib - UefiBootServicesTableLib - -[Protocols] - gEfiLegacyRegionProtocolGuid ## PRODUCES - -[Depex] - TRUE - -[UserExtensions.TianoCore."ExtraFiles"] - LegacyRegionDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.uni b/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.uni deleted file mode 100644 index a0746e961a..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxeExtra.uni b/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxeExtra.uni deleted file mode 100644 index b04851c0d2..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c b/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c deleted file mode 100644 index 76aec0ac2c..0000000000 --- a/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtraction.c +++ /dev/null @@ -1,1456 +0,0 @@ -/** @file - Section Extraction Protocol implementation. - - Stream database is implemented as a linked list of section streams, - where each stream contains a linked list of children, which may be leaves or - encapsulations. - - Children that are encapsulations generate new stream entries - when they are created. Streams can also be created by calls to - SEP->OpenSectionStream(). - - The database is only created far enough to return the requested data from - any given stream, or to determine that the requested data is not found. - - If a GUIDed encapsulation is encountered, there are three possiblilites. - - 1) A support protocol is found, in which the stream is simply processed with - the support protocol. - - 2) A support protocol is not found, but the data is available to be read - without processing. In this case, the database is built up through the - recursions to return the data, and a RPN event is set that will enable - the stream in question to be refreshed if and when the required section - extraction protocol is published.This insures the AuthenticationStatus - does not become stale in the cache. - - 3) A support protocol is not found, and the data is not available to be read - without it. This results in EFI_PROTOCOL_ERROR. - -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 -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 - -// -// Local defines and typedefs -// -#define FRAMEWORK_SECTION_CHILD_SIGNATURE SIGNATURE_32('S','X','F','S') -#define CHILD_SECTION_NODE_FROM_LINK(Node) \ - CR (Node, FRAMEWORK_SECTION_CHILD_NODE, Link, FRAMEWORK_SECTION_CHILD_SIGNATURE) - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - UINT32 Type; - UINT32 Size; - // - // StreamBase + OffsetInStream == pointer to section header in stream. The - // stream base is always known when walking the sections within. - // - UINT32 OffsetInStream; - // - // Then EncapsulatedStreamHandle below is always 0 if the section is NOT an - // encapsulating section. Otherwise, it contains the stream handle - // of the encapsulated stream. This handle is ALWAYS produced any time an - // encapsulating child is encountered, irrespective of whether the - // encapsulated stream is processed further. - // - UINTN EncapsulatedStreamHandle; - EFI_GUID *EncapsulationGuid; - // - // If the section REQUIRES an extraction protocol, register for RPN - // when the required GUIDed extraction protocol becomes available. - // - EFI_EVENT Event; -} FRAMEWORK_SECTION_CHILD_NODE; - -#define FRAMEWORK_SECTION_STREAM_SIGNATURE SIGNATURE_32('S','X','S','S') -#define STREAM_NODE_FROM_LINK(Node) \ - CR (Node, FRAMEWORK_SECTION_STREAM_NODE, Link, FRAMEWORK_SECTION_STREAM_SIGNATURE) - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - UINTN StreamHandle; - UINT8 *StreamBuffer; - UINTN StreamLength; - LIST_ENTRY Children; - // - // Authentication status is from GUIDed encapsulations. - // - UINT32 AuthenticationStatus; -} FRAMEWORK_SECTION_STREAM_NODE; - -#define NULL_STREAM_HANDLE 0 - -typedef struct { - FRAMEWORK_SECTION_CHILD_NODE *ChildNode; - FRAMEWORK_SECTION_STREAM_NODE *ParentStream; - VOID *Registration; -} RPN_EVENT_CONTEXT; - -/** - SEP member function. This function creates and returns a new section stream - handle to represent the new section stream. - - @param This Indicates the calling context. - @param SectionStreamLength Size in bytes of the section stream. - @param SectionStream Buffer containing the new section stream. - @param SectionStreamHandle A pointer to a caller allocated UINTN that on output - contains the new section stream handle. - - @retval EFI_SUCCESS Section wase opened successfully. - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. - @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of - last section. - -**/ -EFI_STATUS -EFIAPI -OpenSectionStream ( - IN EFI_SECTION_EXTRACTION_PROTOCOL *This, - IN UINTN SectionStreamLength, - IN VOID *SectionStream, - OUT UINTN *SectionStreamHandle - ) -; - -/** - SEP member function. Retrieves requested section from section stream. - - @param This Pointer to SEP instance. - @param SectionStreamHandle The section stream from which to extract the requested - section. - @param SectionType A pointer to the type of section to search for. - @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED, then - SectionDefinitionGuid indicates which of these types - of sections to search for. - @param SectionInstance Indicates which instance of the requested section to - return. - @param Buffer Double indirection to buffer. If *Buffer is non-null on - input, then the buffer is caller allocated. If - *Buffer is NULL, then the buffer is callee allocated. - In either case, the requried buffer size is returned - in *BufferSize. - @param BufferSize On input, indicates the size of *Buffer if *Buffer is - non-null on input. On output, indicates the required - size (allocated size if callee allocated) of *Buffer. - @param AuthenticationStatus Indicates the authentication status of the retrieved - section. - - - @retval EFI_SUCCESS Section was retrieved successfully - @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the section - stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED - bit set, but there was no corresponding GUIDed Section - Extraction Protocol in the handle database. *Buffer is - unmodified. - @retval EFI_NOT_FOUND An error was encountered when parsing the SectionStream. - This indicates the SectionStream is not correctly - formatted. - @retval EFI_NOT_FOUND The requested section does not exist. - @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process the - request. - @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist. - @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is - insufficient to contain the requested section. The - input buffer is filled and contents are section contents - are truncated. - -**/ -EFI_STATUS -EFIAPI -GetSection ( - IN EFI_SECTION_EXTRACTION_PROTOCOL *This, - IN UINTN SectionStreamHandle, - IN EFI_SECTION_TYPE *SectionType, - IN EFI_GUID *SectionDefinitionGuid, - IN UINTN SectionInstance, - IN VOID **Buffer, - IN OUT UINTN *BufferSize, - OUT UINT32 *AuthenticationStatus - ) -; - -/** - SEP member function. Deletes an existing section stream - - @param This Indicates the calling context. - @param StreamHandleToClose Indicates the stream to close - - @retval EFI_SUCCESS Section stream was closed successfully. - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. - @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of - last section. - -**/ -EFI_STATUS -EFIAPI -CloseSectionStream ( - IN EFI_SECTION_EXTRACTION_PROTOCOL *This, - IN UINTN StreamHandleToClose - ) -; - -// -// Module globals -// -LIST_ENTRY mStreamRoot = INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot); - -EFI_HANDLE mSectionExtractionHandle = NULL; - -EFI_SECTION_EXTRACTION_PROTOCOL mSectionExtraction = { - OpenSectionStream, - GetSection, - CloseSectionStream -}; - -/** - Entry point of the section extraction code. Initializes an instance of the - section extraction interface and installs it on a new handle. - - @param ImageHandle A handle for the image that is initializing this driver - @param SystemTable A pointer to the EFI system table - - @retval EFI_SUCCESS Driver initialized successfully - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources - -**/ -EFI_STATUS -EFIAPI -SectionExtractionEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install SEP to a new handle - // - Status = gBS->InstallProtocolInterface ( - &mSectionExtractionHandle, - &gEfiSectionExtractionProtocolGuid, - EFI_NATIVE_INTERFACE, - &mSectionExtraction - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} - -/** - - Check if a stream is valid. - - @param SectionStream The section stream to be checked - @param SectionStreamLength The length of section stream - - @return A boolean value indicating the validness of the section stream. - -**/ -BOOLEAN -IsValidSectionStream ( - IN VOID *SectionStream, - IN UINTN SectionStreamLength - ) -{ - UINTN TotalLength; - UINTN SectionLength; - EFI_COMMON_SECTION_HEADER *SectionHeader; - EFI_COMMON_SECTION_HEADER *NextSectionHeader; - - TotalLength = 0; - SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream; - - while (TotalLength < SectionStreamLength) { - if (IS_SECTION2 (SectionHeader)) { - SectionLength = SECTION2_SIZE (SectionHeader); - } else { - SectionLength = SECTION_SIZE (SectionHeader); - } - TotalLength += SectionLength; - - if (TotalLength == SectionStreamLength) { - return TRUE; - } - - // - // Move to the next byte following the section... - // - SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength); - - // - // Figure out where the next section begins - // - NextSectionHeader = ALIGN_POINTER(SectionHeader, 4); - TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader; - SectionHeader = NextSectionHeader; - } - - ASSERT (FALSE); - return FALSE; -} - -/** - Worker function. Constructor for section streams. - - @param SectionStreamLength Size in bytes of the section stream. - @param SectionStream Buffer containing the new section stream. - @param AllocateBuffer Indicates whether the stream buffer is to be copied - or the input buffer is to be used in place. - @param AuthenticationStatus Indicates the default authentication status for the - new stream. - @param SectionStreamHandle A pointer to a caller allocated section stream handle. - - @retval EFI_SUCCESS Stream was added to stream database. - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. - -**/ -EFI_STATUS -OpenSectionStreamEx ( - IN UINTN SectionStreamLength, - IN VOID *SectionStream, - IN BOOLEAN AllocateBuffer, - IN UINT32 AuthenticationStatus, - OUT UINTN *SectionStreamHandle - ) -{ - FRAMEWORK_SECTION_STREAM_NODE *NewStream; - EFI_TPL OldTpl; - - // - // Allocate a new stream - // - NewStream = AllocatePool (sizeof (FRAMEWORK_SECTION_STREAM_NODE)); - if (NewStream == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - if (AllocateBuffer) { - // - // if we're here, we're double buffering, allocate the buffer and copy the - // data in - // - if (SectionStreamLength > 0) { - NewStream->StreamBuffer = AllocatePool (SectionStreamLength); - if (NewStream->StreamBuffer == NULL) { - FreePool (NewStream); - return EFI_OUT_OF_RESOURCES; - } - // - // Copy in stream data - // - CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength); - } else { - // - // It's possible to have a zero length section stream. - // - NewStream->StreamBuffer = NULL; - } - } else { - // - // If were here, the caller has supplied the buffer (it's an internal call) - // so just assign the buffer. This happens when we open section streams - // as a result of expanding an encapsulating section. - // - NewStream->StreamBuffer = SectionStream; - } - - // - // Initialize the rest of the section stream - // - NewStream->Signature = FRAMEWORK_SECTION_STREAM_SIGNATURE; - NewStream->StreamHandle = (UINTN) NewStream; - NewStream->StreamLength = SectionStreamLength; - InitializeListHead (&NewStream->Children); - NewStream->AuthenticationStatus = AuthenticationStatus; - - // - // Add new stream to stream list - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - InsertTailList (&mStreamRoot, &NewStream->Link); - gBS->RestoreTPL (OldTpl); - - *SectionStreamHandle = NewStream->StreamHandle; - - return EFI_SUCCESS; -} - -/** - SEP member function. This function creates and returns a new section stream - handle to represent the new section stream. - - @param This Indicates the calling context. - @param SectionStreamLength Size in bytes of the section stream. - @param SectionStream Buffer containing the new section stream. - @param SectionStreamHandle A pointer to a caller allocated UINTN that on output - contains the new section stream handle. - - @retval EFI_SUCCESS Section wase opened successfully. - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. - @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of - last section. - -**/ -EFI_STATUS -EFIAPI -OpenSectionStream ( - IN EFI_SECTION_EXTRACTION_PROTOCOL *This, - IN UINTN SectionStreamLength, - IN VOID *SectionStream, - OUT UINTN *SectionStreamHandle - ) -{ - // - // Check to see section stream looks good... - // - if (!IsValidSectionStream (SectionStream, SectionStreamLength)) { - return EFI_INVALID_PARAMETER; - } - - return OpenSectionStreamEx ( - SectionStreamLength, - SectionStream, - TRUE, - 0, - SectionStreamHandle - ); -} - -/** - Worker function. Determine if the input stream:child matches the input type. - - @param Stream Indicates the section stream associated with the child - @param Child Indicates the child to check - @param SearchType Indicates the type of section to check against for - @param SectionDefinitionGuid Indicates the GUID to check against if the type is - EFI_SECTION_GUID_DEFINED - - @retval TRUE The child matches - @retval FALSE The child doesn't match - -**/ -BOOLEAN -ChildIsType ( - IN FRAMEWORK_SECTION_STREAM_NODE *Stream, - IN FRAMEWORK_SECTION_CHILD_NODE *Child, - IN EFI_SECTION_TYPE SearchType, - IN EFI_GUID *SectionDefinitionGuid - ) -{ - EFI_GUID_DEFINED_SECTION *GuidedSection; - - if (SearchType == EFI_SECTION_ALL) { - return TRUE; - } - if (Child->Type != SearchType) { - return FALSE; - } - if ((SearchType != EFI_SECTION_GUID_DEFINED) || (SectionDefinitionGuid == NULL)) { - return TRUE; - } - GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream); - if (IS_SECTION2 (GuidedSection)) { - return CompareGuid (&(((EFI_GUID_DEFINED_SECTION2 *) GuidedSection)->SectionDefinitionGuid), SectionDefinitionGuid); - } else { - return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid); - } -} - -/** - Create a protocol notification event and return it. - - @param ProtocolGuid Protocol to register notification event on. - @param NotifyTpl Maximum TPL to signal the NotifyFunction. - @param NotifyFunction EFI notification routine. - @param NotifyContext Context passed into Event when it is created. - @param Registration Registration key returned from RegisterProtocolNotify(). - @param SignalFlag Boolean value to decide whether kick the event after register or not. - - @return The EFI_EVENT that has been registered to be signaled when a ProtocolGuid - is added to the system. - -**/ -EFI_EVENT -CreateProtocolNotifyEvent ( - IN EFI_GUID *ProtocolGuid, - IN EFI_TPL NotifyTpl, - IN EFI_EVENT_NOTIFY NotifyFunction, - IN VOID *NotifyContext, - OUT VOID **Registration, - IN BOOLEAN SignalFlag - ) -{ - EFI_STATUS Status; - EFI_EVENT Event; - - // - // Create the event - // - - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - NotifyTpl, - NotifyFunction, - NotifyContext, - &Event - ); - ASSERT_EFI_ERROR (Status); - - // - // Register for protocol notifactions on this event - // - - Status = gBS->RegisterProtocolNotify ( - ProtocolGuid, - Event, - Registration - ); - ASSERT_EFI_ERROR (Status); - - if (SignalFlag) { - // - // Kick the event so we will perform an initial pass of - // current installed drivers - // - gBS->SignalEvent (Event); - } - - return Event; -} - -/** - Verify the Guided Section GUID by checking if there is the Guided Section GUID configuration table recorded the GUID itself. - - @param GuidedSectionGuid The Guided Section GUID. - @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Protocol - for the Guided Section. - - @return TRUE The GuidedSectionGuid could be identified, and the pointer to - the Guided Section Extraction Protocol will be returned to *GuidedSectionExtraction. - @return FALSE The GuidedSectionGuid could not be identified, or - the Guided Section Extraction Protocol has not been installed yet. - -**/ -BOOLEAN -VerifyGuidedSectionGuid ( - IN EFI_GUID *GuidedSectionGuid, - OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL **GuidedSectionExtraction - ) -{ - EFI_GUID *GuidRecorded; - VOID *Interface; - EFI_STATUS Status; - - // - // Check if there is the Guided Section GUID configuration table recorded the GUID itself. - // - Status = EfiGetSystemConfigurationTable (GuidedSectionGuid, (VOID **) &GuidRecorded); - if (Status == EFI_SUCCESS) { - if (CompareGuid (GuidRecorded, GuidedSectionGuid)) { - // - // Found the recorded GuidedSectionGuid. - // - Status = gBS->LocateProtocol (GuidedSectionGuid, NULL, (VOID **) &Interface); - if (!EFI_ERROR (Status) && Interface != NULL) { - // - // Found the supported Guided Section Extraction Porotocol for the Guided Section. - // - *GuidedSectionExtraction = (EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *) Interface; - return TRUE; - } - return FALSE; - } - } - - return FALSE; -} - -/** - RPN callback function. - 1. Initialize the section stream when the GUIDED_SECTION_EXTRACTION_PROTOCOL is installed. - 2. Removes a stale section stream and re-initializes it with an updated AuthenticationStatus. - - @param Event The event that fired - @param RpnContext A pointer to the context that allows us to identify - the relevent encapsulation. - -**/ -VOID -EFIAPI -NotifyGuidedExtraction ( - IN EFI_EVENT Event, - IN VOID *RpnContext - ) -{ - EFI_STATUS Status; - EFI_GUID_DEFINED_SECTION *GuidedHeader; - EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction; - VOID *NewStreamBuffer; - UINTN NewStreamBufferSize; - UINT32 AuthenticationStatus; - RPN_EVENT_CONTEXT *Context; - - Context = RpnContext; - Status = EFI_SUCCESS; - if (Context->ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) { - Status = CloseSectionStream (&mSectionExtraction, Context->ChildNode->EncapsulatedStreamHandle); - } - if (!EFI_ERROR (Status)) { - // - // The stream is not initialized, open it. - // Or the stream closed successfully, so re-open the stream with correct AuthenticationStatus. - // - - GuidedHeader = (EFI_GUID_DEFINED_SECTION *) - (Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream); - ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED); - - if (!VerifyGuidedSectionGuid (Context->ChildNode->EncapsulationGuid, &GuidedExtraction)) { - return; - } - - Status = GuidedExtraction->ExtractSection ( - GuidedExtraction, - GuidedHeader, - &NewStreamBuffer, - &NewStreamBufferSize, - &AuthenticationStatus - ); - ASSERT_EFI_ERROR (Status); - // - // OR in the parent stream's aggregate status. - // - AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL; - Status = OpenSectionStreamEx ( - NewStreamBufferSize, - NewStreamBuffer, - FALSE, - AuthenticationStatus, - &Context->ChildNode->EncapsulatedStreamHandle - ); - ASSERT_EFI_ERROR (Status); - } - - // - // If above, the stream did not close successfully, it indicates it's - // already been closed by someone, so just destroy the event and be done with - // it. - // - - gBS->CloseEvent (Event); - Context->ChildNode->Event = NULL; - FreePool (Context); -} - -/** - Worker function. Constructor for RPN event if needed to keep AuthenticationStatus - cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears... - - @param ParentStream Indicates the parent of the ecnapsulation section (child) - @param ChildNode Indicates the child node that is the encapsulation section. - -**/ -VOID -CreateGuidedExtractionRpnEvent ( - IN FRAMEWORK_SECTION_STREAM_NODE *ParentStream, - IN FRAMEWORK_SECTION_CHILD_NODE *ChildNode - ) -{ - RPN_EVENT_CONTEXT *Context; - - // - // Allocate new event structure and context - // - Context = AllocatePool (sizeof (RPN_EVENT_CONTEXT)); - ASSERT (Context != NULL); - - Context->ChildNode = ChildNode; - Context->ParentStream = ParentStream; - - Context->ChildNode->Event = CreateProtocolNotifyEvent ( - Context->ChildNode->EncapsulationGuid, - TPL_NOTIFY, - NotifyGuidedExtraction, - Context, - &Context->Registration, - FALSE - ); -} - -/** - Worker function. Constructor for new child nodes. - - @param Stream Indicates the section stream in which to add the child. - @param ChildOffset Indicates the offset in Stream that is the beginning - of the child section. - @param ChildNode Indicates the Callee allocated and initialized child. - - @retval EFI_SUCCESS Child node was found and returned. - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. - @retval EFI_PROTOCOL_ERROR Encapsulation sections produce new stream handles when - the child node is created. If the section type is GUID - defined, and the extraction GUID does not exist, and - producing the stream requires the GUID, then a protocol - error is generated and no child is produced. - Values returned by OpenSectionStreamEx. - -**/ -EFI_STATUS -CreateChildNode ( - IN FRAMEWORK_SECTION_STREAM_NODE *Stream, - IN UINT32 ChildOffset, - OUT FRAMEWORK_SECTION_CHILD_NODE **ChildNode - ) -{ - EFI_STATUS Status; - EFI_COMMON_SECTION_HEADER *SectionHeader; - EFI_COMPRESSION_SECTION *CompressionHeader; - EFI_GUID_DEFINED_SECTION *GuidedHeader; - EFI_DECOMPRESS_PROTOCOL *Decompress; - EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction; - VOID *NewStreamBuffer; - VOID *ScratchBuffer; - UINT32 ScratchSize; - UINTN NewStreamBufferSize; - UINT32 AuthenticationStatus; - VOID *CompressionSource; - UINT32 CompressionSourceSize; - UINT32 UncompressedLength; - UINT8 CompressionType; - UINT16 GuidedSectionAttributes; - - FRAMEWORK_SECTION_CHILD_NODE *Node; - - SectionHeader = (EFI_COMMON_SECTION_HEADER *) (Stream->StreamBuffer + ChildOffset); - - // - // Allocate a new node - // - *ChildNode = AllocateZeroPool (sizeof (FRAMEWORK_SECTION_CHILD_NODE)); - Node = *ChildNode; - if (Node == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Now initialize it - // - Node->Signature = FRAMEWORK_SECTION_CHILD_SIGNATURE; - Node->Type = SectionHeader->Type; - if (IS_SECTION2 (SectionHeader)) { - Node->Size = SECTION2_SIZE (SectionHeader); - } else { - Node->Size = SECTION_SIZE (SectionHeader); - } - Node->OffsetInStream = ChildOffset; - Node->EncapsulatedStreamHandle = NULL_STREAM_HANDLE; - Node->EncapsulationGuid = NULL; - - // - // If it's an encapsulating section, then create the new section stream also - // - switch (Node->Type) { - case EFI_SECTION_COMPRESSION: - // - // Get the CompressionSectionHeader - // - if (Node->Size < sizeof (EFI_COMPRESSION_SECTION)) { - FreePool (Node); - return EFI_NOT_FOUND; - } - - CompressionHeader = (EFI_COMPRESSION_SECTION *) SectionHeader; - - if (IS_SECTION2 (CompressionHeader)) { - CompressionSource = (VOID *) ((UINT8 *) CompressionHeader + sizeof (EFI_COMPRESSION_SECTION2)); - CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionHeader) - sizeof (EFI_COMPRESSION_SECTION2)); - UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionHeader)->UncompressedLength; - CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionHeader)->CompressionType; - } else { - CompressionSource = (VOID *) ((UINT8 *) CompressionHeader + sizeof (EFI_COMPRESSION_SECTION)); - CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionHeader) - sizeof (EFI_COMPRESSION_SECTION)); - UncompressedLength = CompressionHeader->UncompressedLength; - CompressionType = CompressionHeader->CompressionType; - } - - // - // Allocate space for the new stream - // - if (UncompressedLength > 0) { - NewStreamBufferSize = UncompressedLength; - NewStreamBuffer = AllocatePool (NewStreamBufferSize); - if (NewStreamBuffer == NULL) { - FreePool (Node); - return EFI_OUT_OF_RESOURCES; - } - - if (CompressionType == EFI_NOT_COMPRESSED) { - // - // stream is not actually compressed, just encapsulated. So just copy it. - // - CopyMem (NewStreamBuffer, CompressionSource, NewStreamBufferSize); - } else if (CompressionType == EFI_STANDARD_COMPRESSION) { - // - // Only support the EFI_SATNDARD_COMPRESSION algorithm. - // - - // - // Decompress the stream - // - Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **)&Decompress); - - ASSERT_EFI_ERROR (Status); - - Status = Decompress->GetInfo ( - Decompress, - CompressionSource, - CompressionSourceSize, - (UINT32 *)&NewStreamBufferSize, - &ScratchSize - ); - if (EFI_ERROR (Status) || (NewStreamBufferSize != UncompressedLength)) { - FreePool (Node); - FreePool (NewStreamBuffer); - if (!EFI_ERROR (Status)) { - Status = EFI_BAD_BUFFER_SIZE; - } - return Status; - } - - ScratchBuffer = AllocatePool (ScratchSize); - if (ScratchBuffer == NULL) { - FreePool (Node); - FreePool (NewStreamBuffer); - return EFI_OUT_OF_RESOURCES; - } - - Status = Decompress->Decompress ( - Decompress, - CompressionSource, - CompressionSourceSize, - NewStreamBuffer, - (UINT32)NewStreamBufferSize, - ScratchBuffer, - ScratchSize - ); - FreePool (ScratchBuffer); - if (EFI_ERROR (Status)) { - FreePool (Node); - FreePool (NewStreamBuffer); - return Status; - } - } - } else { - NewStreamBuffer = NULL; - NewStreamBufferSize = 0; - } - - Status = OpenSectionStreamEx ( - NewStreamBufferSize, - NewStreamBuffer, - FALSE, - Stream->AuthenticationStatus, - &Node->EncapsulatedStreamHandle - ); - if (EFI_ERROR (Status)) { - FreePool (Node); - FreePool (NewStreamBuffer); - return Status; - } - break; - - case EFI_SECTION_GUID_DEFINED: - GuidedHeader = (EFI_GUID_DEFINED_SECTION *) SectionHeader; - if (IS_SECTION2 (GuidedHeader)) { - Node->EncapsulationGuid = &(((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->SectionDefinitionGuid); - GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->Attributes; - } else { - Node->EncapsulationGuid = &GuidedHeader->SectionDefinitionGuid; - GuidedSectionAttributes = GuidedHeader->Attributes; - } - if (VerifyGuidedSectionGuid (Node->EncapsulationGuid, &GuidedExtraction)) { - // - // NewStreamBuffer is always allocated by ExtractSection... No caller - // allocation here. - // - Status = GuidedExtraction->ExtractSection ( - GuidedExtraction, - GuidedHeader, - &NewStreamBuffer, - &NewStreamBufferSize, - &AuthenticationStatus - ); - if (EFI_ERROR (Status)) { - FreePool (*ChildNode); - return EFI_PROTOCOL_ERROR; - } - - // - // Make sure we initialize the new stream with the correct - // authentication status for both aggregate and local status fields. - // - if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) { - // - // OR in the parent stream's aggregate status. - // - AuthenticationStatus |= Stream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL; - } else { - // - // since there's no authentication data contributed by the section, - // just inherit the full value from our immediate parent. - // - AuthenticationStatus = Stream->AuthenticationStatus; - } - - Status = OpenSectionStreamEx ( - NewStreamBufferSize, - NewStreamBuffer, - FALSE, - AuthenticationStatus, - &Node->EncapsulatedStreamHandle - ); - if (EFI_ERROR (Status)) { - FreePool (*ChildNode); - FreePool (NewStreamBuffer); - return Status; - } - } else { - // - // There's no GUIDed section extraction protocol available. - // - if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == EFI_GUIDED_SECTION_PROCESSING_REQUIRED) { - // - // If the section REQUIRES an extraction protocol, register for RPN - // when the required GUIDed extraction protocol becomes available. - // - AuthenticationStatus = 0; - CreateGuidedExtractionRpnEvent (Stream, Node); - } else { - // - // Figure out the proper authentication status - // - AuthenticationStatus = Stream->AuthenticationStatus; - if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) { - // - // The local status of the new stream is contained in - // AuthenticaionStatus. This value needs to be ORed into the - // Aggregate bits also... - // - - // - // Clear out and initialize the local status - // - AuthenticationStatus &= ~EFI_LOCAL_AUTH_STATUS_ALL; - AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED; - // - // OR local status into aggregate status - // - AuthenticationStatus |= AuthenticationStatus >> 16; - } - - if (IS_SECTION2 (GuidedHeader)) { - Status = OpenSectionStreamEx ( - SECTION2_SIZE (GuidedHeader) - ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->DataOffset, - (UINT8 *) GuidedHeader + ((EFI_GUID_DEFINED_SECTION2 *) GuidedHeader)->DataOffset, - TRUE, - AuthenticationStatus, - &Node->EncapsulatedStreamHandle - ); - } else { - Status = OpenSectionStreamEx ( - SECTION_SIZE (GuidedHeader) - ((EFI_GUID_DEFINED_SECTION *) GuidedHeader)->DataOffset, - (UINT8 *) GuidedHeader + ((EFI_GUID_DEFINED_SECTION *) GuidedHeader)->DataOffset, - TRUE, - AuthenticationStatus, - &Node->EncapsulatedStreamHandle - ); - } - if (EFI_ERROR (Status)) { - FreePool (Node); - return Status; - } - } - } - - if ((AuthenticationStatus & EFI_LOCAL_AUTH_STATUS_ALL) == - (EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED)) { - // - // Need to register for RPN for when the required GUIDed extraction - // protocol becomes available. This will enable us to refresh the - // AuthenticationStatus cached in the Stream if it's ever requested - // again. - // - CreateGuidedExtractionRpnEvent (Stream, Node); - } - - break; - - default: - - // - // Nothing to do if it's a leaf - // - break; - } - - // - // Last, add the new child node to the stream - // - InsertTailList (&Stream->Children, &Node->Link); - - return EFI_SUCCESS; -} - -/** - Worker function Recursively searches / builds section stream database - looking for requested section. - - - @param SourceStream Indicates the section stream in which to do the search. - @param SearchType Indicates the type of section to search for. - @param SectionInstance Indicates which instance of section to find. This is - an in/out parameter to deal with recursions. - @param SectionDefinitionGuid Guid of section definition - @param FoundChild Output indicating the child node that is found. - @param FoundStream Output indicating which section stream the child was - found in. If this stream was generated as a result of - an encapsulation section, the streamhandle is visible - within the SEP driver only. - @param AuthenticationStatus Indicates the authentication status of the found section. - - @retval EFI_SUCCESS Child node was found and returned. - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. - @retval EFI_NOT_FOUND Requested child node does not exist. - @retval EFI_PROTOCOL_ERROR A required GUIDED section extraction protocol does not - exist - -**/ -EFI_STATUS -FindChildNode ( - IN FRAMEWORK_SECTION_STREAM_NODE *SourceStream, - IN EFI_SECTION_TYPE SearchType, - IN OUT UINTN *SectionInstance, - IN EFI_GUID *SectionDefinitionGuid, - OUT FRAMEWORK_SECTION_CHILD_NODE **FoundChild, - OUT FRAMEWORK_SECTION_STREAM_NODE **FoundStream, - OUT UINT32 *AuthenticationStatus - ) -{ - FRAMEWORK_SECTION_CHILD_NODE *CurrentChildNode; - FRAMEWORK_SECTION_CHILD_NODE *RecursedChildNode; - FRAMEWORK_SECTION_STREAM_NODE *RecursedFoundStream; - UINT32 NextChildOffset; - EFI_STATUS ErrorStatus; - EFI_STATUS Status; - - CurrentChildNode = NULL; - ErrorStatus = EFI_NOT_FOUND; - - if (SourceStream->StreamLength == 0) { - return EFI_NOT_FOUND; - } - - if (IsListEmpty (&SourceStream->Children) && - SourceStream->StreamLength >= sizeof (EFI_COMMON_SECTION_HEADER)) { - // - // This occurs when a section stream exists, but no child sections - // have been parsed out yet. Therefore, extract the first child and add it - // to the list of children so we can get started. - // Section stream may contain an array of zero or more bytes. - // So, its size should be >= the size of commen section header. - // - Status = CreateChildNode (SourceStream, 0, &CurrentChildNode); - if (EFI_ERROR (Status)) { - return Status; - } - } - - // - // At least one child has been parsed out of the section stream. So, walk - // through the sections that have already been parsed out looking for the - // requested section, if necessary, continue parsing section stream and - // adding children until either the requested section is found, or we run - // out of data - // - CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children)); - - for (;;) { - ASSERT (CurrentChildNode != NULL); - if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) { - // - // The type matches, so check the instance count to see if it's the one we want - // - (*SectionInstance)--; - if (*SectionInstance == 0) { - // - // Got it! - // - *FoundChild = CurrentChildNode; - *FoundStream = SourceStream; - *AuthenticationStatus = SourceStream->AuthenticationStatus; - return EFI_SUCCESS; - } - } - - if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) { - // - // If the current node is an encapsulating node, recurse into it... - // - Status = FindChildNode ( - (FRAMEWORK_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle, - SearchType, - SectionInstance, - SectionDefinitionGuid, - &RecursedChildNode, - &RecursedFoundStream, - AuthenticationStatus - ); - // - // If the status is not EFI_SUCCESS, just save the error code and continue - // to find the request child node in the rest stream. - // - if (*SectionInstance == 0) { - ASSERT_EFI_ERROR (Status); - *FoundChild = RecursedChildNode; - *FoundStream = RecursedFoundStream; - return EFI_SUCCESS; - } else { - ErrorStatus = Status; - } - } else if ((CurrentChildNode->Type == EFI_SECTION_GUID_DEFINED) && (SearchType != EFI_SECTION_GUID_DEFINED)) { - // - // When Node Type is GUIDED section, but Node has no encapsulated data, Node data should not be parsed - // because a required GUIDED section extraction protocol does not exist. - // If SearchType is not GUIDED section, EFI_PROTOCOL_ERROR should return. - // - ErrorStatus = EFI_PROTOCOL_ERROR; - } - - if (!IsNodeAtEnd (&SourceStream->Children, &CurrentChildNode->Link)) { - // - // We haven't found the child node we're interested in yet, but there's - // still more nodes that have already been parsed so get the next one - // and continue searching.. - // - CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream->Children, &CurrentChildNode->Link)); - } else { - // - // We've exhausted children that have already been parsed, so see if - // there's any more data and continue parsing out more children if there - // is. - // - NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size; - // - // Round up to 4 byte boundary - // - NextChildOffset += 3; - NextChildOffset &= ~(UINTN)3; - if (NextChildOffset <= SourceStream->StreamLength - sizeof (EFI_COMMON_SECTION_HEADER)) { - // - // There's an unparsed child remaining in the stream, so create a new child node - // - Status = CreateChildNode (SourceStream, NextChildOffset, &CurrentChildNode); - if (EFI_ERROR (Status)) { - return Status; - } - } else { - ASSERT (EFI_ERROR (ErrorStatus)); - return ErrorStatus; - } - } - } -} - -/** - Worker function. Search stream database for requested stream handle. - - @param SearchHandle Indicates which stream to look for. - @param FoundStream Output pointer to the found stream. - - @retval EFI_SUCCESS StreamHandle was found and *FoundStream contains - the stream node. - @retval EFI_NOT_FOUND SearchHandle was not found in the stream database. - -**/ -EFI_STATUS -FindStreamNode ( - IN UINTN SearchHandle, - OUT FRAMEWORK_SECTION_STREAM_NODE **FoundStream - ) -{ - FRAMEWORK_SECTION_STREAM_NODE *StreamNode; - - if (!IsListEmpty (&mStreamRoot)) { - StreamNode = STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot)); - for (;;) { - if (StreamNode->StreamHandle == SearchHandle) { - *FoundStream = StreamNode; - return EFI_SUCCESS; - } else if (IsNodeAtEnd (&mStreamRoot, &StreamNode->Link)) { - break; - } else { - StreamNode = STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot, &StreamNode->Link)); - } - } - } - - return EFI_NOT_FOUND; -} - -/** - SEP member function. Retrieves requested section from section stream. - - @param This Pointer to SEP instance. - @param SectionStreamHandle The section stream from which to extract the requested - section. - @param SectionType A pointer to the type of section to search for. - @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED, then - SectionDefinitionGuid indicates which of these types - of sections to search for. - @param SectionInstance Indicates which instance of the requested section to - return. - @param Buffer Double indirection to buffer. If *Buffer is non-null on - input, then the buffer is caller allocated. If - *Buffer is NULL, then the buffer is callee allocated. - In either case, the requried buffer size is returned - in *BufferSize. - @param BufferSize On input, indicates the size of *Buffer if *Buffer is - non-null on input. On output, indicates the required - size (allocated size if callee allocated) of *Buffer. - @param AuthenticationStatus Indicates the authentication status of the retrieved - section. - - - @retval EFI_SUCCESS Section was retrieved successfully - @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the section - stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED - bit set, but there was no corresponding GUIDed Section - Extraction Protocol in the handle database. *Buffer is - unmodified. - @retval EFI_NOT_FOUND An error was encountered when parsing the SectionStream. - This indicates the SectionStream is not correctly - formatted. - @retval EFI_NOT_FOUND The requested section does not exist. - @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process the - request. - @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist. - @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is - insufficient to contain the requested section. The - input buffer is filled and contents are section contents - are truncated. - -**/ -EFI_STATUS -EFIAPI -GetSection ( - IN EFI_SECTION_EXTRACTION_PROTOCOL *This, - IN UINTN SectionStreamHandle, - IN EFI_SECTION_TYPE *SectionType, - IN EFI_GUID *SectionDefinitionGuid, - IN UINTN SectionInstance, - IN VOID **Buffer, - IN OUT UINTN *BufferSize, - OUT UINT32 *AuthenticationStatus - ) -{ - FRAMEWORK_SECTION_STREAM_NODE *StreamNode; - EFI_TPL OldTpl; - EFI_STATUS Status; - FRAMEWORK_SECTION_CHILD_NODE *ChildNode; - FRAMEWORK_SECTION_STREAM_NODE *ChildStreamNode; - UINTN CopySize; - UINT32 ExtractedAuthenticationStatus; - UINTN Instance; - UINT8 *CopyBuffer; - UINTN SectionSize; - EFI_COMMON_SECTION_HEADER *Section; - - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - Instance = SectionInstance + 1; - ChildStreamNode = NULL; - - // - // Locate target stream - // - Status = FindStreamNode (SectionStreamHandle, &StreamNode); - if (EFI_ERROR (Status)) { - Status = EFI_INVALID_PARAMETER; - goto GetSection_Done; - } - - // - // Found the stream, now locate and return the appropriate section - // - if (SectionType == NULL) { - // - // SectionType == NULL means return the WHOLE section stream... - // - CopySize = StreamNode->StreamLength; - CopyBuffer = StreamNode->StreamBuffer; - *AuthenticationStatus = StreamNode->AuthenticationStatus; - } else { - // - // There's a requested section type, so go find it and return it... - // - Status = FindChildNode ( - StreamNode, - *SectionType, - &Instance, - SectionDefinitionGuid, - &ChildNode, - &ChildStreamNode, - &ExtractedAuthenticationStatus - ); - if (EFI_ERROR (Status)) { - goto GetSection_Done; - } - ASSERT (ChildNode != NULL); - ASSERT (ChildStreamNode != NULL); - Section = (EFI_COMMON_SECTION_HEADER *) (ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream); - - if (IS_SECTION2 (Section)) { - CopySize = SECTION2_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER2); - CopyBuffer = (UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2); - } else { - CopySize = SECTION_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER); - CopyBuffer = (UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER); - } - *AuthenticationStatus = ExtractedAuthenticationStatus; - } - - SectionSize = CopySize; - if (*Buffer != NULL) { - // - // Caller allocated buffer. Fill to size and return required size... - // - if (*BufferSize < CopySize) { - Status = EFI_WARN_BUFFER_TOO_SMALL; - CopySize = *BufferSize; - } - } else { - // - // Callee allocated buffer. Allocate buffer and return size. - // - *Buffer = AllocatePool (CopySize); - if (*Buffer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto GetSection_Done; - } - } - CopyMem (*Buffer, CopyBuffer, CopySize); - *BufferSize = SectionSize; - -GetSection_Done: - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - Worker function. Destructor for child nodes. - - @param ChildNode Indicates the node to destroy - -**/ -VOID -FreeChildNode ( - IN FRAMEWORK_SECTION_CHILD_NODE *ChildNode - ) -{ - ASSERT (ChildNode->Signature == FRAMEWORK_SECTION_CHILD_SIGNATURE); - // - // Remove the child from it's list - // - RemoveEntryList (&ChildNode->Link); - - if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) { - // - // If it's an encapsulating section, we close the resulting section stream. - // CloseSectionStream will free all memory associated with the stream. - // - CloseSectionStream (&mSectionExtraction, ChildNode->EncapsulatedStreamHandle); - } - - if (ChildNode->Event != NULL) { - gBS->CloseEvent (ChildNode->Event); - } - - // - // Last, free the child node itself - // - FreePool (ChildNode); -} - -/** - SEP member function. Deletes an existing section stream - - @param This Indicates the calling context. - @param StreamHandleToClose Indicates the stream to close - - @retval EFI_SUCCESS Section stream was closed successfully. - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. - @retval EFI_INVALID_PARAMETER Section stream does not end concident with end of - last section. - -**/ -EFI_STATUS -EFIAPI -CloseSectionStream ( - IN EFI_SECTION_EXTRACTION_PROTOCOL *This, - IN UINTN StreamHandleToClose - ) -{ - FRAMEWORK_SECTION_STREAM_NODE *StreamNode; - EFI_TPL OldTpl; - EFI_STATUS Status; - LIST_ENTRY *Link; - FRAMEWORK_SECTION_CHILD_NODE *ChildNode; - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Locate target stream - // - Status = FindStreamNode (StreamHandleToClose, &StreamNode); - if (!EFI_ERROR (Status)) { - // - // Found the stream, so close it - // - RemoveEntryList (&StreamNode->Link); - while (!IsListEmpty (&StreamNode->Children)) { - Link = GetFirstNode (&StreamNode->Children); - ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link); - FreeChildNode (ChildNode); - } - FreePool (StreamNode->StreamBuffer); - FreePool (StreamNode); - Status = EFI_SUCCESS; - } else { - Status = EFI_INVALID_PARAMETER; - } - - gBS->RestoreTPL (OldTpl); - return Status; -} diff --git a/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf b/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf deleted file mode 100644 index ab0bd63076..0000000000 --- a/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf +++ /dev/null @@ -1,57 +0,0 @@ -## @file -# Section Extraction Dxe Driver produces framework section extract protocol. -# -# The section is implemented as a linked list of section streams, -# where each stream contains a linked list of children, which may be leaves or -# encapsulations. Encapsulation section will further generate new section stream entries. -# -# 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 -# 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 = SectionExtractionDxe - MODULE_UNI_FILE = SectionExtractionDxe.uni - FILE_GUID = 801ADCA0-815E-46a4-84F7-657F53621A57 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = SectionExtractionEntryPoint - -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - SectionExtraction.c - -[LibraryClasses] - UefiBootServicesTableLib - MemoryAllocationLib - DebugLib - BaseLib - BaseMemoryLib - UefiDriverEntryPoint - UefiLib - -[Packages] - MdePkg/MdePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - -[Protocols] - gEfiSectionExtractionProtocolGuid ## PRODUCES - gEfiDecompressProtocolGuid ## SOMETIMES_CONSUMES - -[Depex] - gEfiDecompressProtocolGuid - -[UserExtensions.TianoCore."ExtraFiles"] - SectionExtractionDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.uni b/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.uni deleted file mode 100644 index 98a01d2f90..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxeExtra.uni b/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxeExtra.uni deleted file mode 100644 index 84db1b982f..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c deleted file mode 100644 index 5b42395dbd..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c +++ /dev/null @@ -1,376 +0,0 @@ -/** @file - Data Hub status code worker. - - 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 "DatahubStatusCodeHandlerDxe.h" - -// -// Initialize FIFO to cache records. -// -LIST_ENTRY mRecordsFifo = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsFifo); -LIST_ENTRY mRecordsBuffer = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsBuffer); -UINT32 mLogDataHubStatus = 0; -EFI_EVENT mLogDataHubEvent; -// -// Cache data hub protocol. -// -EFI_DATA_HUB_PROTOCOL *mDataHubProtocol = NULL; - - -/** - Retrieve one record of from free record buffer. This record is removed from - free record buffer. - - This function retrieves one record from free record buffer. - If the pool has been exhausted, then new memory would be allocated for it. - - @return Pointer to the free record. - NULL means failure to allocate new memeory for free record buffer. - -**/ -DATA_HUB_STATUS_CODE_DATA_RECORD * -AcquireRecordBuffer ( - VOID - ) -{ - DATAHUB_STATUSCODE_RECORD *Record; - EFI_TPL CurrentTpl; - LIST_ENTRY *Node; - UINT32 Index; - - CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - if (!IsListEmpty (&mRecordsBuffer)) { - // - // Strip one entry from free record buffer. - // - Node = GetFirstNode (&mRecordsBuffer); - RemoveEntryList (Node); - - Record = BASE_CR (Node, DATAHUB_STATUSCODE_RECORD, Node); - } else { - if (CurrentTpl > TPL_NOTIFY) { - // - // Memory management should work at <=TPL_NOTIFY - // - gBS->RestoreTPL (CurrentTpl); - return NULL; - } - - // - // If free record buffer is exhausted, then allocate 16 new records for it. - // - gBS->RestoreTPL (CurrentTpl); - Record = (DATAHUB_STATUSCODE_RECORD *) AllocateZeroPool (sizeof (DATAHUB_STATUSCODE_RECORD) * 16); - if (Record == NULL) { - return NULL; - } - - CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - // - // Here we only insert 15 new records to the free record buffer, for the first record - // will be returned immediately. - // - for (Index = 1; Index < 16; Index++) { - InsertTailList (&mRecordsBuffer, &Record[Index].Node); - } - } - - Record->Signature = DATAHUB_STATUS_CODE_SIGNATURE; - InsertTailList (&mRecordsFifo, &Record->Node); - - gBS->RestoreTPL (CurrentTpl); - - return (DATA_HUB_STATUS_CODE_DATA_RECORD *) (Record->Data); -} - - -/** - Retrieve one record from Records FIFO. The record would be removed from FIFO. - - @return Point to record, which is ready to be logged. - NULL means the FIFO of record is empty. - -**/ -DATA_HUB_STATUS_CODE_DATA_RECORD * -RetrieveRecord ( - VOID - ) -{ - DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData; - DATAHUB_STATUSCODE_RECORD *Record; - LIST_ENTRY *Node; - EFI_TPL CurrentTpl; - - RecordData = NULL; - - CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - if (!IsListEmpty (&mRecordsFifo)) { - Node = GetFirstNode (&mRecordsFifo); - Record = CR (Node, DATAHUB_STATUSCODE_RECORD, Node, DATAHUB_STATUS_CODE_SIGNATURE); - ASSERT (Record != NULL); - - RemoveEntryList (&Record->Node); - RecordData = (DATA_HUB_STATUS_CODE_DATA_RECORD *) Record->Data; - } - - gBS->RestoreTPL (CurrentTpl); - - return RecordData; -} - -/** - Release given record and return it to free record buffer. - - @param RecordData Pointer to the record to release. - -**/ -VOID -ReleaseRecord ( - DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData - ) -{ - DATAHUB_STATUSCODE_RECORD *Record; - EFI_TPL CurrentTpl; - - Record = CR (RecordData, DATAHUB_STATUSCODE_RECORD, Data[0], DATAHUB_STATUS_CODE_SIGNATURE); - ASSERT (Record != NULL); - - CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - InsertTailList (&mRecordsBuffer, &Record->Node); - Record->Signature = 0; - - gBS->RestoreTPL (CurrentTpl); -} - -/** - Report status code into DataHub. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_DEVICE_ERROR Function is reentered. - @retval EFI_DEVICE_ERROR Function is called at runtime. - @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. - -**/ -EFI_STATUS -EFIAPI -DataHubStatusCodeReportWorker ( - 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 - ) -{ - DATA_HUB_STATUS_CODE_DATA_RECORD *Record; - UINT32 ErrorLevel; - BASE_LIST Marker; - CHAR8 *Format; - UINTN CharCount; - - // - // Use atom operation to avoid the reentant of report. - // If current status is not zero, then the function is reentrancy. - // - if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 0) == 1) { - return EFI_DEVICE_ERROR; - } - - Record = AcquireRecordBuffer (); - if (Record == NULL) { - // - // There are no empty record buffer in private buffers - // - return EFI_OUT_OF_RESOURCES; - } - - // - // Construct Data Hub Extended Data - // - Record->CodeType = CodeType; - Record->Value = Value; - Record->Instance = Instance; - - if (CallerId != NULL) { - CopyMem (&Record->CallerId, CallerId, sizeof (EFI_GUID)); - } - - if (Data != NULL) { - if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { - CharCount = UnicodeBSPrintAsciiFormat ( - (CHAR16 *) (Record + 1), - EFI_STATUS_CODE_DATA_MAX_SIZE, - Format, - Marker - ); - // - // Change record data type to DebugType. - // - CopyGuid (&Record->Data.Type, &gEfiStatusCodeDataTypeDebugGuid); - Record->Data.HeaderSize = Data->HeaderSize; - Record->Data.Size = (UINT16) ((CharCount + 1) * sizeof (CHAR16)); - } else { - // - // Copy status code data header - // - CopyMem (&Record->Data, Data, sizeof (EFI_STATUS_CODE_DATA)); - - if (Data->Size > EFI_STATUS_CODE_DATA_MAX_SIZE) { - Record->Data.Size = EFI_STATUS_CODE_DATA_MAX_SIZE; - } - CopyMem ((VOID *) (Record + 1), Data + 1, Record->Data.Size); - } - } - - gBS->SignalEvent (mLogDataHubEvent); - - return EFI_SUCCESS; -} - - -/** - The Event handler which will be notified to log data in Data Hub. - - @param Event Instance of the EFI_EVENT to signal whenever data is - available to be logged in the system. - @param Context Context of the event. - -**/ -VOID -EFIAPI -LogDataHubEventCallBack ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - DATA_HUB_STATUS_CODE_DATA_RECORD *Record; - UINT32 Size; - UINT64 DataRecordClass; - - // - // Use atom operation to avoid the reentant of report. - // If current status is not zero, then the function is reentrancy. - // - if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 1) == 1) { - return; - } - - // - // Log DataRecord in Data Hub. - // Journal records fifo to find all record entry. - // - while (TRUE) { - // - // Retrieve record from record FIFO until no more record can be retrieved. - // - Record = RetrieveRecord (); - if (Record == NULL) { - break; - } - // - // Add in the size of the header we added. - // - Size = sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD) + (UINT32) Record->Data.Size; - - if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { - DataRecordClass = EFI_DATA_RECORD_CLASS_PROGRESS_CODE; - } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { - DataRecordClass = EFI_DATA_RECORD_CLASS_ERROR; - } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { - DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG; - } else { - // - // Should never get here. - // - DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG | - EFI_DATA_RECORD_CLASS_ERROR | - EFI_DATA_RECORD_CLASS_DATA | - EFI_DATA_RECORD_CLASS_PROGRESS_CODE; - } - - // - // Log DataRecord in Data Hub - // - mDataHubProtocol->LogData ( - mDataHubProtocol, - &gEfiDataHubStatusCodeRecordGuid, - &gEfiStatusCodeRuntimeProtocolGuid, - DataRecordClass, - Record, - Size - ); - - ReleaseRecord (Record); - } - - // - // Restore the nest status of report - // - InterlockedCompareExchange32 (&mLogDataHubStatus, 1, 0); -} - - -/** - Locate Data Hub Protocol and create event for logging data - as initialization for data hub status code worker. - - @retval EFI_SUCCESS Initialization is successful. - -**/ -EFI_STATUS -DataHubStatusCodeInitializeWorker ( - VOID - ) -{ - EFI_STATUS Status; - - Status = gBS->LocateProtocol ( - &gEfiDataHubProtocolGuid, - NULL, - (VOID **) &mDataHubProtocol - ); - if (EFI_ERROR (Status)) { - mDataHubProtocol = NULL; - return Status; - } - - // - // Create a Notify Event to log data in Data Hub - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - LogDataHubEventCallBack, - NULL, - &mLogDataHubEvent - ); - - ASSERT_EFI_ERROR (Status); - - return EFI_SUCCESS; -} - - diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c deleted file mode 100644 index ee7bdd36af..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c +++ /dev/null @@ -1,88 +0,0 @@ -/** @file - Status Code Handler Driver which produces datahub handler and hook it - onto the DXE status code router. - - 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 "DatahubStatusCodeHandlerDxe.h" - -EFI_EVENT mExitBootServicesEvent = NULL; -EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL; - -/** - Unregister status code callback functions only available at boot time from - report status code router when exiting boot services. - - @param Event Event whose notification function is being invoked. - @param Context Pointer to the notification function's context, which is - always zero in current implementation. - -**/ -VOID -EFIAPI -UnregisterBootTimeHandlers ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - mRscHandlerProtocol->Unregister (DataHubStatusCodeReportWorker); -} - -/** - Entry point of DXE Status Code Driver. - - This function is the entry point of this DXE Status Code Driver. - It initializes registers status code handlers, and registers event for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. - - @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. - -**/ -EFI_STATUS -EFIAPI -DatahubStatusCodeHandlerDxeEntry ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { - Status = gBS->LocateProtocol ( - &gEfiRscHandlerProtocolGuid, - NULL, - (VOID **) &mRscHandlerProtocol - ); - ASSERT_EFI_ERROR (Status); - - // - // Dispatch initialization request to supported devices - // - DataHubStatusCodeInitializeWorker (); - - mRscHandlerProtocol->Register (DataHubStatusCodeReportWorker, TPL_HIGH_LEVEL); - - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - UnregisterBootTimeHandlers, - NULL, - &gEfiEventExitBootServicesGuid, - &mExitBootServicesEvent - ); - ASSERT_EFI_ERROR (Status); - } - - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h deleted file mode 100644 index 8ee0b55fa8..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h +++ /dev/null @@ -1,91 +0,0 @@ -/** @file - Internal include file for Datahub Status Code Handler Driver. - - 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 __DATAHUB_STATUS_CODE_HANDLER_DXE_H__ -#define __DATAHUB_STATUS_CODE_HANDLER_DXE_H__ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Data hub worker definition -// -#define DATAHUB_STATUS_CODE_SIGNATURE SIGNATURE_32 ('B', 'D', 'H', 'S') - -typedef struct { - UINTN Signature; - LIST_ENTRY Node; - UINT8 Data[sizeof(DATA_HUB_STATUS_CODE_DATA_RECORD) + EFI_STATUS_CODE_DATA_MAX_SIZE]; -} DATAHUB_STATUSCODE_RECORD; - -/** - Report status code into DataHub. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_DEVICE_ERROR Function is reentered. - @retval EFI_DEVICE_ERROR Function is called at runtime. - @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. - -**/ -EFI_STATUS -EFIAPI -DataHubStatusCodeReportWorker ( - 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 - ); - -/** - Locate Data Hub Protocol and create event for logging data - as initialization for data hub status code worker. - - @retval EFI_SUCCESS Initialization is successful. - -**/ -EFI_STATUS -DataHubStatusCodeInitializeWorker ( - VOID - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf deleted file mode 100644 index 1a576772a3..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf +++ /dev/null @@ -1,72 +0,0 @@ -## @file -# Status Code Handler Driver which produces datahub handler. -# -# 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 -# 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 = DatahubStatusCodeHandlerDxe - MODULE_UNI_FILE = DatahubStatusCodeHandlerDxe.uni - FILE_GUID = 863D214F-0920-437B-8CAD-88EA83A24E97 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = DatahubStatusCodeHandlerDxeEntry - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - DatahubStatusCodeHandlerDxe.h - DatahubStatusCodeHandlerDxe.c - DataHubStatusCodeWorker.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - BaseLib - MemoryAllocationLib - UefiBootServicesTableLib - UefiDriverEntryPoint - PcdLib - PrintLib - ReportStatusCodeLib - DebugLib - SynchronizationLib - BaseMemoryLib - -[Guids] - gEfiEventExitBootServicesGuid ## CONSUMES ## Event - gEfiDataHubStatusCodeRecordGuid ## PRODUCES ## UNDEFINED # DataRecord Guid - gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_PRODUCES ## UNDEFINED # Record data type - -[Protocols] - gEfiRscHandlerProtocolGuid ## CONSUMES - gEfiDataHubProtocolGuid ## CONSUMES - gEfiStatusCodeRuntimeProtocolGuid ## UNDEFINED - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub ## CONSUMES - -[Depex] - gEfiRscHandlerProtocolGuid AND - gEfiDataHubProtocolGuid - -[UserExtensions.TianoCore."ExtraFiles"] - DatahubStatusCodeHandlerDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.uni b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.uni deleted file mode 100644 index 57f0640fa4..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxeExtra.uni b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxeExtra.uni deleted file mode 100644 index 0e648005ec..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxeExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/MemoryStausCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/Pei/MemoryStausCodeWorker.c deleted file mode 100644 index f0b36f23a2..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/MemoryStausCodeWorker.c +++ /dev/null @@ -1,118 +0,0 @@ -/** @file - PEI memory status code worker. - - Copyright (c) 2006 - 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 "StatusCodePei.h" - -/** - Create the first memory status code GUID'ed HOB as initialization for memory status code worker. - - @retval EFI_SUCCESS The GUID'ed HOB is created successfully. - -**/ -EFI_STATUS -MemoryStatusCodeInitializeWorker ( - VOID - ) -{ - // - // Create memory status code GUID'ed HOB. - // - MEMORY_STATUSCODE_PACKET_HEADER *PacketHeader; - - // - // Build GUID'ed HOB with PCD defined size. - // - PacketHeader = BuildGuidHob ( - &gMemoryStatusCodeRecordGuid, - PcdGet16 (PcdStatusCodeMemorySize) * 1024 + sizeof (MEMORY_STATUSCODE_PACKET_HEADER) - ); - ASSERT (PacketHeader != NULL); - - PacketHeader->MaxRecordsNumber = (PcdGet16 (PcdStatusCodeMemorySize) * 1024) / sizeof (MEMORY_STATUSCODE_RECORD); - PacketHeader->PacketIndex = 0; - PacketHeader->RecordIndex = 0; - - return EFI_SUCCESS; -} - - -/** - Report status code into GUID'ed HOB. - - This function reports status code into GUID'ed HOB. If not all packets are full, then - write status code into available entry. Otherwise, create a new packet for it. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or - software entity. This includes information about the class and - subclass that is used to classify the entity as well as an operation. - For progress codes, the operation is the current activity. - For error codes, it is the exception.For debug codes,it is not defined at this time. - @param Instance The enumeration of a hardware or software entity within - the system. A system may contain multiple entities that match a class/subclass - pairing. The instance differentiates between them. An instance of 0 indicates - that instance information is unavailable, not meaningful, or not relevant. - Valid instance numbers start with 1. - - @retval EFI_SUCCESS The function always return EFI_SUCCESS. - -**/ -EFI_STATUS -MemoryStatusCodeReportWorker ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance - ) -{ - - EFI_PEI_HOB_POINTERS Hob; - MEMORY_STATUSCODE_PACKET_HEADER *PacketHeader; - MEMORY_STATUSCODE_RECORD *Record; - - // - // Find GUID'ed HOBs to locate current record buffer. - // - Hob.Raw = GetFirstGuidHob (&gMemoryStatusCodeRecordGuid); - ASSERT (Hob.Raw != NULL); - - PacketHeader = (MEMORY_STATUSCODE_PACKET_HEADER *) GET_GUID_HOB_DATA (Hob.Guid); - Record = (MEMORY_STATUSCODE_RECORD *) (PacketHeader + 1); - Record = &Record[PacketHeader->RecordIndex++]; - - // - // Save status code. - // - Record->CodeType = CodeType; - Record->Instance = Instance; - Record->Value = Value; - - // - // If record index equals to max record number, then wrap around record index to zero. - // - // The reader of status code should compare the number of records with max records number, - // If it is equal to or larger than the max number, then the wrap-around had happened, - // so the first record is pointed by record index. - // If it is less then max number, index of the first record is zero. - // - if (PacketHeader->RecordIndex == PacketHeader->MaxRecordsNumber) { - // - // Wrap around record index. - // - PacketHeader->RecordIndex = 0; - PacketHeader->PacketIndex ++; - } - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/SerialStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/Pei/SerialStatusCodeWorker.c deleted file mode 100644 index d62cb8f8c8..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/SerialStatusCodeWorker.c +++ /dev/null @@ -1,162 +0,0 @@ -/** @file - Serial I/O status code reporting worker. - - 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 - 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 "StatusCodePei.h" - -/** - Convert status code value and extended data to readable ASCII string, send string to serial I/O device. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or - software entity. This includes information about the class and - subclass that is used to classify the entity as well as an operation. - For progress codes, the operation is the current activity. - For error codes, it is the exception.For debug codes,it is not defined at this time. - @param Instance The enumeration of a hardware or software entity within - the system. A system may contain multiple entities that match a class/subclass - pairing. The instance differentiates between them. An instance of 0 indicates - that instance information is unavailable, not meaningful, or not relevant. - Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS Status code reported to serial I/O successfully. - -**/ -EFI_STATUS -SerialStatusCodeReportWorker ( - 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%08x:V%08x I%x", - CodeType, - Value, - Instance - ); - - 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%08x 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%08x:V%08x I%x\n\r", - CodeType, - Value, - Instance - ); - } - - // - // Call SerialPort Lib function to do print. - // - SerialPortWrite ((UINT8 *) Buffer, CharCount); - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.c b/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.c deleted file mode 100644 index 5b17df3862..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.c +++ /dev/null @@ -1,146 +0,0 @@ -/** @file - Status code PEIM which produces Status Code PPI. - - Copyright (c) 2006 - 2009, Intel 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 "StatusCodePei.h" - -EFI_PEI_PROGRESS_CODE_PPI mStatusCodePpi = { - ReportDispatcher - }; - -EFI_PEI_PPI_DESCRIPTOR mStatusCodePpiDescriptor = { - EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, - &gEfiPeiStatusCodePpiGuid, - &mStatusCodePpi - }; - -/** - Publishes an interface that allows PEIMs to report status codes. - - This function implements EFI_PEI_PROGRESS_CODE_PPI.ReportStatusCode(). - It publishes an interface that allows PEIMs to report status codes. - - @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or - software entity. This includes information about the class and - subclass that is used to classify the entity as well as an operation. - For progress codes, the operation is the current activity. - For error codes, it is the exception.For debug codes,it is not defined at this time. - @param Instance The enumeration of a hardware or software entity within - the system. A system may contain multiple entities that match a class/subclass - pairing. The instance differentiates between them. An instance of 0 indicates - that instance information is unavailable, not meaningful, or not relevant. - Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -EFIAPI -ReportDispatcher ( - 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 OPTIONAL, - IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL - ) -{ - if (FeaturePcdGet (PcdStatusCodeUseSerial)) { - SerialStatusCodeReportWorker ( - CodeType, - Value, - Instance, - CallerId, - Data - ); - } - if (FeaturePcdGet (PcdStatusCodeUseMemory)) { - MemoryStatusCodeReportWorker ( - CodeType, - Value, - Instance - ); - } - if (FeaturePcdGet (PcdStatusCodeUseOEM)) { - // - // Call OEM hook status code library API to report status code to OEM device - // - OemHookStatusCodeReport ( - CodeType, - Value, - Instance, - (EFI_GUID *)CallerId, - (EFI_STATUS_CODE_DATA *)Data - ); - } - - return EFI_SUCCESS; -} - -/** - Entry point of Status Code PEIM. - - This function is the entry point of this Status Code PEIM. - It initializes supported status code devices according to PCD settings, - and installs Status Code PPI. - - @param FileHandle Handle of the file being invoked. - @param PeiServices Describes the list of possible PEI Services. - - @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully. - -**/ -EFI_STATUS -EFIAPI -PeiStatusCodeDriverEntry ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN CONST EFI_PEI_SERVICES **PeiServices - ) -{ - EFI_STATUS Status; - - // - // Dispatch initialization request to sub-statuscode-devices. - // If enable UseSerial, then initialize serial port. - // if enable UseMemory, then initialize memory status code worker. - // if enable UseOEM, then initialize Oem status code. - // - if (FeaturePcdGet (PcdStatusCodeUseSerial)) { - Status = SerialPortInitialize(); - ASSERT_EFI_ERROR (Status); - } - if (FeaturePcdGet (PcdStatusCodeUseMemory)) { - Status = MemoryStatusCodeInitializeWorker (); - ASSERT_EFI_ERROR (Status); - } - if (FeaturePcdGet (PcdStatusCodeUseOEM)) { - Status = OemHookStatusCodeInitialize (); - ASSERT_EFI_ERROR (Status); - } - - // - // Install Status Code PPI. - // It serves the PEI Service ReportStatusCode. - // - Status = PeiServicesInstallPpi (&mStatusCodePpiDescriptor); - ASSERT_EFI_ERROR (Status); - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.h b/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.h deleted file mode 100644 index 75078d0ef4..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.h +++ /dev/null @@ -1,147 +0,0 @@ -/** @file - Internal include file for Status Code PEIM. - - Copyright (c) 2006 - 2009, Intel 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_STATUS_CODE_H__ -#define __PEI_STATUS_CODE_H__ - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - Convert status code value and extended data to readable ASCII string, send string to serial I/O device. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or - software entity. This includes information about the class and - subclass that is used to classify the entity as well as an operation. - For progress codes, the operation is the current activity. - For error codes, it is the exception.For debug codes,it is not defined at this time. - @param Instance The enumeration of a hardware or software entity within - the system. A system may contain multiple entities that match a class/subclass - pairing. The instance differentiates between them. An instance of 0 indicates - that instance information is unavailable, not meaningful, or not relevant. - Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS Status code reported to serial I/O successfully. - -**/ -EFI_STATUS -SerialStatusCodeReportWorker ( - 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 - ); - - -/** - Create the first memory status code GUID'ed HOB as initialization for memory status code worker. - - @retval EFI_SUCCESS The GUID'ed HOB is created successfully. - -**/ -EFI_STATUS -MemoryStatusCodeInitializeWorker ( - VOID - ); - -/** - Report status code into GUID'ed HOB. - - This function reports status code into GUID'ed HOB. If not all packets are full, then - write status code into available entry. Otherwise, create a new packet for it. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or - software entity. This includes information about the class and - subclass that is used to classify the entity as well as an operation. - For progress codes, the operation is the current activity. - For error codes, it is the exception.For debug codes,it is not defined at this time. - @param Instance The enumeration of a hardware or software entity within - the system. A system may contain multiple entities that match a class/subclass - pairing. The instance differentiates between them. An instance of 0 indicates - that instance information is unavailable, not meaningful, or not relevant. - Valid instance numbers start with 1. - - @retval EFI_SUCCESS The function always return EFI_SUCCESS. - -**/ -EFI_STATUS -MemoryStatusCodeReportWorker ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance - ); - -/** - Publishes an interface that allows PEIMs to report status codes. - - This function implements EFI_PEI_PROGRESS_CODE_PPI.ReportStatusCode(). - It publishes an interface that allows PEIMs to report status codes. - - @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or - software entity. This includes information about the class and - subclass that is used to classify the entity as well as an operation. - For progress codes, the operation is the current activity. - For error codes, it is the exception.For debug codes,it is not defined at this time. - @param Instance The enumeration of a hardware or software entity within - the system. A system may contain multiple entities that match a class/subclass - pairing. The instance differentiates between them. An instance of 0 indicates - that instance information is unavailable, not meaningful, or not relevant. - Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS The function completed successfully. - -**/ -EFI_STATUS -EFIAPI -ReportDispatcher ( - 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 OPTIONAL, - IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL - ); - -#endif - - diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf b/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf deleted file mode 100644 index 04cef4a2f4..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf +++ /dev/null @@ -1,78 +0,0 @@ -## @file -# Status code PEIM which produces Status Code PPI. -# -# 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 -# 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 = StatusCodePei - MODULE_UNI_FILE = StatusCodePei.uni - FILE_GUID = 1EC0F53A-FDE0-4576-8F25-7A1A410F58EB - MODULE_TYPE = PEIM - VERSION_STRING = 1.0 - ENTRY_POINT = PeiStatusCodeDriverEntry - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - StatusCodePei.c - StatusCodePei.h - MemoryStausCodeWorker.c - SerialStatusCodeWorker.c - - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - PeimEntryPoint - OemHookStatusCodeLib - PeiServicesLib - PcdLib - HobLib - SerialPortLib - ReportStatusCodeLib - PrintLib - DebugLib - BaseLib - - -[Guids] - gMemoryStatusCodeRecordGuid ## SOMETIMES_CONSUMES ## HOB - gEfiStatusCodeDataTypeStringGuid ## SOMETIMES_CONSUMES ## UNDEFINED # String Data Type - -[Ppis] - gEfiPeiStatusCodePpiGuid ## PRODUCES - - -[FeaturePcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseOEM ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES - - -[Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES - -[Depex] - TRUE - -[UserExtensions.TianoCore."ExtraFiles"] - StatusCodePeiExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.uni b/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.uni deleted file mode 100644 index 1e0b9edd0d..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePeiExtra.uni b/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePeiExtra.uni deleted file mode 100644 index 6385b4190e..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePeiExtra.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c deleted file mode 100644 index ffee2f9c2a..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c +++ /dev/null @@ -1,390 +0,0 @@ -/** @file - Data Hub status code worker. - - Copyright (c) 2006 - 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 "StatusCodeRuntimeDxe.h" - -// -// Initialize FIFO to cache records. -// -LIST_ENTRY mRecordsFifo = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsFifo); -LIST_ENTRY mRecordsBuffer = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsBuffer); -UINT32 mLogDataHubStatus = 0; -EFI_EVENT mLogDataHubEvent; -// -// Cache data hub protocol. -// -EFI_DATA_HUB_PROTOCOL *mDataHubProtocol = NULL; - - -/** - Retrieve one record of from free record buffer. This record is removed from - free record buffer. - - This function retrieves one record from free record buffer. - If the pool has been exhausted, then new memory would be allocated for it. - - @return Pointer to the free record. - NULL means failure to allocate new memeory for free record buffer. - -**/ -DATA_HUB_STATUS_CODE_DATA_RECORD * -AcquireRecordBuffer ( - VOID - ) -{ - DATAHUB_STATUSCODE_RECORD *Record; - EFI_TPL CurrentTpl; - LIST_ENTRY *Node; - UINT32 Index; - - CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - if (!IsListEmpty (&mRecordsBuffer)) { - // - // Strip one entry from free record buffer. - // - Node = GetFirstNode (&mRecordsBuffer); - RemoveEntryList (Node); - - Record = BASE_CR (Node, DATAHUB_STATUSCODE_RECORD, Node); - } else { - if (CurrentTpl > TPL_NOTIFY) { - // - // Memory management should work at <=TPL_NOTIFY - // - gBS->RestoreTPL (CurrentTpl); - return NULL; - } - - // - // If free record buffer is exhausted, then allocate 16 new records for it. - // - gBS->RestoreTPL (CurrentTpl); - Record = (DATAHUB_STATUSCODE_RECORD *) AllocateZeroPool (sizeof (DATAHUB_STATUSCODE_RECORD) * 16); - if (Record == NULL) { - return NULL; - } - - CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - // - // Here we only insert 15 new records to the free record buffer, for the first record - // will be returned immediately. - // - for (Index = 1; Index < 16; Index++) { - InsertTailList (&mRecordsBuffer, &Record[Index].Node); - } - } - - Record->Signature = DATAHUB_STATUS_CODE_SIGNATURE; - InsertTailList (&mRecordsFifo, &Record->Node); - - gBS->RestoreTPL (CurrentTpl); - - return (DATA_HUB_STATUS_CODE_DATA_RECORD *) (Record->Data); -} - - -/** - Retrieve one record from Records FIFO. The record would be removed from FIFO. - - @return Point to record, which is ready to be logged. - NULL means the FIFO of record is empty. - -**/ -DATA_HUB_STATUS_CODE_DATA_RECORD * -RetrieveRecord ( - VOID - ) -{ - DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData; - DATAHUB_STATUSCODE_RECORD *Record; - LIST_ENTRY *Node; - EFI_TPL CurrentTpl; - - RecordData = NULL; - - CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - if (!IsListEmpty (&mRecordsFifo)) { - Node = GetFirstNode (&mRecordsFifo); - Record = CR (Node, DATAHUB_STATUSCODE_RECORD, Node, DATAHUB_STATUS_CODE_SIGNATURE); - ASSERT (Record != NULL); - - RemoveEntryList (&Record->Node); - RecordData = (DATA_HUB_STATUS_CODE_DATA_RECORD *) Record->Data; - } - - gBS->RestoreTPL (CurrentTpl); - - return RecordData; -} - -/** - Release given record and return it to free record buffer. - - @param RecordData Pointer to the record to release. - -**/ -VOID -ReleaseRecord ( - DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData - ) -{ - DATAHUB_STATUSCODE_RECORD *Record; - EFI_TPL CurrentTpl; - - Record = CR (RecordData, DATAHUB_STATUSCODE_RECORD, Data[0], DATAHUB_STATUS_CODE_SIGNATURE); - ASSERT (Record != NULL); - - CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - - InsertTailList (&mRecordsBuffer, &Record->Node); - Record->Signature = 0; - - gBS->RestoreTPL (CurrentTpl); -} - -/** - Report status code into DataHub. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_DEVICE_ERROR Function is reentered. - @retval EFI_DEVICE_ERROR Function is called at runtime. - @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. - -**/ -EFI_STATUS -DataHubStatusCodeReportWorker ( - 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 - ) -{ - DATA_HUB_STATUS_CODE_DATA_RECORD *Record; - UINT32 ErrorLevel; - BASE_LIST Marker; - CHAR8 *Format; - UINTN CharCount; - EFI_STATUS Status; - - // - // Use atom operation to avoid the reentant of report. - // If current status is not zero, then the function is reentrancy. - // - if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 0) == 1) { - return EFI_DEVICE_ERROR; - } - - // - // See whether in runtime phase or not. - // - if (EfiAtRuntime ()) { - return EFI_DEVICE_ERROR; - } - - if (mDataHubProtocol == NULL) { - Status = DataHubStatusCodeInitializeWorker (); - if (EFI_ERROR (Status)) { - return Status; - } - } - - Record = AcquireRecordBuffer (); - if (Record == NULL) { - // - // There are no empty record buffer in private buffers - // - return EFI_OUT_OF_RESOURCES; - } - - // - // Construct Data Hub Extended Data - // - Record->CodeType = CodeType; - Record->Value = Value; - Record->Instance = Instance; - - if (CallerId != NULL) { - CopyMem (&Record->CallerId, CallerId, sizeof (EFI_GUID)); - } - - if (Data != NULL) { - if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { - CharCount = UnicodeBSPrintAsciiFormat ( - (CHAR16 *) (Record + 1), - EFI_STATUS_CODE_DATA_MAX_SIZE, - Format, - Marker - ); - // - // Change record data type to DebugType. - // - CopyGuid (&Record->Data.Type, &gEfiStatusCodeDataTypeDebugGuid); - Record->Data.HeaderSize = Data->HeaderSize; - Record->Data.Size = (UINT16) ((CharCount + 1) * sizeof (CHAR16)); - } else { - // - // Copy status code data header - // - CopyMem (&Record->Data, Data, sizeof (EFI_STATUS_CODE_DATA)); - - if (Data->Size > EFI_STATUS_CODE_DATA_MAX_SIZE) { - Record->Data.Size = EFI_STATUS_CODE_DATA_MAX_SIZE; - } - CopyMem ((VOID *) (Record + 1), Data + 1, Record->Data.Size); - } - } - - gBS->SignalEvent (mLogDataHubEvent); - - return EFI_SUCCESS; -} - - -/** - The Event handler which will be notified to log data in Data Hub. - - @param Event Instance of the EFI_EVENT to signal whenever data is - available to be logged in the system. - @param Context Context of the event. - -**/ -VOID -EFIAPI -LogDataHubEventCallBack ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - DATA_HUB_STATUS_CODE_DATA_RECORD *Record; - UINT32 Size; - UINT64 DataRecordClass; - - // - // Use atom operation to avoid the reentant of report. - // If current status is not zero, then the function is reentrancy. - // - if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 1) == 1) { - return; - } - - // - // Log DataRecord in Data Hub. - // Journal records fifo to find all record entry. - // - while (TRUE) { - // - // Retrieve record from record FIFO until no more record can be retrieved. - // - Record = RetrieveRecord (); - if (Record == NULL) { - break; - } - // - // Add in the size of the header we added. - // - Size = sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD) + (UINT32) Record->Data.Size; - - if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { - DataRecordClass = EFI_DATA_RECORD_CLASS_PROGRESS_CODE; - } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { - DataRecordClass = EFI_DATA_RECORD_CLASS_ERROR; - } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { - DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG; - } else { - // - // Should never get here. - // - DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG | - EFI_DATA_RECORD_CLASS_ERROR | - EFI_DATA_RECORD_CLASS_DATA | - EFI_DATA_RECORD_CLASS_PROGRESS_CODE; - } - - // - // Log DataRecord in Data Hub - // - mDataHubProtocol->LogData ( - mDataHubProtocol, - &gEfiDataHubStatusCodeRecordGuid, - &gEfiStatusCodeRuntimeProtocolGuid, - DataRecordClass, - Record, - Size - ); - - ReleaseRecord (Record); - } - - // - // Restore the nest status of report - // - InterlockedCompareExchange32 (&mLogDataHubStatus, 1, 0); -} - - -/** - Locate Data Hub Protocol and create event for logging data - as initialization for data hub status code worker. - - @retval EFI_SUCCESS Initialization is successful. - -**/ -EFI_STATUS -DataHubStatusCodeInitializeWorker ( - VOID - ) -{ - EFI_STATUS Status; - - Status = gBS->LocateProtocol ( - &gEfiDataHubProtocolGuid, - NULL, - (VOID **) &mDataHubProtocol - ); - if (EFI_ERROR (Status)) { - mDataHubProtocol = NULL; - return Status; - } - - // - // Create a Notify Event to log data in Data Hub - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - LogDataHubEventCallBack, - NULL, - &mLogDataHubEvent - ); - - ASSERT_EFI_ERROR (Status); - - return EFI_SUCCESS; -} - - diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c deleted file mode 100644 index 2a26e19e65..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c +++ /dev/null @@ -1,104 +0,0 @@ -/** @file - Runtime memory status code worker. - - Copyright (c) 2006 - 2009, Intel 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 "StatusCodeRuntimeDxe.h" - -RUNTIME_MEMORY_STATUSCODE_HEADER *mRtMemoryStatusCodeTable; - -/** - Initialize runtime memory status code table as initialization for runtime memory status code worker - - @retval EFI_SUCCESS Runtime memory status code table successfully initialized. - -**/ -EFI_STATUS -RtMemoryStatusCodeInitializeWorker ( - VOID - ) -{ - // - // Allocate runtime memory status code pool. - // - mRtMemoryStatusCodeTable = AllocateRuntimePool ( - sizeof (RUNTIME_MEMORY_STATUSCODE_HEADER) + - PcdGet16 (PcdStatusCodeMemorySize) * 1024 - ); - ASSERT (mRtMemoryStatusCodeTable != NULL); - - mRtMemoryStatusCodeTable->RecordIndex = 0; - mRtMemoryStatusCodeTable->NumberOfRecords = 0; - mRtMemoryStatusCodeTable->MaxRecordsNumber = - (PcdGet16 (PcdStatusCodeMemorySize) * 1024) / sizeof (MEMORY_STATUSCODE_RECORD); - - return EFI_SUCCESS; -} - - -/** - Report status code into runtime memory. If the runtime pool is full, roll back to the - first record and overwrite it. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - - @retval EFI_SUCCESS Status code successfully recorded in runtime memory status code table. - -**/ -EFI_STATUS -RtMemoryStatusCodeReportWorker ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance - ) -{ - MEMORY_STATUSCODE_RECORD *Record; - - // - // Locate current record buffer. - // - Record = (MEMORY_STATUSCODE_RECORD *) (mRtMemoryStatusCodeTable + 1); - Record = &Record[mRtMemoryStatusCodeTable->RecordIndex++]; - - // - // Save status code. - // - Record->CodeType = CodeType; - Record->Value = Value; - Record->Instance = Instance; - - // - // If record index equals to max record number, then wrap around record index to zero. - // - // The reader of status code should compare the number of records with max records number, - // If it is equal to or larger than the max number, then the wrap-around had happened, - // so the first record is pointed by record index. - // If it is less then max number, index of the first record is zero. - // - mRtMemoryStatusCodeTable->NumberOfRecords++; - if (mRtMemoryStatusCodeTable->RecordIndex == mRtMemoryStatusCodeTable->MaxRecordsNumber) { - // - // Wrap around record index. - // - mRtMemoryStatusCodeTable->RecordIndex = 0; - } - - return EFI_SUCCESS; -} - - - diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c deleted file mode 100644 index e1d02630e7..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c +++ /dev/null @@ -1,160 +0,0 @@ -/** @file - Serial I/O status code reporting worker. - - 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 - 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 "StatusCodeRuntimeDxe.h" - -/** - Convert status code value and extended data to readable ASCII string, send string to serial I/O device. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS Status code reported to serial I/O successfully. - @retval EFI_DEVICE_ERROR EFI serial device cannot work after ExitBootService() is called. - @retval EFI_DEVICE_ERROR EFI serial device cannot work with TPL higher than TPL_CALLBACK. - -**/ -EFI_STATUS -SerialStatusCodeReportWorker ( - 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 - ) -{ - 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\rDXE_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%08x:V%08x I%x", - CodeType, - Value, - Instance - ); - - 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%08x 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%08x:V%08x I%x\n\r", - CodeType, - Value, - Instance - ); - } - - // - // Call SerialPort Lib function to do print. - // - SerialPortWrite ((UINT8 *) Buffer, CharCount); - - return EFI_SUCCESS; -} - diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c deleted file mode 100644 index 6435e1f727..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c +++ /dev/null @@ -1,301 +0,0 @@ -/** @file - Status code driver for IA32/X64/EBC architecture. - - Copyright (c) 2006 - 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 "StatusCodeRuntimeDxe.h" - -EFI_EVENT mVirtualAddressChangeEvent = NULL; -EFI_HANDLE mHandle = NULL; - -// -// Declaration of status code protocol. -// -EFI_STATUS_CODE_PROTOCOL mEfiStatusCodeProtocol = { - ReportDispatcher -}; - -// -// Report operation nest status. -// If it is set, then the report operation has nested. -// -UINT32 mStatusCodeNestStatus = 0; - -/** - Entry point of DXE Status Code Driver. - - This function is the entry point of this DXE Status Code Driver. - It installs Status Code Runtime Protocol, and registers event for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. - - @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. - -**/ -EFI_STATUS -EFIAPI -StatusCodeRuntimeDxeEntry ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Dispatch initialization request to supported devices - // - InitializationDispatcherWorker (); - - // - // Install Status Code Runtime Protocol implementation as defined in PI Specification. - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &mHandle, - &gEfiStatusCodeRuntimeProtocolGuid, - &mEfiStatusCodeProtocol, - NULL - ); - ASSERT_EFI_ERROR (Status); - - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - VirtualAddressChangeCallBack, - NULL, - &gEfiEventVirtualAddressChangeGuid, - &mVirtualAddressChangeEvent - ); - ASSERT_EFI_ERROR (Status); - - return EFI_SUCCESS; -} - -/** - Report status code to all supported device. - - This function implements EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). - It calls into the workers which dispatches the platform specific listeners. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS The function completed successfully - @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. - -**/ -EFI_STATUS -EFIAPI -ReportDispatcher ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance, - IN EFI_GUID *CallerId OPTIONAL, - IN EFI_STATUS_CODE_DATA *Data OPTIONAL - ) -{ - // - // Use atom operation to avoid the reentant of report. - // If current status is not zero, then the function is reentrancy. - // - if (InterlockedCompareExchange32 (&mStatusCodeNestStatus, 0, 1) == 1) { - return EFI_DEVICE_ERROR; - } - - if (FeaturePcdGet (PcdStatusCodeUseSerial)) { - SerialStatusCodeReportWorker ( - CodeType, - Value, - Instance, - CallerId, - Data - ); - } - if (FeaturePcdGet (PcdStatusCodeUseMemory)) { - RtMemoryStatusCodeReportWorker ( - CodeType, - Value, - Instance - ); - } - if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { - DataHubStatusCodeReportWorker ( - CodeType, - Value, - Instance, - CallerId, - Data - ); - } - if (FeaturePcdGet (PcdStatusCodeUseOEM)) { - // - // Call OEM hook status code library API to report status code to OEM device - // - OemHookStatusCodeReport ( - CodeType, - Value, - Instance, - CallerId, - Data - ); - } - - // - // Restore the nest status of report - // - InterlockedCompareExchange32 (&mStatusCodeNestStatus, 1, 0); - - return EFI_SUCCESS; -} - - -/** - Virtual address change notification call back. It converts global pointer - to virtual address. - - @param Event Event whose notification function is being invoked. - @param Context Pointer to the notification function's context, which is - always zero in current implementation. - -**/ -VOID -EFIAPI -VirtualAddressChangeCallBack ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // Convert memory status code table to virtual address; - // - EfiConvertPointer ( - 0, - (VOID **) &mRtMemoryStatusCodeTable - ); -} - -/** - Dispatch initialization request to sub status code devices based on - customized feature flags. - -**/ -VOID -InitializationDispatcherWorker ( - VOID - ) -{ - EFI_PEI_HOB_POINTERS Hob; - EFI_STATUS Status; - MEMORY_STATUSCODE_PACKET_HEADER *PacketHeader; - MEMORY_STATUSCODE_RECORD *Record; - UINTN Index; - UINTN MaxRecordNumber; - - // - // If enable UseSerial, then initialize serial port. - // if enable UseRuntimeMemory, then initialize runtime memory status code worker. - // if enable UseDataHub, then initialize data hub status code worker. - // - if (FeaturePcdGet (PcdStatusCodeUseSerial)) { - // - // Call Serial Port Lib API to initialize serial port. - // - Status = SerialPortInitialize (); - ASSERT_EFI_ERROR (Status); - } - if (FeaturePcdGet (PcdStatusCodeUseMemory)) { - Status = RtMemoryStatusCodeInitializeWorker (); - ASSERT_EFI_ERROR (Status); - } - if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { - DataHubStatusCodeInitializeWorker (); - } - if (FeaturePcdGet (PcdStatusCodeUseOEM)) { - // - // Call OEM hook status code library API to initialize OEM device for status code. - // - Status = OemHookStatusCodeInitialize (); - ASSERT_EFI_ERROR (Status); - } - - // - // Replay Status code which saved in GUID'ed HOB to all supported devices. - // - if (FeaturePcdGet (PcdStatusCodeReplayIn)) { - // - // Journal GUID'ed HOBs to find all record entry, if found, - // then output record to support replay device. - // - Hob.Raw = GetFirstGuidHob (&gMemoryStatusCodeRecordGuid); - if (Hob.Raw != NULL) { - PacketHeader = (MEMORY_STATUSCODE_PACKET_HEADER *) GET_GUID_HOB_DATA (Hob.Guid); - Record = (MEMORY_STATUSCODE_RECORD *) (PacketHeader + 1); - MaxRecordNumber = (UINTN) PacketHeader->RecordIndex; - if (PacketHeader->PacketIndex > 0) { - // - // Record has been wrapped around. So, record number has arrived at max number. - // - MaxRecordNumber = (UINTN) PacketHeader->MaxRecordsNumber; - } - for (Index = 0; Index < MaxRecordNumber; Index++) { - // - // Dispatch records to devices based on feature flag. - // - if (FeaturePcdGet (PcdStatusCodeUseSerial)) { - SerialStatusCodeReportWorker ( - Record[Index].CodeType, - Record[Index].Value, - Record[Index].Instance, - NULL, - NULL - ); - } - if (FeaturePcdGet (PcdStatusCodeUseMemory)) { - RtMemoryStatusCodeReportWorker ( - Record[Index].CodeType, - Record[Index].Value, - Record[Index].Instance - ); - } - if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { - DataHubStatusCodeReportWorker ( - Record[Index].CodeType, - Record[Index].Value, - Record[Index].Instance, - NULL, - NULL - ); - } - if (FeaturePcdGet (PcdStatusCodeUseOEM)) { - // - // Call OEM hook status code library API to report status code to OEM device - // - OemHookStatusCodeReport ( - Record[Index].CodeType, - Record[Index].Value, - Record[Index].Instance, - NULL, - NULL - ); - } - } - } - } -} diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h deleted file mode 100644 index 9d0ed19c4a..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h +++ /dev/null @@ -1,240 +0,0 @@ -/** @file - Internal include file of Status Code Runtime DXE Driver. - - Copyright (c) 2006 - 2009, Intel 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 __STATUS_CODE_RUNTIME_DXE_H__ -#define __STATUS_CODE_RUNTIME_DXE_H__ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Data hub worker definition -// -#define DATAHUB_STATUS_CODE_SIGNATURE SIGNATURE_32 ('B', 'D', 'H', 'S') - -typedef struct { - UINTN Signature; - LIST_ENTRY Node; - UINT8 Data[sizeof(DATA_HUB_STATUS_CODE_DATA_RECORD) + EFI_STATUS_CODE_DATA_MAX_SIZE]; -} DATAHUB_STATUSCODE_RECORD; - - -// -// Runtime memory status code worker definition -// -typedef struct { - UINT32 RecordIndex; - UINT32 NumberOfRecords; - UINT32 MaxRecordsNumber; -} RUNTIME_MEMORY_STATUSCODE_HEADER; - -extern RUNTIME_MEMORY_STATUSCODE_HEADER *mRtMemoryStatusCodeTable; - -/** - Report status code to all supported device. - - This function implements EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). - It calls into the workers which dispatches the platform specific listeners. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS The function completed successfully - @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. - -**/ -EFI_STATUS -EFIAPI -ReportDispatcher ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance, - IN EFI_GUID *CallerId OPTIONAL, - IN EFI_STATUS_CODE_DATA *Data OPTIONAL - ); - -/** - Dispatch initialization request to sub status code devices based on - customized feature flags. - -**/ -VOID -InitializationDispatcherWorker ( - VOID - ); - - -/** - Locates Serial I/O Protocol as initialization for serial status code worker. - - @retval EFI_SUCCESS Serial I/O Protocol is successfully located. - -**/ -EFI_STATUS -EfiSerialStatusCodeInitializeWorker ( - VOID - ); - - -/** - Convert status code value and extended data to readable ASCII string, send string to serial I/O device. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS Status code reported to serial I/O successfully. - @retval EFI_DEVICE_ERROR EFI serial device cannot work after ExitBootService() is called. - @retval EFI_DEVICE_ERROR EFI serial device cannot work with TPL higher than TPL_CALLBACK. - -**/ -EFI_STATUS -SerialStatusCodeReportWorker ( - 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 - ); - -/** - Initialize runtime memory status code table as initialization for runtime memory status code worker - - @retval EFI_SUCCESS Runtime memory status code table successfully initialized. - -**/ -EFI_STATUS -RtMemoryStatusCodeInitializeWorker ( - VOID - ); - -/** - Report status code into runtime memory. If the runtime pool is full, roll back to the - first record and overwrite it. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - - @retval EFI_SUCCESS Status code successfully recorded in runtime memory status code table. - -**/ -EFI_STATUS -RtMemoryStatusCodeReportWorker ( - IN EFI_STATUS_CODE_TYPE CodeType, - IN EFI_STATUS_CODE_VALUE Value, - IN UINT32 Instance - ); - -/** - Locate Data Hub Protocol and create event for logging data - as initialization for data hub status code worker. - - @retval EFI_SUCCESS Initialization is successful. - -**/ -EFI_STATUS -DataHubStatusCodeInitializeWorker ( - VOID - ); - - -/** - Report status code into DataHub. - - @param CodeType Indicates the type of status code being reported. - @param Value Describes the current status of a hardware or software entity. - This included information about the class and subclass that is used to - classify the entity as well as an operation. - @param Instance The enumeration of a hardware or software entity within - the system. Valid instance numbers start with 1. - @param CallerId This optional parameter may be used to identify the caller. - This parameter allows the status code driver to apply different rules to - different callers. - @param Data This optional parameter may be used to pass additional data. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_DEVICE_ERROR Function is reentered. - @retval EFI_DEVICE_ERROR Function is called at runtime. - @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. - -**/ -EFI_STATUS -DataHubStatusCodeReportWorker ( - 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 - ); - - -/** - Virtual address change notification call back. It converts global pointer - to virtual address. - - @param Event Event whose notification function is being invoked. - @param Context Pointer to the notification function's context, which is - always zero in current implementation. - -**/ -VOID -EFIAPI -VirtualAddressChangeCallBack ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -#endif diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf deleted file mode 100644 index d7c35021a2..0000000000 --- a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf +++ /dev/null @@ -1,88 +0,0 @@ -## @file -# Status Code Runtime Dxe driver produces Status Code Runtime 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 -# 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 = StatusCodeRuntimeDxe - MODULE_UNI_FILE = StatusCodeRuntimeDxe.uni - FILE_GUID = FEDE0A1B-BCA2-4A9F-BB2B-D9FD7DEC2E9F - MODULE_TYPE = DXE_RUNTIME_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = StatusCodeRuntimeDxeEntry - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 EBC -# -# VIRTUAL_ADDRESS_MAP_CALLBACK = VirtualAddressChangeCallBack -# - -[Sources] - SerialStatusCodeWorker.c - RtMemoryStatusCodeWorker.c - DataHubStatusCodeWorker.c - StatusCodeRuntimeDxe.h - StatusCodeRuntimeDxe.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - -[LibraryClasses] - OemHookStatusCodeLib - SerialPortLib - UefiRuntimeLib - MemoryAllocationLib - UefiLib - UefiBootServicesTableLib - UefiDriverEntryPoint - HobLib - PcdLib - PrintLib - ReportStatusCodeLib - DebugLib - BaseMemoryLib - BaseLib - SynchronizationLib - - -[Guids] - gEfiDataHubStatusCodeRecordGuid ## SOMETIMES_PRODUCES ## UNDEFINED # DataRecord Guid - gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_PRODUCES ## UNDEFINED # Record data type - gMemoryStatusCodeRecordGuid ## SOMETIMES_CONSUMES ## HOB - gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event - gEfiStatusCodeDataTypeStringGuid ## SOMETIMES_CONSUMES ## UNDEFINED - -[Protocols] - gEfiStatusCodeRuntimeProtocolGuid ## PRODUCES - gEfiDataHubProtocolGuid ## SOMETIMES_CONSUMES # Needed if Data Hub is supported for status code - -[FeaturePcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeReplayIn ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseOEM ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES - -[Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize |128| gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES - -[Depex] - TRUE -[UserExtensions.TianoCore."ExtraFiles"] - StatusCodeRuntimeDxeExtra.uni diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni deleted file mode 100644 index 963a16e9e6..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.uni and /dev/null differ diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxeExtra.uni b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxeExtra.uni deleted file mode 100644 index ae409adbed..0000000000 Binary files a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxeExtra.uni and /dev/null differ -- cgit v1.2.3